This is the first of (hopefully) many entries in a series I like to call You don't need...
What do we need for tab navigation?
To do tabs we need to do 2 things:
- Track the current tab index
- Show and hide tab content based on the index
And CSS can do both!
CSS has a class of selectors called a sibling selector (
+ for immediately after and
~ for somewhere after) which will select a sibling element (one that is on the same "level" and shares their containing element).
CSS also has
nth pseudo selectors, specifically the
:nth-of-type(i) selector which will select the
ith element of whatever selector you put before it.
The CSS principal you need to understand is the
:checked pseudo selector which applies to
input elements that have been checked (like a radio button or check box
Getting it done
Track the current tab index
input element state with
:checked as mentioned above so we can detect this in CSS with
i is the index of the tab selected. We can make a new rule for every tab but it's kind of useless without some action based on the index
Show and hide tab content based on selected index
For starters, the default state of a tab is hidden so I think
display: none on our tab content is obvious. And showing it is as simple as
display: block. The trick is showing the
ith content when the
ith tab is selected. For that we use the
~ (general sibling) selector. As long as your tabs are of one type (probably a
label element for each of your hidden
input state-managing elements) and your content is another type (a
div maybe?) then you can group them as different "types" and use a rule like
input.tab:checked:nth-of-type(1)~div.tab-content:nth-of-type(1) to select the first tab content element whenever the first tab is selected
A working example
You can also change the input type to
checkbox for toggles JSFiddle link
noscript users still have a good experience. At the very least, I want them to be able to sucessfuly use the site in a limited form, even if the optional frills I throw in do not function
Top comments (3)
Or you could just use CSS's
:targetselector. Not only is this a simpler implementation, but it also supports "deep linking" via the hashed url value.
Edit: Downside is there doesn't seem to be a way to apply an active state to the tab. So with either approach we can only meet 2/3 of the requirements to make usable tabs. So, once again, this is why we end up turning to JS.
I like using :target for routing (spoilers for the next article! 🤫) but I also don't have a good way of doing active states nicely.
I was thinking of showing it being done with a bunch of copies of tabs where 1 is manually marked as active with a class so the Tab and Tab Content is swapped based on active state. I decided not to because it's a lot of repetition.
Im doing websites for ages, i mean, 20+ years. And i've never met anyone, who has scripts disabled. I understand the idea, but this should not be the motivation. I am sure there are some users who do not allow script to run, but motivation should be size of the page, speed on low end devices, something you can measure and verify, if time spent on such solution was worth it or not.