2

Learning Vue with Nuxt. Want to change navbar classes depending on the page scroll position.

Looked in several places, but haven't found a working solution.

Here's what I have to work with:

``` default.vue
<template lang="pug">
div(v-on:scroll="shrinkNav", v-on:click="shrinkNav")
  b-navbar.text-center(toggleable="sm" type="light" sticky v-b-scrollspy)
    #myNav.mx-auto.bg-white
      b-navbar-toggle(target="nav_collapse")
      b-navbar-brand.mx-auto(href="#") 
        | Example.org
      b-collapse#nav_collapse.mx-auto(is-nav='')
        b-navbar-nav(justified, style="min-width: 600px").vertical-center
          b-nav-item.my-auto(href='#home') Home
          b-nav-item.my-auto(href='/how') How
          i.fab.fa-earlybirds.fa-2x.mt-2.mb-3
          b-nav-item.my-auto(href='/values') Values
          b-nav-item.my-auto(href='/join-us') Join Us
  #content.container(v-on:scroll="shrinkNav", v-on:click="shrinkNav")
nuxt
    nuxt
</template>

<script>
  // resize navbar on scroll
  export default {
    methods: {
      shrinkNav() {
        var nav = document.getElementById('nav')
        var content = document.getElementById('content')
        if (nav && content) {
          if(content.scrollTop >= 150) {
            nav.classList.add('shrink')
          } else {
            nav.classList.remove('shrink')
          }
        }
        console.log(document.documentElement.scrollTop || document.body.scrollTop)
      }      
    }
  }
</script>
```

shrinkNav runs twice on click, but nothing on scroll. What is the Vue/Nuxt way to do this?

1
  • ss animation stops after last frame Commented Oct 1, 2020 at 6:11

2 Answers 2

5

In your .vue:

<template> section:

<nav id="nav" class="navbar is-transparent is-fixed-top">

<script> section:

export default {
mounted() {
      this.$nextTick(function(){
        window.addEventListener("scroll", function(){
          var navbar = document.getElementById("nav");
          var nav_classes = navbar.classList;
          if(document.documentElement.scrollTop >= 150) {
            if (nav_classes.contains("shrink") === false) {
              nav_classes.toggle("shrink");
            }
          }
          else {
            if (nav_classes.contains("shrink") === true) {
              nav_classes.toggle("shrink");
            }
          }
        })
      })
    },
}

Live Demo on codesandbox

Sign up to request clarification or add additional context in comments.

Comments

1

Ok, here's a solution using Plugins. There may be a better way:

1) Define a directive in plugins/scroll.js

``` javascript
// https://vuejs.org/v2/cookbook/creating-custom-scroll-directives.html#Base-Example
import Vue from 'vue'

Vue.directive('scroll', {
  inserted: function (el, binding) {
    let f = function (evt) {
      if (binding.value(evt, el)) {
        window.removeEventListener('scroll', f)
      }
    }
    window.addEventListener('scroll', f)
  }
})
```

2) Add plugin to project in nuxt.config.js

``` javascript
module.exports = {
  head: { },
  plugins: [
    { src: '~/plugins/scroll.js', },
  ]
}
```

3) Use the v-scroll directive to define custom behavior in menu in /layouts/default.vue

``` javascript
<template lang="pug">
div(v-scroll="shrinkNav")
  b-navbar.text-center(toggleable="sm" type="light" sticky)
    #myNav.mx-auto.bg-white
      b-navbar-toggle(target="nav_collapse")
      b-navbar-brand.mx-auto(href="/#home") Example.org
      b-collapse#nav_collapse.mx-auto(is-nav='')
        b-navbar-nav(justified, style="min-width: 600px").vertical-center
          b-nav-item.my-auto(to='/#home') Home
  #content.container
    nuxt
</template>

<script>
  export default {
    methods: {
      shrinkNav() {
        var scrollPosition = document.documentElement.scrollTop || document.body.scrollTop
        var nav = document.getElementById('myNav')
        console.log(scrollPosition, nav)
        if(scrollPosition >= 150) {
          nav.classList.add('shrink')
        } else {
          nav.classList.remove('shrink')
        }
      },
    },
  }
</script>

<style>
  nav.navbar {
    margin: 0;
    padding: 0;
  }
  #myNav {
    border-radius: 0 0 10px 10px;
    border: 2px solid purple;
    border-top: none;
  }
  #myNav.shrink {
    border: none;
  }
</style>
```

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.