LoginSignup
3
2

More than 3 years have passed since last update.

Vuetify でウィンドウの縦幅に合わせてコンテンツサイズを動的に配置・調整する。

Posted at

はじめに

Vuetifyはグリッドシステムを備えており、これを活用すればウィンドウの横幅に対してコンテンツが動的に配置・調整されます。

Grid system
https://vuetifyjs.com/ja/components/grids/

ただ、ウィンドウの縦幅に対する配置・調整が思い通りにならない場面があったため、調査・実施した結果を残します。

具体的に説明すること

次のような4つのメニューボタン(アイコンは適当)を表示する画面があったとして
キャプチャ.PNG

縦幅の大きな余白が気になるので、次のように画面の縦幅が埋まるようにメニューボタンを表示できるようにしたいと思います。
キャプチャ2.PNG

※ iPhoneの場合はこうできます。画面サイズが変わっても、実際の画面に応じてメニューボタンのサイズが調整されます。
キャプチャ5.PNG

環境

  • Vue.js 2.6.12
  • Vuetify 2.3.10

結論

Home.vue
<template>
  <div class="Home">
    <v-container fluid >
      <v-row>
        <v-col cols="12">
          <v-row v-resize="onResize" :style="style" >
            <v-col cols="6" v-for="menu in menus" v-bind:key="menu.key">
              <v-btn
                color="accent"
                block
                height='100%'
              >
                <v-icon :size="iconSize">{{menu.icon}}</v-icon>
              </v-btn>
            </v-col>
          </v-row>
        </v-col>
      </v-row>
    </v-container>
  </div>
</template>

<script>

  export default {
    name: 'Home',
    data: () => ({
      menus: [
        { title: 'home', icon: 'mdi-home' },
        { title: 'currency', icon: 'mdi-currency-cny' },
        { title: 'gift', icon: 'mdi-gift' },
        { title: 'kaji', icon: 'mdi-washing-machine'},
      ],
      windowSize: {
        x: 0,
        y: 0,
      },
      iconSize: 0 
    }),

    mounted () {
      this.onResize()
    },

    computed: {
      style () {
        return 'height: ' + this.windowSize.y * 0.8 + 'px;'
      }
    },

    methods: {
      onResize () {
        this.windowSize = { x: window.innerWidth, y: window.innerHeight }
        this.iconSize = window.innerHeight * 0.1
      },
    },
    components: {
    },
  }
</script>

詳細

基本的な方針としては、windowオブジェクトから取得したウィンドウサイズに応じてコンテンツのstyleを設定します。

また、ウィンドウサイズ変更時に呼び出されるコールバック関数を用意し、ウィンドウサイズに応じてstyleも更新されるようにします。

Resizing directive
https://vuetifyjs.com/ja/directives/resizing/

このあたりの実装は以下が該当します。
mountedでもonResize()を呼び出すことで初回表示時にwindowSizeに値が格納されるようにします。
computedのstyle()はディレクティブに設定するstyleのとして、windowSizeの値に応じてheightのピクセルを返すようにしています。ウィンドウサイズの0.8倍としているのは決め打ちです。

また、onResize()でアイコンサイズを動的に変更するようにしました。ウィンドウサイズ縦幅の0.1倍としているのは、これまた決め打ちです。

<script>
  export default {
    name: 'Home',
    data: () => ({
      windowSize: {
        x: 0,
        y: 0,
      },
    }),

    mounted () {
      this.onResize()
    },

    computed: {
      style () {
        return 'height: ' + this.windowSize.y * 0.8 + 'px;'
      }
    },

    methods: {
      onResize () {
        this.windowSize = { x: window.innerWidth, y: window.innerHeight }
        this.iconSize = window.innerHeight * 0.1
      },
    },
</script>

onResize(コールバック関数)とstyleの設定は、コンテンツ()の親要素()で設定します。
ここで必要なのは、<v-btn>のheight='100%'を設定しておくことで、ボタンがいい感じにウィンドウサイズ縦幅に合わせて調整されます。

...
        <v-col cols="12">
          <v-row v-resize="onResize" :style="style" >
            <v-col cols="6" v-for="menu in menus" v-bind:key="menu.key">
              <v-btn
                color="accent"
                block
                height='100%'
              >
                <v-icon :size="iconSize">{{menu.icon}}</v-icon>
              </v-btn>
            </v-col>
          </v-row>
        </v-col>
...

以上です。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2