100% Pure HTML/CSS Page Navigation - No JavaScript Required
Morten Olsrud
Posted on October 13, 2018
Build a page navigation system using only HTML and CSS
This is a little trick I've acquired over the years, and for most use cases it works wonders in keeping my code clean, lean and free from unnecessary JavaScript.
Imagine a Single Page Application or a page showing and hiding panels, modals etc. without reloading the page. Clicking on one of these triggers will alter the content of the page.
Traditionally this was done using jQuery or some home made JavaScript functions altering the styles or classes on the elements in question. Setting a class with display: none;
to hide or display: block;
to show them are classics, along with setting that style directly on the elements.
Well, there is no need to do it so complicated at all.
Examples
Take a look at this HTML:
...
<!-- Just a typical nav-element with a list of links -->
<nav>
<a href="#page1">Page 1</a>
<a href="#page2">Page 2</a>
...
<a href="#page5">Page 5</a>
</nav>
...
<!--
All the divs with the content you want to serve. Notice page1 sits last.
This is important for the CSS to work.
-->
<div id="page2" class="page">[some content]</div>
<div id="page3" class="page">[some content]</div>
...
<div id="page5" class="page">[some content]</div>
<div id="page1" class="page default">[some content]</div>
...
Here we have the nav
element with it's links, and the div
s with their content. Notice the ID of the DIV is the same as the anchor link. One important thing is placing the first page, or rather the div with the content you want to be shown when no link is clicked yet, last.
And here is the important parts of the CSS:
/* This hides all pages */
.page {
display: none;
}
/* This displays the first page */
.default {
display: block;
}
/* This displays the page corresponding to the one you clicked on */
:target {
display: block;
}
/* This hides the default page when another page is clicked */
:target ~ .default {
display: none;
}
Or condensed:
.page, :target ~ .default {
display: none;
}
.default, :target {
display: block;
}
Demo
Now, the CodePen I've embedded below contains CSS and HTML not displayed in this example, but that's just to make it "pretty" and has nothing to do with the actual function of the nav. Just the layout. Try it out before we unveil the secret sauce, and a caveat.
Unveiling the secret
The first part of this secret is the links. The href
contains only hashed identifiers like the ones you use to jump up and down a page. The hash in a URL gets picked up by CSS using the :target
pseudo-selector, allowing us to use that to change the style of the element who's ID is equal to the hash in the URL.
The second part is how we use the selectors to hide the default page. Since we are placing that last, we can use the sibling selector to target all elements with the class .default
that comes after the element who is targeted.
Now the caveat is that unless the page is structured or laid out in such a way that the top of the "pages" are also at the top of the browser, the page might jump. Some CSS/HTML only hacks can be done by using container DIVs that holds the ID and are positioned with top: 0px;
and contains the actual content DIV pushed down with margins, or some other similar approach.
Hope you enjoyed!
Oh, and if you have other approaches to do SPA and similar type navigation without JavaScript, please share in the comments.
Posted on October 13, 2018
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.