【Vuetify3】JavaScriptで横幅を取得する方法~v-spacerとuseDisplayの組み合わせが便利そう~

プログラミング等

どうもこじらです。

Vuetify3で少し学びがあったので共有です。

どうもネット上にVue3, Vuetify3の記事が少ない気がします。あんまり人気ないんですかね?

 

まぁ、私の記事が同志への手助けになれたら嬉しいです。

Vuetify3で横幅を取得する方法

useDisplayを使う

結論としては、useDisplayを使用すると、横幅をリアクティブに取得することができます。

 

普段VuetifyではuseThemeを使うことが多いですが、useDisplayというAPIもあるんですね。

知りませんでした。

 

↓こんな感じで監視できます。

<template>
// 省略
</template>

<script setup lang="ts">
import { useDisplay } from 'vuetify'
const width = useDisplay().width
watch(
  width,
  (newValue) => {
    console.log(newValue) // 横幅が変更されるたびにコンソール出力される。
  }
)
</script>

 

Vuetify3で横幅を取得するのはアンチパターン?

VuetifyがuseDisplayで横幅を提供してくれているので、Vuetify的に横幅を取得するのはOKな訳ですが、私はアンチパターンになりやすいんじゃないかと思っています。

 

VuetifyではGrid Systemとして、xs, sm,md,lg,xl,xxlという横幅に応じた区分けが存在します。

その区分けがあるにもかかわらず、横幅という連続的な値を見て判断するのはナンセンスかと思います。

 

すでに存在する区分けに従って表示を切り替えたほうが想定外の挙動になりにくいですし、Vuetifyもこの6段階の区分けが粒度的にちょうど良いだろうと判断してこの仕様にしているはずです。

そのため、widthから横幅を取得して何かをしている時点で、Vuetifyを作成した人たちの尊厳が足りていないと思った方が良いというか、我が強すぎるコーディングをしている可能性を疑った方が良いと思います。

 

じゃあどうすれば?

Vuetify3のuseDisplayは横幅以外に、xs,sm,md,lg,xl,xxlか否かをboolean型で提供しています。

これを使うのがより良い実装になると思います。

 

<template>
// 省略
</template>

<script setup lang="ts">
import { useDisplay } from 'vuetify'

const display = useDisplay()
const isXs = display.xs // xsか否か
const isSm = display.sm // smか否か
const isMd = display.md // mdか否か
const isLg = display.lg // lgか否か
const isXl = display.xl // xlか否か
const isXxl = display.xxl // xxlか否か
</script

 

v-spacerとuseDisplayの組み合わせが結構使えそう

私はv-spacerが結構好きでよく使っています。

画面の真ん中の方に表示させて、表示の開始位置を揃えたいときに使うことが多いです。

↓こんな感じのイメージです。(もっと良いやり方がありそうですが、v-colで色んな画面サイズに対応できるのはやっぱり魅力的で、Grid Systemに頼るのが最善かなと思ってます。)

 

v-spacerを使用することによって横幅4分割の均等割付けになっている訳ですが、この場合スマホで表示させた場合に文字を表示するスペースが小さくなって、文字列に改行が入りレイアウトが崩れてしまいます。

↓そのため、こんな感じに、画面サイズが小さい時だけv-spacerを非表示にするやり方が結構いいんじゃないかと思っています。

<template>
  <v-container>
    <v-row>
      <v-spacer v-if="isSmAndUp" />
      <v-col>タイトル1</v-col>
      <v-col>あたい1</v-col>
      <v-spacer v-if="isSmAndUp" />
    </v-row>
    <v-row>
      <v-spacer v-if="isSmAndUp" />
      <v-col>タイトル2</v-col>
      <v-col>あたい2</v-col>
      <v-spacer v-if="isSmAndUp" />
    </v-row>
  </v-container>
</template>

<script setup lang="ts">
import { useDisplay } from 'vuetify'
const width = useDisplay().width

const isSmAndUp = useDisplay().smAndUp
</script>

 

sm以上か否かで判定してますが、普通にxsか否かの方がきれいな気もしますw

まぁ、Vuetifyの配慮の良さを活かしたくてsmAndUpで指定してますw

 

余談:classにおけるxs,sm,md,lg,xl,xxlに関する勘違い

Vuetify3ではシンタックスシュガーとして、使用頻度が高いstyleをclassとして用意してくれています。

 

このclassでよくsm,md,lg,xl,xxlが登場するんですが、これが付くやつは全部「以上」です。

 

私は盛大に勘違いしていましたw

 

これはVue2時代からの話なのかどうなのか……。

「なんか、xsだけないな…。なんでだ……?」と思っていました。

 

例えば、text-center(text-align: center; !important)で存在するclassは、

  1. text-center
  2. text-sm-center
  3. text-md-center
  4. text-lg-center
  5. text-xl-center
  6. text-xxl-center

です。

text-xs-centerは存在しません。

 

↓カラクリというか、理由はこういうことのようです。

これらのcssは、適用範囲が@media (min-width: XXXpx)として指定されています。

つまりは「それ以上」の場合に適用させる仕様になっている訳です。

 

そのため、useDisplayでいうと、smじゃなくてsmAndUpっていうことです。

少し違和感あるけど、たしかにこっちの方が便利だもんなぁ…。

 

はい、という感じで、useDisplayのxs,sm,md,lg,xxlとvuetifyが用意してくれているclassを使うのが一番良い実装方法だと思うよっていう記事でした。

こじらでした

じゃ

タイトルとURLをコピーしました