Tips for adding a scroll-to-top button on a page with only a vertical scroll bar

How can I make the scroll to top/bottom button only show up on pages with a vertical scrollbar? Currently, the button is not appearing when the page contains a vertical scrollbar. Any suggestions on how to implement this feature?

ScrollToTopBottom.vue

<template>
      <div v-if= "hasVerticalScroll" v-scroll="onScroll" >
        <v-btn v-if = "!isVisible"
            fab fixed bottom right color="primary" @click="toBottom">
            <v-icon>mdi-arrow-down-bold-box-outline</v-icon>
        </v-btn>

        <v-btn v-else
            fab fixed bottom right color="primary" @click="toTop">
            <v-icon>mdi-arrow-up-bold-box-outline</v-icon>
        </v-btn>
      </div>
</template>

<script>

export default{
    data () {
        return {
        isVisible: false,
        position: 0,

    }
  },
   methods: {
    onScroll () {
      this.isVisible = window.scrollY > 500
    },
    toTop () {
      this.position = window.scrollY
      window.scrollTo({
        top: 0,
        left: 0,
        behavior: 'smooth'
      })
    },
    toBottom(){
      let pos = this.position > 0 ? this.position : document.body.scrollHeight
      window.scrollTo({
        top: pos,
        behavior: 'smooth'
      })
    },
  },
  computed: {
      hasVerticalScroll(){
        console.log('offsetHeight',document.body.offsetHeight);
        console.log('windowinner',window.innerHeight);
        return document.body.offsetHeight > window.innerHeight;
      }
    }
}

</script> 

Answer №1

To optimize your code, you can refactor the hasVerticalScroll function to be a method within the parent component and listen for scroll events:

Vue.component('scrollToTopButton', {
  template: `
    <div v-scroll="onScroll" >
      <v-btn v-if="!isVisible" fab fixed bottom right color="primary" @click="toBottom">
        <v-icon>mdi-arrow-down-bold-box-outline</v-icon>
      </v-btn>
      <v-btn v-else fab fixed bottom right color="primary" @click="toTop">
        <v-icon>mdi-arrow-up-bold-box-outline</v-icon>
      </v-btn>
    </div>
  `,
  data () {
    return {
      isVisible: false,
      position: 0
    }
  },
   methods: {
    onScroll() {
      this.isVisible = window.scrollY > 50
    },
    toTop() {
      this.position = window.scrollY
      window.scrollTo({
        top: 0,
        left: 0,
        behavior: 'smooth'
      })
    },
    toBottom(){
      let pos = this.position > 0 ? this.position : document.body.scrollHeight
      window.scrollTo({
        top: pos,
        behavior: 'smooth'
      })
    },
  },

})
new Vue({
  el: "#demo",
  vuetify: new Vuetify(),
  data() {
    return {
      hasScroll: false
    }
  },
  methods: {
    hasVerticalScroll() {
      this.hasScroll = document.body.offsetHeight > window.innerHeight; 
    }
  }
})
<link href="https://cdn.jsdelivr.net/npm/@mdi/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f5939a9b81b5c3db8d">[email protected]</a>/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f7818292839e918eb7c5d98f">[email protected]</a>/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ec9a9989acdec294">[email protected]</a>/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f98f8c9c8d909f80b9cbd781">[email protected]</a>/dist/vuetify.js"></script>
<div id="demo" >
  <v-app v-scroll="hasVerticalScroll">
    <v-main>
      <v-container >
        <div>xxx</div><div>xxx</div><div>xxx</div><div>xxx</div><div>xxx</div><div>xxx</div><div>xxx</div><div>xxx</div><div>xxx</div><div>xxx</div>
        <div>xxx</div><div>xxx</div><div>xxx</div><div>xxx</div><div>xxx</div>
        <scroll-to-top-button v-if="hasScroll" ></scroll-to-top-button>
      </v-container>
    </v-main>
  </v-app>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Fill the drop-down menu with the present day's date, month, and year

I'm new to this, so please bear with me. I have some html and jQuery code: $(document).ready(function() { var d = new Date(); var month = d.getMonth() + 1; var year = d.getFullYear(); $("#month").val(month); $("#year").val(year) ...

Opt for utilizing v-model over the name attribute when implementing Vee-Validate

Recently, I've embarked on a journey to learn how to create Single Page Applications using Vue. Today, my focus is on Vee-Validate. When working with Vee-Validate, the validation requires the name attribute to be filled in. Otherwise, a warning messa ...

Parsing JSON data to extract values stored in a two-dimensional array

