開発

Vuetify で position: sticky を有効にする

  • Pocket

Nuxt 3 & Vuetify はとても使いやすいフレームワークで気に入ってします。

ひつじの翻訳室で開発している TraToys もこのフレームワークを使って開発しています。

しかし、つい最近つまづいたことがありました。

それが、タイトルにもある position: sticky です。

つくりたかったもの

このように2カラムあって、右側のカラムは左側のスクロールに関係なく、常に表示されるようにしたかったのです。

通常これは、CSSで position: sticky を設定すれば上手くいきます。

<template>
  <v-container id="stick-container">
    <v-row>
      <v-col>
        <v-list>
          <v-list-item v-for="(i, n) in arr" :title="n" />
        </v-list>
      </v-col>
      <v-col>
        <div class="sticky-top">
          <p>Stick at top!</p>
        </div>
      </v-col>
    </v-row>
  </v-container>
</template>

<script setup lang="ts">
const arr = Array(100).fill(true);
</script>

<style>
.sticky-top {
  position: sticky;
  top: 0;
}
</style>

しかし、これだけではなぜか上手くいきませんでした。

heightの設定や親要素・兄弟要素などいろいろ調整してみましたが、どうにも上手くいきません。

何が問題だったか

調べ回ったところ、こんなissueが上がっていました。

https://github.com/vuetifyjs/vuetify/issues/15433

これによると、v-layout コンポーネントに position: relative と overflow: hidden が設定されているのが問題かもしれないとのこと。このissueはすでに閉じられていますが、開発ツールで要素を見てやると、確かにv-layoutにはoverflow: hiddenが設定されています。

そのため、layouts/default.vue を作成し、次のようにv-layoutにstyleを設定してやります。

<template>
  <v-app>
    <v-layout class="rounded rounded-md" style="overflow: visible">
      <v-app-bar
        color="blue-grey"
        scroll-behavior="elevate"
        scroll-threshold="100"
      >
        <v-app-bar-title>Default Layout</v-app-bar-title>
      </v-app-bar>
      <v-main
        class="d-flex align-center justify-center"
        style="width: 100%; height: 100%"
      >
        <slot />
      </v-main>
    </v-layout>
  </v-app>
</template>

これで最初の画像のとおり、stickyを実現することができました。

この記事のコードは こちら(Stackblitz)にあります。

  • Pocket