Go to homepage

Projects /

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.

Vertical Fixed Navigation
Check our new component library →

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 #cd-vertical-nav.open {
  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).

Project duplicated

Project created

Globals imported

There was an error while trying to export your project. Please try again or contact us.