In order to develop a basic version of Tic Tac Toe, I decided to store game data in a JSON file. Here is an example of how the file is structured: [ { "turn": "x", "board": [ [ " ...

JavaScript - Combining nested arrays of JSON data into a single object

I'm looking to convert a nested JSON structure into a single object with dynamic keys. I attempted the code below, which only works for one level. I need help writing a recursive function to handle n levels of nesting. Any advice would be appreciated. ...

Maximizing the worth of itemtype using jQuery: A guide

My goal is to include an 'itemtype' attribute in the body tag, body.page-body.ng-scope.device-lg(itemscope='', itemtype='') I attempted the following method $('body').add(itemtype='t1'); Unfortunately, ...

Encountering the error `RollupError: Expression expected` during the compilation of an NPM package

Following the setup of my environment to create my initial NPM package for React JS with ROLLUP bundler, I encountered a RollupError: Expression expected error message as displayed below: Error Message > rollup -c --environment NODE_ENV:development dev ...

Tips for maintaining the browser scroll bar at the top when switching routes in AngularJS

How can I ensure that the scrollbar is always at the top when a user is redirected to a different page after scrolling down on the home page? The autoscroll feature in the code below doesn't seem to be working. Any suggestions would be greatly appreci ...

Enhance your Vue template slots with type hinting in PhpStorm

I've been grappling with how to add type hints to my scoped slots directly in the template. Here's an example of what I currently have: <template #item="{ item }"> I'm using PhpStorm, and I would like to access properties o ...

Make sure to always send back JSON data when using the default error handler in ExpressJS

I'm in the process of developing an API server using ExpressJS. I want to guarantee that the server consistently delivers JSON data rather than HTML data. While I can easily make the server respond with JSON for all customized routes, I encounter diff ...

Explore in MegaMenu Pop-up

At my workplace, the internal web portal features a MegaMenu with a popup menu that includes a Search input field. The issue I am encountering is that when a user starts typing in the search bar and moves the mouse off of the megamenu, it disappears. It ...

Combining VueJS with the powerful Vue.Draggable plugin, along with the Vuex Store to manage data

Seeking guidance on integrating Vue.Draggable lists with computed variables in a Vuex Store. As a newcomer to VueJS, I'm currently working with the following component setup: // Template <draggable class="list-group" :list="list1" group="people"&g ...

Switching from Vue's Options API to Composition API is like transforming your code from

My goal is to transition the code below from using the options API to the composition API in Vue while utilizing Typescript. data() { return { items: [ 'Car', 'Truck', 'Bike', 'Ca ...

The tabbing feature in bxslider disrupts the alignment of slides, making it

After encountering accessibility issues, I upgraded the bxslider library to version 4.2.3 for better support. Check out this example of bxslider where you can easily tab through the controls: http://jsfiddle.net/qax7w8vt/2/embedded/result/ The problem a ...

Guide to leveraging the Vue.js framework alongside the template compiler in conjunction with Webpack

I recently started using Webpack for my project. Following a tutorial, I managed to configure Vuejs into my build. The tutorial can be found here. Everything was working fine until I tried to render a template and encountered an error in the browser sayi ...

Focused on individual characters in a string to implement diverse CSS styles

Is there a way I can apply different CSS classes to specific indexes within a string? For example, consider this string: "Tip. \n Please search using a third character. \n Or use a wildcard." I know how to target the first line with CSS using : ...

Collecting all Material-UI components into a single document

Currently, I am engaged in a Meteor project that utilizes Material UI and ReactJS. I wish to streamline the process by creating a single file that imports all necessary Material UI components for my project. This way, instead of adding individual exports ...

Experience an enthralling carousel feature powered by the dynamic ContentFlow.js

My website features a cover flow style carousel with 7 images: <!-- ===== FLOW ===== --> <div id="contentFlow" class="ContentFlow"> <!-- should be place before flow so that contained images will be loaded first --> <div class= ...

Unable to `.catch()` an error while utilizing Jquery.ajax().then()

My current project involves making calls to various APIs using JQuery and caching the response from each API. This cached data is then used multiple times on the page to create different dashboard widgets. The issue I'm facing is that if an API retur ...

Tips on implementing VueStripe in a vue2 Project

I recently integrated Vue Stripe into my vue2 Project and encountered 2 similar errors in my code : Property 'redirectToCheckout' does not exist on type 'Vue | Element | (Vue | Element)[]'. Property 'publishableKey' does ...

Using Typescript to create an asynchronous function without explicitly declaring a Promise

When you examine TypeScript's async function, you may notice the redundancy with "async" and "Promise<type>". public async test(): Promise<string> { return "Test"; } Is there a way to configure TypeScript to handle async types ...