Hide Navbar on Scroll Down in Vue

Feb 19 2019 | By Taha Shashtari

Content focused sites usually improve the user experience by reducing the distraction when it's possible. And one way to achieve this is by hiding the navbar when the user scrolls down, and show it back when scrolls up.

Achieving this behavior in vue is very easy. So, let me show you how to do this. But before that, check out this demo on CodePen:

Step 1: Create the navbar

We'll only need a single component for this demo: App.vue. So, create it, then run it using Instant Prototyping:

vue serve App.vue

Next, put this in the template section:

<template>
  <div class="app">
    <div
      class="navbar"
      :class="{ 'navbar--hidden': !showNavbar }"
    ></div>
  </div>
</template>

The navbar is just a simple div that gets hidden when showNavbar is false.

We haven't defined showNavbar or the .navbar-hidden class yet.

Let's start with the .navbar-hidden first. So in your css section, put the following:

<style>
* {
  box-sizing: border-box;
}

body {
  padding: 0;
  margin: 0;
}

.app {
  width: 100vw;
  height: 500vh;
  background: hsl(200, 50%, 90%);
}

.navbar {
  height: 60px;
  width: 100vw;
  background: hsl(200, 50%, 50%);
  position: fixed;
  box-shadow: 0 2px 15px rgba(71, 120, 120, 0.5);
  transform: translate3d(0, 0, 0);
  transition: 0.1s all ease-out;
}

.navbar.navbar--hidden {
  box-shadow: none;
  transform: translate3d(0, -100%, 0);
}
</style>

Notes on what's important here:

  • We have height: 500vh on .app to have room for scrolling (just to test our work).
  • The navbar has position: fixed, to make it sticky while we're scrolling.
  • When the navbar is hidden, we update its transform: translate3d to move it up exactly the same amount as its height (it's better to use translate3d as opposed to just translate or translateY for performance reasons).

Step 2: Hide it when scrolling down

To hide the navbar, we just have to set showNavbar to false. But we should do this only when the user scrolls down. And we can detect the scrolling direction by storing the last scroll position and compare it to the current scroll position. If currentScrollPosition < lastScrollPosition we show the navbar — we hide it, otherwise.

So, we need to define two data properties: showNavbar and lastScrollPosition.

<script>
export default {
  data () {
    return {
      showNavbar: true,
      lastScrollPosition: 0
    }
  }
}
</script>

Now, when the page is loaded, we need to listen for the scroll event on window.

mounted () {
  window.addEventListener('scroll', this.onScroll)
},

beforeDestroy () {
  window.removeEventListener('scroll', this.onScroll)
}

Let's now implement the handler:

methods: {
  onScroll () {
    // Get the current scroll position
    const currentScrollPosition = window.pageYOffset || document.documentElement.scrollTop
    // Because of momentum scrolling on mobiles, we shouldn't continue if it is less than zero
    if (currentScrollPosition < 0) {
      return
    }
    // Here we determine whether we need to show or hide the navbar
    this.showNavbar = currentScrollPosition < this.lastScrollPosition
    // Set the current scroll position as the last scroll position
    this.lastScrollPosition = currentScrollPosition
  }
}

If you check it in the browser, you will see the navbar hiding once you start scrolling down (even by one pixel). But you might want for a few pixels to pass before hiding or showing it. We can achieve this with a simple check in the handler.

Step 3: Add scroll offset before hiding or showing the navbar

Update the onScroll method to become like this:

onScroll () {
  const currentScrollPosition = window.pageYOffset || document.documentElement.scrollTop
  if (currentScrollPosition < 0) {
    return
  }
  // Stop executing this function if the difference between
  // current scroll position and last scroll position is less than some offset
  if (Math.abs(currentScrollPosition - this.lastScrollPosition) < 60) {
    return
  }
  this.showNavbar = currentScrollPosition < this.lastScrollPosition
  this.lastScrollPosition = currentScrollPosition
}

So with this change, we don't update showNavbar until the difference between the current scroll position and the last scroll position is less than the offset we choose (60px in this example).

That's it! Now your navbar should be hidden/shown if you scroll down/up more than 60px.