CSS Tabs are really great at displaying associated information in one easy-to-navigate place. They essentially look like tabbed dividers that you would see in a recipe box or a binder. Here are some examples of websites using tabbed navigation:
- Southwest Airlines uses tabbed navigation to let the user navigate between checking in for a flight, booking a flight or adding a hotel to their reservation.
- Enterprise uses tabs for navigation to let the user decide between renting or buying, and also learning about their other services.
As you observe these two sites, think about what the pros are of using such a UI component on the sites. What problems does it solve? What type of information would tabbed navigation be a good implementation for?
When you need to reach for a UI structure that organizes text or information into meaningful components and displays them on the screen without taking up too much space, tabbed navigation is a wise choice. We will talk about tabbed navigation more in-depth as we get into using JavaScript, jQuery and/or Bootstrap, but there is also an implementation we could use that just requires HTML and pure CSS. Let’s take a look at the setup:
Setup your HTML:
Go ahead and set up your boilerplate HTML with a container inside the body that will serve as our main container for the project. You can call it whatever you’d like in the class attribute, but I will call it class=”tabs”
. So far, your HTML should look like this:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CSS Tabs</title> <style> /* No CSS to display yet */ </style> </head> <body> <div class="tabs"></div> <body> </html>
Inside the “tabs” <div>
, we will insert another four more <div>s and call each with a class of tab
. This represents each of the four tabs that we will be writing up today. It will contain our input, tab labels and tab content. Let’s make empty containers for all of those:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CSS Tabs</title> <style> /* No CSS to display yet */ </style> </head> <body> <div class="tabs"> <div class="tab"> /* THIS IS OUR PLAN IN ACTION*/ /*input */ <input type="radio" id="tab-1" name="tab-group-1" checked/> /*label for input */ <label for="tab-1">Label 1</label> /* content */ <div class="content">Our content will go here</div> </div> <div class="tab"> <input type="radio" id="tab-2" name="tab-group-1" checked/> <label for="tab-2">Label 2</label> <div class="content gryffindor">Our content will go here</div> </div> <div class="tab">Try these two on your own! Follow the same convention as above for your class names and ids - I am using a HP theme, but name them whatever you'd like!</div> <div class="tab"></div> </div> <body> </html>
Inside the content class name will be our content. You can use whatever content you’d like, but it’s standard practice to use associated content on one tab.
Time to Start CSS:
When it comes to writing the CSS, start on the biggest container and work your way to the smallest container. Here is the minimum we need to do to get it to work:
- Set a wild card selector to a box-sizing: border-box.
- On the main container, we need to have the display property set to flex and have the position set to relative. Display: flex allows the tabs to lay next to each other in a row and the relative position basically acts as a boundary or fence that contains the content of the tab.
At this point you will see what looks to be four blocks of text with a radio button and some content. Next we have to figure out a way to show the checked block and hide the other blocks.
- On the .tab container, we’ll set up the styling for the label:
- 1px solid border in any color you wish.
- Padding: 5px, 10px – will add some space around the label text
- Border-radius 10px, 10px, 0px, 0px – this will make the label look more like a traditional tab.
If you check your work now, you will see that the labels have the circular radio buttons to the left of them. So it looks more like a traditional tab, but to still keep the checked attribute of the button, we need to hide the circular portion of the radio button.
- To actually select the button, we use .tab [type=’radio’]. To hide it, we set display to none.
Next, we need to tackle the actual content so that it only shows one tab at a time.
- Select the content div and then set the position to absolute. When the absolute position is set, the div can be set anywhere inside the relative parent. Using top, right, left and bottom, you can set the content where you want to inside the parent div. In this case, set the left and right properties to 0. We also want to create a border and set a background color to a non-transparent color.
- Setting the z-index of the selected tab will put that tab’s panel on top. To do so, select the checked button and its content. To do this we use [type=’radio’]:checked ~ label ~ .content. The “~ “ in between the elements in CSS tells us that we want the content class that occurs after a label element that occurs after a checked radio button.
- To show which tab is active, set [type=’radio’]:checked ~ label to a different background color.
Now when the user clicks on each of the tabs, they should be able to successfully go from one to the other without seeing the content of the other panels. This is the minimum you need to get the tabbed navigation to work. Try playing around with the CSS to change up the styling! A working implementation is coded out below:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CSS Tabs</title> <style> * { box-sizing: border-box; } body { font-family: 'Roboto'; } .tabs { max-width: 700px; min-height: 100px; margin: 25px 0; width: 100%; display: flex; /* allows for tabs to be next to each other */ position: relative; /* relative here contains the width of the content */ } .tab label { padding: 5px 10px; border: 1px solid #ccc; cursor: pointer; border-radius: 10px 10px 0 0; } .tab [type='radio'] { display: none; /* this makes the radio buttons disappear - we are only keeping track if they are checked or not */ } h3 { margin: 10px 40px; } ul { list-style-type: none; } .content { padding: 10px; border-radius: 0px 10px 10px 10px; position: absolute; left: 0; right: 0; background: white; border: 1px solid #ccc; /* the left and right at 0 help the tabs to overlap each other */ } /* This allows the selected tab to be on top */ [type='radio']:checked ~ label ~ .content { z-index: 1; } [type="radio"]:checked ~ label { background: lightgrey; } /* color scheme for tabs */ [type='radio']:checked ~ #gryffindor { background: #ec9086; color: #241806; } [type='radio']:checked ~ #ravenclaw { background: #3054ca; color: #241806; } [type='radio']:checked ~ #slytherin { background: #089714; color: #252525; } [type='radio']:checked ~ #hufflepuff { background: #f0d695; color: #372e29; } [type='radio'] ~ #slytherin { background: #033807; color: #aaaaaa; } [type='radio'] ~ #hufflepuff { background: #f0c75e; color: #372e29; } [type='radio'] ~ #gryffindor { background: #9c1203; color: #e3a000; } [type='radio'] ~ #ravenclaw { background: #0e1a40; color: #946b2d; } .gryffindor { background: #9c1203; color: #e3a000; } .slytherin { background: #033807; color: #aaaaaa; } .hufflepuff { background: #f0c75e; color: #372e29; } .ravenclaw { background: #0e1a40; color: #946b2d; } </style> </head> <body> <div class="tabs"> <div class="tab"> <input type="radio" id="tab-1" name="tab-group-1" checked/> <label id="gryffindor" for="tab-1">Gryffindor</label> <div class="content gryffindor"> <h3>HP Chars in Gryffindor</h3> <ul class="gryffindor-students"> <li>Harry Potter</li> <li>Hermione Grainger</li> <li>Ron Weasley</li> <li>Albus Dumbledore</li> <li>Katie Bell</li> <li>Neville Longbottom</li> </ul> </div> </div> <div class="tab"> <input type="radio" id="tab-2" name="tab-group-1"/> <label id="slytherin" for="tab-2">Slytherin</label> <div class="content slytherin"> <h3>HP Chars in Slytherin</h3> <ul class="slytherin-students"> <li>Draco Malfoy</li> <li>Narcissa Black</li> <li>Lucius Malfoy</li> <li>Severus Snape</li> <li>Tom Riddle</li> <li>Dolores Umbridge</li> </ul> </div> </div> <div class="tab"> <input type="radio" id="tab-3" name="tab-group-1"/> <label for="tab-3" id="ravenclaw">Ravenclaw</label> <div class="content ravenclaw"> <h3>HP Chars in Ravenclaw</h3> <ul class="ravenclaw-students"> <li>Lisa Turpin</li> <li>Luna Lovegood</li> <li>Gilderoy Lockhart</li> <li>Garrick Ollivander</li> <li>Padma Patil</li> <li>Sybil Trelawney</li> </ul> </div> </div> <div class="tab"> <input type="radio" id="tab-4" name="tab-group-1"> <label for="tab-4" id="hufflepuff">Hufflepuff</label> <div class="content hufflepuff"> <h3>HP Chars in Hufflepuff</h3> <ul class="hufflepuff-students"> <li>Cedric Diggory</li> <li>Newton Scamander</li> <li>Nymphadora Tonks</li> <li>Pomona Sprout</li> <li>Susan Bones</li> <li>Teddy Lupin</li> </ul> </div> </div> </div> </body> </html>
About us: Career Karma is a platform designed to help job seekers find, research, and connect with job training programs to advance their careers. Learn about the CK publication.