Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Headroom.js header with initial static state

I'm using the awesome Headroom.js plugin to build an auto-hiding header. The header is static from start and becomes pinned after an offset (when scrolling down) and then back to static (when it's back to the top).

Here is what I have done: http://codepen.io/netgloo/pen/KmGpBL

but I got 2 problems:

  • scrolling down from top: when the header becomes pinned, I see it slides down and suddenly slides up
  • scrolling up from middle page: when the header arrives to the offset it disappears, but I need keeping it pinned to the top

Someone could give me some help or ideas? Thanks

Here is how I initialize the plugin:

var myElement = document.querySelector("header");

var headroom  = new Headroom(myElement, {
  "offset": 150,
  "tolerance": 0,
});

headroom.init();
like image 418
Fred K Avatar asked May 18 '17 18:05

Fred K


1 Answers

The headroom.js script mainly handles the addition/removal of some classes for you. It's up to you to add the appropriate styles to achieve the effect you want. Let's start with the simplest part, the HTML:

HTML

<header>
  Header
</header>

That's it!

Now for the JS setup:

JS

var myElement = document.querySelector("header");

var headroom  = new Headroom(myElement, {
  "offset": 220,
  "tolerance": {
    up: 0,
    down: 0
  },
  "classes": {
    "initial": "header--fixed",
    "pinned": "slideDown",
    "unpinned": "slideUp",
    "top": "top",
    "notTop" : "not-top",
  }
});

headroom.init();

The first line selects the header element. The second creates a new Headroom object using the configuration values. I've set the values based on the effect it sounds like you're trying to achieve - the header should slide away when the page is scrolled down quickly, and should slide into view when the page is scrolled up.

The offset of 205px is the distance from the top when the header can become unpinned.

The tolerance of 5px is the scroll tolerance before the state changes.

And finally we're going to define the classes that will be added to the element for the different states. At the start the element will be assigned a class of header--fixed. When pinned, the element will receive the additional slideDown class. And when unpinned the element will receive the additional slideUp class.

The final line initializes the headroom object.

Using the state-based classes we can now create the CSS needed to achieve the effect you want.

CSS

We'll start with the .header--fixed class:

.header--fixed {
  position: absolute;
  top: 0; 
  width: 100%; 
}

main {
  padding-top: 110px;
}

This sets the initial placement of the header (at the top) and sets a padding for the main content of the page so it's not covered by the header.

Next we need to define the styles for various states - .top, .not-top, .slideDown and .slideUp:

.header--fixed.top {
  transition: none;
  transform: translateY(0);
}
.header--fixed.not-top {
  position: fixed;
  transform: translateY(-100%);
}
.header--fixed.slideDown.not-top {
  transition: transform 0.3s ease-in-out;
  transform: translateY(0);
}
.header--fixed.slideDown.top {
  transition: transform 0.3s ease-in-out;
  position: fixed;
}
.header--fixed.slideUp.not-top {
  transition: transform 0.3s ease-in-out;
  transform: translateY(-100%);
}
.header--fixed.slideUp.top {
  transform: translateY(-100%);
  position: absolute;
}

Most of these styles are related to setting the position and transition for each state. In short, the .not-top class is applied when the page is scrolled below the header. .top is applied when the page is scrolled near the top (within the height of the header).

In addition to this critical CSS you would need the CSS for the styling of the header - a background color, font, etc. This could be applied by targeting the header element, or header--fixed class.

The final piece, and crux of the problem is resetting the header when the page is scrolled back to the very top - ie a window.pageYOffset of 0. When the page reaches this point, we need to remove the .slideDown class so the header scrolls with the page.

window.addEventListener('scroll', function() {
  if (window.pageYOffset === 0) {
    myElement.classList.remove('slideDown')
  }
})

The Full Code

Putting it all together we get this:

// Headroom.js
// https://github.com/WickyNilliams/headroom.js
var myElement = document.querySelector("header");

var headroom  = new Headroom(myElement, {
  "offset": 220,
  "tolerance": {
    up: 0,
    down: 0
  },
  "classes": {
    "initial": "header--fixed",
    "pinned": "slideDown",
    "unpinned": "slideUp",
    "top": "top",
    "notTop" : "not-top",
  }
});

headroom.init();

// When the page is at the top, remove the slideDown class.
window.addEventListener('scroll', function() {
  if (window.pageYOffset === 0) {
    myElement.classList.remove('slideDown')
  }
})
.header--fixed {
  position: absolute;
  top: 0;
  width: 100%;
}
.header--fixed.top {
  transition: none;
  transform: translateY(0);
}
.header--fixed.not-top {
  position: fixed;
  transform: translateY(-100%);
}
.header--fixed.slideDown.not-top {
  transition: transform 0.3s ease-in-out;
  transform: translateY(0);
}
.header--fixed.slideDown.top {
  transition: transform 0.3s ease-in-out;
  position: fixed;
}
.header--fixed.slideUp.not-top {
  transition: transform 0.3s ease-in-out;
  transform: translateY(-100%);
}
.header--fixed.slideUp.top {
  transform: translateY(-100%);
  position: absolute;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  text-align: center;
}

