Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Building Linkable Tabs with only CSS
Nathan Kallman
Nathan Kallman

Posted on • Edited on • Originally published atkallmanation.com

     

Building Linkable Tabs with only CSS

The venerable Tab. Some of us have too many on our browsers... Before using JavaScript to build more, consider what just HTML and CSS can do.

There's actually many ways to build tabs with just HTML and CSS (we'll explore an alternative in another post; follow me to be notified when that comes out). In this article, we're going to use the:target selector.

The goals

  1. Build a classic tab system
  2. Make the current tab stay the current tab on refresh
  3. Make the tabs linkable
  4. Require 0 JavaScript

The results

The strategy

  1. Make a section for each tab with a unique id
  2. Make the tab navigation be links to fragments corresponding to each unique id
  3. Use the:target selector to show the current tab content while hiding the others

How to get there

The CSS selectors used

  1. Psuedo-class

    a.:target - selects the element with the uniqueid corresponding to the URI'sfragment
    b.:last-child - selects the element that is the last child of its parent

  2. General sibling combinator~ - combines that selector on the right-hand side to limit to only elements that are also subsequent siblings of elements selected by the left-hand side

  3. Class selector. - selects all elements with the given class name

Important CSS styles used

  1. display
    a.block oranything besidesnone to render the tab content
    b.none - removes the element from having any effect on the rendered page

  2. color /border-color / your-fancy-tab-styling-here -whatever styles should change on the tabs to indicate being active/inactive for the particular design.

Starting out: the HTML

Our tabs will besections with a class oftab (for selecting) as siblings of one another. These tabs depend on theURI fragment; if you intend to show a default tab if there is no fragment (I do), it is important to order the tabs in the HTML so that the default tab appears last (I want the first tab to be default open, so I place my tabs in reverse order).

Inside each tab, the first element will be our navigation. Unfortunately, to style the tab navigation requires duplicating the navigation in each tab. This could be avoided, but would require other compromises, which we will discuss later.

<sectionclass="tab"id="last-tab"><nav><ahref="#first-tab">First Tab</a><ahref="#last-tab"class="active">Last Tab</a></nav><p>Last tab content</p></section><sectionclass="tab"id="first-tab"><nav><ahref="#first-tab"class="active">First Tab</a><ahref="#last-tab">Last Tab</a></nav><p>First tab content</p></section>
Enter fullscreen modeExit fullscreen mode

Show the targeted tab

Start off by hiding all the tabs:

.tab{display:none;}
Enter fullscreen modeExit fullscreen mode

Now show the one tab whoseid matches the URI fragment using the:target selector:

.tab{display:none;}.tab:target{display:block;}
Enter fullscreen modeExit fullscreen mode

Let's also go ahead and throw in the style to show which tab is "active":

.active{color:teal;border-bottom-color:teal;}.tab{display:none;}.tab:target{display:block;}
Enter fullscreen modeExit fullscreen mode

And we now have a totally functioning tab system that is:

  1. linkable
  2. survives page refresh
  3. uses only CSS!

But, visiting the page without a current fragment will result innone of the tabs showing (until one is clicked)... let's fix that.

Show the default tab

We placed our default tab as the last in the HTML, so let's use:last-child:

.tab:last-child{display:block;}
Enter fullscreen modeExit fullscreen mode

At this point, you are probably wondering why we didn't just order them normally and use:first-child?

We can'tonly display the default tab. We also need tohide the default tab ifany other tab has been targeted.

So how do we do that?

With thegeneral sibling combinator!

Take a moment to read the description of what~ does. A key thing to understand is that it only selectssubsequent siblings. That is: it only selectsdownward through the HTML; not upward to previous elements.

That is why we have to place our default tab last. We want to select and hide the default tab if it is a sibling to another tab that is currently targeted by the fragment. Since~ only works downward, our default has to be last.

.tab:last-child{display:block;}.tab:target~.tab:last-child{display:none;}
Enter fullscreen modeExit fullscreen mode

Put it all together (and throw in some additional layout) and we have a quite nice, linkable, tab system:

.active{color:teal;border-bottom-color:teal;}.tab{display:none;}.tab:target{display:block;}.tab:last-child{display:block;}.tab:target~.tab:last-child{display:none;}
Enter fullscreen modeExit fullscreen mode

Compromises

I chose to duplicate my navigation within each tab in order to allow styling of the active tab.

This may not be the right decision for you. There are other options:

  1. Do not style the link to the tab. This allows moving them outside and above to deduplicate the HTML.
  2. Specifically target each tab by unique classes in CSS. This moves duplication from HTML into CSS.
  3. Use fixed height tab content. Mix the tab content and navigation links in a way they can be selected with theadjacent sibling combinator,+. Absolutely position the tab content into the reserved area.

and I am sure there are more...

And, of course: use a little JavaScript. When needed it can be the right tool. This is just an experiment to make you think about when it actually is the "right" tool, or just a hammer beating your design into submission.

Wrapping up

Thanks for reading! I like sharing and finding things like this where common web design patterns can be done without a massive JavaScript library or framework bogging the page down. Give me some suggestions below on patterns you'd like to see me break-down in CSS/HTML-only for this series.

Follow me for future installments in this series, including tabs done using radio buttons instead.

Or check out some of myother articles; like my series on basics of writing your own articles here on DEV:

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Husband; Father; Software Engineer; Gamer; Tinkerer; Writing about code on DEV.
  • Location
    Columbus, OH
  • Education
    B.S. Computer Engineering
  • Work
    Engineering Manager at Root Insurance
  • Joined

More fromNathan Kallman

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp