Let CSS do the work

There’s a time and a place for JavaScript.

I've been guilty of this many times, especially when I was first starting out with JavaScript.

Once the excitement died down, however, I realised I was just making more work for myself in the long run. I was mistaking stateless HTML with having no context until I could figure it out with JavaScript. An example I've seen of this is as follows:

// curPage is a global variable on the individual page
$('.nav .' + curPage).addClass('active');

This isn't particularly flexible, and in the cases I've seen ‘curPage’ isn't used for much more than setting the active navigation item. Instead, let’s use classes to set the context and CSS to figure the rest out. In these examples I’m using Sass, but I’ll show the compiled output as well.


Let’s begin with the markup. This works on the basis that there’s a wrapping element (the tag in this case), and we target specific elements from that.

<body class="page page--home">

    <nav role="navigation">

        <ul class="hoz-nav">

            <li class="hoz-nav__item">
                <a href="/" class="nav-home">Home</a>
            </li>

            <li class="hoz-nav__item">
                <a href="/about" class="nav-about">About</a>
            </li>

            <li class="hoz-nav__item">
                <a href="/clients" class="nav-clients">Clients</a>
            </li>

            <li class="hoz-nav__item">
                <a href="/contact" class="nav-contact">Contact Us</a>
            </li>

        </ul>

    </nav>

</body>  

All you have to take notice of is the class page—home, and the class on the anchor tag (nav—home), so you can figure out the rule would be .page—home .nav-home { /* active nav styles */ }

In my Sass example, there’s a couple of extra things going on.

$navItems: (home, about, clients, contact);

@each $item in $navItems {
    .page--#{$item} .nav-#{$item} {
        @extend .active-state;
    }
}

.active-state {
    background: #fc5a08;
}

We have an array which matches the second half of the classes on the page and anchor tag. I’m then looping through them and extending my active class. The output is as follows:

.active-state, 
.page--home .nav-home, 
.page--about .nav-about, 
.page--clients .nav-clients, 
.page--contact .nav-contact {
  background: #fc5a08;
}

See the Pen Sass - Active navigation by T.J. Fogarty (@tjFogarty) on CodePen.

You can easily create CSS-only drop downs as well with use of :hover to display the hidden child element. Maybe sprinkle some transitions to fade it in rather than using the animate(); method in jQuery :)