header {
  background: #4ECDC4;
  padding: 40px;
  font: normal 30px/1 sans-serif;
}

main {
  padding: 110px 0 0 0;
}
<script src="https://unpkg.com/headroom.js"></script>
<header>
  Header
</header>

<main>
  <p>Lorem ipsum 1</p>
  <p>Lorem ipsum 2</p>
  <p>Lorem ipsum 3</p>
  <p>Lorem ipsum 4</p>
  <p>Lorem ipsum 5</p>
  <p>Lorem ipsum 6</p>
  <p>Lorem ipsum 7</p>
  <p>Lorem ipsum 8</p>
  <p>Lorem ipsum 9</p>
  <p>Lorem ipsum 10</p>
  <hr>
  <p>Lorem ipsum 1</p>
  <p>Lorem ipsum 2</p>
  <p>Lorem ipsum 3</p>
  <p>Lorem ipsum 4</p>
  <p>Lorem ipsum 5</p>
  <p>Lorem ipsum 6</p>
  <p>Lorem ipsum 7</p>
  <p>Lorem ipsum 8</p>
  <p>Lorem ipsum 9</p>
  <p>Lorem ipsum 10</p>
  <hr>
  <p>Lorem ipsum 1</p>
  <p>Lorem ipsum 2</p>
  <p>Lorem ipsum 3</p>
  <p>Lorem ipsum 4</p>
  <p>Lorem ipsum 5</p>
  <p>Lorem ipsum 6</p>
  <p>Lorem ipsum 7</p>
  <p>Lorem ipsum 8</p>
  <p>Lorem ipsum 9</p>
  <p>Lorem ipsum 10</p>
  <hr>
  <p>Lorem ipsum 1</p>
  <p>Lorem ipsum 2</p>
  <p>Lorem ipsum 3</p>
  <p>Lorem ipsum 4</p>
  <p>Lorem ipsum 5</p>
  <p>Lorem ipsum 6</p>
  <p>Lorem ipsum 7</p>
  <p>Lorem ipsum 8</p>
  <p>Lorem ipsum 9</p>
  <p>Lorem ipsum 10</p>
  <hr>
  <p>Lorem ipsum 1</p>
  <p>Lorem ipsum 2</p>
  <p>Lorem ipsum 3</p>
  <p>Lorem ipsum 4</p>
  <p>Lorem ipsum 5</p>
  <p>Lorem ipsum 6</p>
  <p>Lorem ipsum 7</p>
  <p>Lorem ipsum 8</p>
  <p>Lorem ipsum 9</p>
  <p>Lorem ipsum 10</p>
  <hr>
  <p>Lorem ipsum 1</p>
  <p>Lorem ipsum 2</p>
  <p>Lorem ipsum 3</p>
  <p>Lorem ipsum 4</p>
  <p>Lorem ipsum 5</p>
  <p>Lorem ipsum 6</p>
  <p>Lorem ipsum 7</p>
  <p>Lorem ipsum 8</p>
  <p>Lorem ipsum 9</p>
  <p>Lorem ipsum 10</p>
  <hr>
  <p>Lorem ipsum 1</p>
  <p>Lorem ipsum 2</p>
  <p>Lorem ipsum 3</p>
  <p>Lorem ipsum 4</p>
  <p>Lorem ipsum 5</p>
  <p>Lorem ipsum 6</p>
  <p>Lorem ipsum 7</p>
  <p>Lorem ipsum 8</p>
  <p>Lorem ipsum 9</p>
  <p>Lorem ipsum 10</p>
  <hr>
  <p>Lorem ipsum 1</p>
  <p>Lorem ipsum 2</p>
  <p>Lorem ipsum 3</p>
  <p>Lorem ipsum 4</p>
  <p>Lorem ipsum 5</p>
  <p>Lorem ipsum 6</p>
  <p>Lorem ipsum 7</p>
  <p>Lorem ipsum 8</p>
  <p>Lorem ipsum 9</p>
  <p>Lorem ipsum 10</p>
  <hr>
  <p>Lorem ipsum 1</p>
  <p>Lorem ipsum 2</p>
  <p>Lorem ipsum 3</p>
  <p>Lorem ipsum 4</p>
  <p>Lorem ipsum 5</p>
  <p>Lorem ipsum 6</p>
  <p>Lorem ipsum 7</p>
  <p>Lorem ipsum 8</p>
  <p>Lorem ipsum 9</p>
  <p>Lorem ipsum 10</p>
  <hr>
  <p>Lorem ipsum 1</p>
  <p>Lorem ipsum 2</p>
  <p>Lorem ipsum 3</p>
  <p>Lorem ipsum 4</p>
  <p>Lorem ipsum 5</p>
  <p>Lorem ipsum 6</p>
  <p>Lorem ipsum 7</p>
  <p>Lorem ipsum 8</p>
  <p>Lorem ipsum 9</p>
  <p>Lorem ipsum 10</p>
  <hr>
</main>

And with that we have everything we need. For a working example with the CSS done in SCSS like your example, see this Codepen.

like image 62
Brett DeWoody Avatar answered Oct 23 '22 00:10

Brett DeWoody