How to build custom tabs component with HTML and CSS without JavaScript #1

Today we will talk about the tabs component. This is one of the popular ways to present information, which allows you to group content and place relevant information in the same place on the screen.

TL;DR: The result is a simple tabs component that works without JavaScript: full markup with styles in a CodePen.

Markup preparation

The tabs will always be placed above the content and act as navigation, so we wrap them in a header block and a nav navigation block. The place for the content will be allocated with the section element, and the content of each tab will be located inside the article.

<section class="container">

    <header>
        <nav class="tab-nav-wrap">
            <a class="tab-nav">Tab 1</a>
            <a class="tab-nav">Tab 2</a>
            <a class="tab-nav">Tab 3</a>
        </nav>
    </header>

    <section class="tab-content-wrap">
        <article class="tab-content">
            Tab 1 content
        </article>
        <article class="tab-content">
            Tab 2 content
        </article>
        <article class="tab-content">
            Tab 3 content
        </article>
    </section>

</section>
Tab 1 content
Tab 2 content
Tab 3 content
component preview

Binding elements

To bind the links and their respective tabs, we’ll use the href attributes on the anchors and the id attributes on the article by assigning them the appropriate values. So, by clicking on each anchor, the browser will send us to the corresponding tag with the identifier specified in the href.

<section class="container">

    <header>
        <nav class="tab-nav-wrap">
            <a class="tab-nav"
                href="#tab1">Tab 1</a>
            <!-- ... -->
        </nav>
    </header>

    <section class="tab-content-wrap">
        <article class="tab-content"
            id="tab1">
            Tab 1 content
        </article>
        <!-- ... -->
    </section>

</section>
Tab 1 content
Tab 2 content
Tab 3 content
component preview

Styles

Let’s start styling the components. At first, we need to hide all elements with the .tag-article class, and arrange the tabs in a convenient order. In my case, I used flexbox for tabs. Don’t forget to add padding to the tabs to make them easier to hit. We will also add styles to the :hover and :focus elements for the <a> elements for accessibility, so that the user can distinguish when he hovered over the area of ​​our “button” or highlighted it with the focus using the tab.

.tab {
    &-nav {
        &-wrap {
            display: flex;
            flex-direction: row;
            align-items: center;

            & > * + *  {
                margin-left: 10px;
            }
        }
    }

    &-content {
        display: none;
        visibility: hidden;
        opacity: 0;

        &-wrap {
            width: 100%;
            padding: 20px 40px;
            border: 2px solid black;
            border-radius: 0 8px 8px 8px;
        }
    }
}
Tab 1 content
Tab 2 content
Tab 3 content
component preview

To make sure that when a link (anchor) is clicked, the corresponding content appears on the page, we add a :target pseudo-element to the article, which will select the article with the corresponding id, which the link leads to and which appears in the address bar. It is worth noting here that if you want the section to not be empty at the beginning, pass in the URL the id of the article that you want to see when the page loads, for example https://my.site/ex#ample.

.tab {
    &-content {
        &:target {
            display: block;
            visibility: visible;
            opacity: 1;
        }
    }
}
Tab 1 content
Tab 2 content
Tab 3 content
component preview

Let’s add a small animation of the appearance of the content and disable it if the user wants to see less animation in their browser using the prefers-reduced-motion: reduce media query.

.tab {
    &-content {
        display: none;
        visibility: hidden;
        opacity: 0;

        &:target {
            display: block;
            visibility: visible;
            opacity: 1;

            animation-name: show;
            animation-duration: 0.3s;

            @media (prefers-reduced-motion: reduce) {
                animation: unset;
            }
        }
    }
}

@keyframes show {
    from {
        visibility: visible;
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}
Tab 1 content
Tab 2 content
Tab 3 content
component preview

Result

The result is a simple tabs component that works without a single line of JavaScript: full markup with styles on a CodePen.

$ cd ..