Vue.js

Vue 3でスクロールすると出てくる「トップへ戻る」ボタンの作り方

Vue 3(Composition API)でスクロールすると出てくる「トップへ戻る」ボタンの作り方を紹介します。scrollイベントとwindow.scrollYで表示を切り替え、scrollToでなめらかに先頭へ戻します。

この記事の目次
  1. Vue 3で「トップへ戻る」ボタンの作り方
  2. index.html
  3. template
  4. script
  5. style

Vue.jsのv3(Composition API)でスクロールすると出てくる「トップへ戻る」ボタンの作り方を紹介します。

仕組みは3つだけです。scrollイベントでwindow.scrollYを監視し、一定量スクロールしたらrefの真偽値を切り替えてボタンのclassを付け外しします。クリック時はwindow.scrollTo({ top: 0, behavior: 'smooth' })で先頭に戻ります。ライブラリは不要で、アイコンだけBoxiconsを使います。

Vue 3で「トップへ戻る」ボタンの作り方

index.html

アイコンを使いたいので、今回はBoxiconsを使用します。

<html lang="">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <link href='https://unpkg.com/boxicons@2.0.7/css/boxicons.min.css' rel='stylesheet'>
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>

publicフォルダのindex.htmlのheadタグ内にlinkを差し込みます。

この方法か、npmを使う方法があります。
上のindex.htmlはVue CLIで作ったプロジェクトのものです。Viteで作ったプロジェクトではindex.htmlがプロジェクト直下にあり、<%= BASE_URL %>のような記法は使いません。その場合もlinkタグを同じようにheadに置けば動きます。

template

<template>
  <a
    href="#"
    class="scrolltop"
    @click="scrollTop"
    :class="{'show-scroll' : scrollHeader}">
    <i class='bx bxs-chevron-up scrolltop__icon' ></i>
  </a>
</template>

templateタグでは、Boxiconsより取得したiタグのアイコンフォントをaタグで囲ってリンクにします。
aタグでは、scrollHeaderがtrueのときshow-scrollクラスが付与されるように動的なclassを作成します。
この動的なクラスで、一定のところまでスクロールしたときにスクロールトップのボタンを表示させます。

クリックしたときに上へ戻るようにするためにscrollTopというメソッドを指定しておきます。
また、iタグではアイコンの装飾をしています。

script

<script>

import { onMounted, ref } from 'vue';

export default {
  setup() {
    const scrollHeader = ref(false)

    function showScrollTop() {
      if(window.scrollY >= 560) {
        scrollHeader.value = true
      } else {
        scrollHeader.value = false
      }
    }

    function scrollTop() {
      if(window.scrollY >= 560) {

          window.scrollTo({
            top: 0,
          behavior:'smooth'
        })
      }
    }
    onMounted(() => {
    window.addEventListener("scroll", showScrollTop, { passive: true })
    })

    return {
      scrollTop,
      scrollHeader,
      showScrollTop,
    }
  }

}</script>

onMountedとrefを使うので、vueからimportします。
setup内では、true/falseのscrollHeaderを定義します。
一定のところまでスクロールされたら表示したい場合、window.scrollYでその値を取得できます。
window.scrollYは、ページの一番上からどれだけ縦にスクロールしたかをピクセル数で返します。
コンソールなどでよい位置を確認して設定します。
上の例では560としています。
560以上ならscrollHeaderをtrueに(上へ戻るボタンを表示)、そうでないならfalse(非表示)にする関数を作成します。

そして、スクロールするには、window.scrollToを使います。
topからの位置を指定します。一番上に戻りたい場合は0を指定します。
behaviorでは、smoothを指定するとスルスルとなめらかに動きます。

そして、mountされたときにスクロールを検知できるよう、onMountedでイベントリスナーを設定します。
{ passive: true }にすると、リスナー内でpreventDefault()を使わないことをブラウザに伝えられます。
ブラウザは画面描写を待たずにスクロールを処理できるので、カクつき防止にも有効です。

コンポーネントが破棄されてもリスナーは自動では外れないので、ページ遷移のあるアプリではonUnmountedで解除しておきます。<script setup>で書き直すと次のようになります。

<script setup>
import { onMounted, onUnmounted, ref } from 'vue'

const scrollHeader = ref(false)

function showScrollTop() {
  scrollHeader.value = window.scrollY >= 560
}

function scrollTop() {
  window.scrollTo({ top: 0, behavior: 'smooth' })
}

onMounted(() => {
  window.addEventListener('scroll', showScrollTop, { passive: true })
})

onUnmounted(() => {
  window.removeEventListener('scroll', showScrollTop)
})
</script>

<script setup>ではreturnが不要で、定義した変数と関数をそのままtemplateから参照できます。

スクロール位置ではなく「特定の要素が画面に入ったか」で表示を切り替えたい場合は、scrollイベントよりIntersectionObserverのほうが軽く済みます。書き方はVue.jsで要素がスクロール画面に現れたらアニメーションさせる方法を参考にしてください。

style

<style lang="scss" scoped>
  .scrolltop {
    position: fixed;
    right: 1rem;
    bottom: -20%;
    display: flex;
    justify-content: center;
    align-items: center;
    padding: .5rem;
    background-color: rgba(123,111,113,.7);
    border-radius: .5rem;
    z-index: var(--z-tooltop);
    transition: .4s;
    visibility: hidden;

    &:hover {
      background-color: var(--first-color);
    }

    &__icon {
      font-size: 2rem;
      color: var(--first-color-lighten);
    }
  }

  .show-scroll {
    visibility: visible;
    bottom: 1.5rem;
  }</style>

show-scrollで上へ戻るボタンの表示・非表示を制御しているので、visibilityを操作します。
下から出てくるような簡単なトランジションを加えるなら、表示時と非表示時のbottomに違う値を設定します。

アイコンフォントではなくSVGを使いたい場合はtailwindcssでSVGアイコンを使う方法、スクロール量そのものを可視化したい場合はライブラリを使わずに進捗バーを表示する方法が同じ考え方で作れます。

スポンサーリンク