This post was published 8 years ago

There's a chance things are out of date or no longer reflect my views today

Stop headroom.js hiding when your navigation is open

Headroom.js is a popular plugin for providing additional functionality in having a fixed header. It has a lot of additional callbacks and options, to make sure you can cover a variety of situations. One of those things is stopping it from hiding when your navigation is open.

1,058 views

Stop headroom.js hiding when your navigation is open (featured image)

Headroom.js is a popular plugin for providing additional functionality in having a fixed header. It has a lot of additional callbacks and options, to make sure you can cover a variety of situations. One of those things is stopping it from hiding when your navigation is open. Which is what this post will cover, as this is something I had to do recently.

The problem detailed

You’ve got your header setup and working with headroom.js. Your navigation is revealed by tapping or clicking an icon (be that a hamburger or whatnot). When you scroll the header still hides despite the navigation being visible.

You may even have the navigation cover the whole viewport, but you can still trigger scroll events.

Using CSS only could probably solve this, but that isn’t ideal. As it can quickly become difficult to maintain, if you’re adding an additional state to the navigation.

The solution

To solve this you need to stop the navigation hiding, when it’s ‘open’ or ‘visible’.

You may have this currently

You will have initialised headroom, it may look similar, or you may have passed some options.

var header = document.getElementById('header');
var headroom = new Headroom(header);
headroom.init();

Checking the state

Firstly, it’s helpful to write a small function to check whether the nav is visible. This will make code more readable amongst the options.

function isNavVisible(nav) {
  return ( nav.classList.contains('visible') ? true : false );
}

So this function has a single argument, which when you come to use this function, will look something like document.querySelector('.nav'). It then returns a value of true or false whether the navigation contains the class visible.

You can change this visible class to be more in line with your naming convention.

Using the onUnpin callback to disable hiding

If you have your options set up already, then it will be a matter of taking the onUnpin callback and adding it to your existing options.

var header = document.getElementById('header');
var nav = document.getElementById('nav');

var options = {
  onUnpin: function() {
    if ( isNavVisible(nav) ) {
      this.elem.classList.remove(this.classes.unpinned);
      this.elem.classList.add(this.classes.pinned);
    }
    else {
      this.elem.classList.add(this.classes.unpinned);
      this.elem.classList.remove(this.classes.pinned);
    }
  }
};

var headroom = new Headroom(header, options);
headroom.init();

If you don’t have options, this essentially passes an extra parameter to the headroom variable. Inside the options object, the onUnpin callback uses the function from earlier to remove or add a class name using the classes object built into headroom.

How the classes are chosen

Using this gives you access to all the options. Specifically you need to access elem and classes.

this.elem.classList.remove(this.classes.unpinned);

this.elem refers to the element you pass to headroom, in this case it’s the header variable. You can use this to look at the class list and use that to remove or add a class.

To remove the class that applies the unpinned state, you use this.classes.unpinned.

You’re free to update class names

This is useful because you may have an override in place for your own class names. You can also update them without the need to change this code later on.

Toggling your navigation

For the sake of completeness and clarity, I’ve included a basic navigation toggle.

var nav = document.querySelector('.nav');
var navToggle = document.querySelector('.nav-toggle');

navToggle.addEventListener('click', function() {
  nav.classlist.toggle('visible');
}, false);

This will listen for clicks on .nav-toggle and toggle a class on .nav.

Final code

To recap you’ve got a function to detect visibility of your nav element. That function is used as part of the onunpin callback, where you add and remove class names based upon the state. The class names are found in the classes object.

function isNavVisible(nav) {
  return ( nav.classList.contains('visible') ? true : false );
}

var header = document.getElementById('header');
var nav = document.getElementById('nav');

var options = {
  onUnpin: function() {
    if ( isNavVisible(nav) ) {
      this.elem.classList.remove(this.classes.unpinned);
      this.elem.classList.add(this.classes.pinned);
    }
    else {
      this.elem.classList.add(this.classes.unpinned);
      this.elem.classList.remove(this.classes.pinned);
    }
  }
};

var headroom = new Headroom(header, options);
headroom.init();
View on Github