Tabbed interface
Creating a tabbed interface without JavaScrpt
Years ago, I created a no-js solution for a tabbed interface, but the drawback was you needed to define the height of the enclosing element. This solution uses CSS Grid instead of absolute positioning, and therefor is a lot more flexible.
This is tab 1. It has a small amount of text, and nothing much else.
Lorem ipsum dolor sit amet eu ac convallis ac fermentum. Aliquet pellentesque scelerisque tellus faucibus iaculis non do. Do lacus etiam consequat at feugiat hendrerit fusce fringilla ultricies fusce risus luctus.
This is tab 2. There's a lot more text here, to show that the size of the tab container will expand and be responsive.
Lorem ipsum dolor sit aromatic blue iced ut panna plunger ut con foam. Pumpkin go wings french mug barista plunger con roast shop extraction. Mazagran java cinnamon luwak mocha cappuccino galão espresso dripper foam café qui lungo wings. Press filter trifecta caramelization press decaffeinated a trade id con acerbic. Caramelization decaffeinated crema french single panna skinny aromatic instant.
Blue a press spoon go grinder shop cultivar. Caffeine extra sweet robusta breve carajillo at dripper. Organic breve grinder eu shot wings id trifecta aged luwak java fair. Decaffeinated wings siphon id caramelization steamed java grounds chicory espresso cappuccino. Sweet au as shop spice filter barista sweet acerbic white shot sugar spice americano.
Tab 3 has a couple sentences, too.
Lorem ipsum dolor sit roll bonbon halvah tiramisu plum marzipan jujubes bears chocolate. Cheesecake wafer tart pie chupa drops roll danish bar gummies macaroon bar bears. Cream roll caramels pie tootsie sweet tootsie macaroon cupcake. Bonbon cake brownie soufflé lemon cake drops toffee muffin ice roll snaps tart.
Just like the previous version, this uses radio buttons as the trigger. Since the browser already knows how to switch a button on or off, and is aware of the checked/unchecked state of each button, then there's no need to have a JavaScript listener for clicks on each tab. Instead, the radio buttons are visually hidden, and the labels are what trigger the radio button selection.
<div class="tab-container">
<input type="radio" name="tabs" id="tab_1" class="tab" checked>
<label for="tab_1" class="tab-label">Tab 1</label>
<div class="tab-content">
<!-- tab 1 content here -->
</div>
<input type="radio" name="tabs" id="tab_2" class="tab" checked>
<label for="tab_2" class="tab-label">Tab 2</label>
<div class="tab-content">
<!-- tab 2 content here -->
</div>
<input type="radio" name="tabs" id="tab_3" class="tab" checked>
<label for="tab_3" class="tab-label">Tab 2</label>
<div class="tab-content">
<!-- tab 3 content here -->
</div>
</div>
.tab-container {
display: grid;
grid-template-rows: 2em 1px 1fr;
}
.tab {
display: none;
}
.tab-content {
background: white;
display: none;
padding: 12px;
grid-column: 1 / 5;
grid-row: 2 / 4;
}
.tab-label:nth-of-type(1) { grid-column: 1 / 2}
.tab-label:nth-of-type(2) { grid-column: 2 / 3}
.tab-label:nth-of-type(3) { grid-column: 3 / 4}
.tab-label {
display: block;
padding: 0 1em;
line-height: 2em;
border: 1px solid #ccc;
border-bottom: none;
background: #f5f5f5;
color: #666;
position: relative;
grid-row: 1 / 2;
}
.tab:checked + .tab-label {
color: black;
background: white;
grid-row: 1 / 3;
}
.tab:checked + .tab-label + .tab-content {
display: block;
border: 1px solid #ccc;
}
I am defining 3 grid row tracks, grid-template-rows: 2em 1px 1fr;, and letting the browser implicitly create the grid columns. The 1px second track is used to create the illusion of the active tab being in front of the others.
This is set up for 3 tabs. If you need to have more tabs, then just increase the number of grid column tracks on line 14 grid-column: 1 / 5 by 2 more than the number of tabs you need. In addition, you'll need to add more .tab-label:nth-of-type(n) selectors, one for each tab.
This solution is fluid, but not exactly responsive. At some point, the label titles will wrap to the next line, and the tap targets of each tab might get too small for a mobile screen. But since everything is CSS, it's pretty easy to imagine a different solution on mobile. For instance, just remove display: grid on .tab-container element and display: none on the .tab-content div, and let the content flow semantically.