Vertical Fixed Navigation

Vertical Fixed Navigation

A side navigation which allows users to easily browse the page, selecting one of its sections and smoothly scrolling to it. It doesn't necessarily replace the main website navigation, but comes in handy for pages packed with content.

Nucleo icons

Sponsored by Nucleo, a free application to collect, customize and export all your icons as icon font and SVG symbols. Made by the CodyHouse folks!

All the resources available on CodyHouse are released under the BSD-3-Clause license. You can support our project with a Paypal donation 🙌

If your website pages have lots of content, users can have a hard time finding exactly what they are looking for. This vertical navigation provides a complete overview of the page content, reducing browsing time and making navigation easier.
Navigation labels are hidden and shown only on hover in order to make the navigation less distracting while browsing,

Creating the structure

We wrapped our navigation in a <nav> element and created a section for each navigation item. We added a navigation "trigger"  to access navigation on touch devices.

<a class="cd-nav-trigger cd-img-replace">Open navigation</a>
<nav id="cd-vertical-nav" >
         <a href="#section1" data-number="1">
            <span class="cd-dot"></span>
            <span class="cd-label">Item 1</span>
      <!-- other navigation items here-->

<section id="section1" class="cd-section">
   <!-- content here -->

<section id="section2" class="cd-section">
   <!-- content here -->

<!-- other sections here -->

Adding style

We use Modernizr (.touch and .no-touch classes) to detect touch and no-touch devices, and deliver 2 custom navigation experiences. That is why if you resize the browser to test the snippet, you'll still get the same effect with the dots. But if you test the demo on a touch device, you see this:

vertical fixed navigation mobile preview

On no-touch devices, we hid the navigation "trigger" and set position: fixed to the <nav> element.

As default, we assigned a scale-down transformation to the navigation items (both dots and labels), and scaled them up on hover.

.no-touch #cd-vertical-nav {
  /*fix the navigation*/
  position: fixed;
  right: 40px;
  top: 50%;
  bottom: auto;
  transform: translateY(-50%);

.no-touch #cd-vertical-nav a span {
  float: right;
  /*scale down navigation dots and labels*/
  transform: scale(0.6);

.no-touch #cd-vertical-nav .cd-dot {
  transform-origin: 50% 50%;

.no-touch #cd-vertical-nav .cd-label {
  transform-origin: 100% 50%;

.no-touch #vertical-nav a:hover span {
  /*scale up navigation dots and labels*/
  transform: scale(1);

.no-touch #cd-vertical-nav a:hover .cd-label {
  /*show labels*/
  opacity: 1;

On touch devices, we set a position: fixed for the .cd-nav-trigger and <nav> and  placed them at the bottom right. This way, it should not conflict with an additional navigation, in case your website requires one.

When user clicks on the .cd-nav-trigger element, we give the .open class to the navigation to change its CSS3 scale value from 0 to 1 , with a CSS3 transition to achieve a smooth animation.

.touch #cd-vertical-nav {
  position: fixed;
  z-index: 1;
  right: 5%;
  bottom: 30px;
  width: 90%;
  max-width: 400px;
  max-height: 90%;
  transform: scale(0);
  transition-property: transform;
  transition-duration: 0.2s;
.touch {
  transform: scale(1);

Events handling

When user scrolls through the sections, the updateNavigation() function evaluates which section is currently being viewed and assigns the .is-selected class to the corresponding navigation item (based on the data-number attribute of the navigation items).

Join our newsletter

Get our monthly recap with the latest CodyHouse news