🖼️

【Vue3,Nuxt3】Bodyのbackground-imageの画像を動的に変えたい時はuseHeadを使おう

2023/09/27に公開

<body>で背景画像を指定していて,それを動的に切り替えたい場合,Vue3/Nuxt3ならばuseHeadを使うのが良さそうです。

インストール方法

Vue3の場合

npm install unhead

Nuxt3の場合

同梱なので最初から使えます。

使用例

<script setup>
const userImage = ref(/hogehoge.png)
useHead({
  bodyAttrs: {
    style: computed(() => {
      if (userImage.value) {
        return "background-image: url('" + userImage.value + "')" //()内は形式に合わせて変更してください
      }
    })
  }
})
</script>

bodyAttrsstyleを変更すると,HTMLの出力としては<body style=hogehoge>となります。
computedを用いることで,動的に値を計算して出力するようにします。

classを変更すると失敗する

Tailwindcssを使っていると,styleよりもclassを先に使おうという考えになるので,

<script setup>
const userImage = ref(/hogehoge.png)
useHead({
  bodyAttrs: {
    class: computed(() => {
      if (userImage.value) {
        return `bg-[url('${userImage.value}')]`
      }
    })
  }
})
</script>

このように書くことになりますが,これだとブラウザコンソール上で<body>のclassが切り替わっているのは確認出来るものの,画像が出力されません。

なぜ失敗するかの考察

おそらくbodyが出力されるタイミングで,styleが適用されてないからだと思います。某TCGで言うならばタイミングを逃すと同じ概念です。

  • styleを切り替えた場合
    <body>を生成しようとする→styleを適用する<body>が生成される

  • classを切り替えた場合
    <body>を生成しようとする→styleを適用する→<body>が生成される→cssファイルが読みこまれる→対応するclassにstyleを適用する

bodyは一般的なコンポーネントとは異なり最初に生成されるため,直接styleで記述してあげないと画像パスにアクセスするタイミングを逃してしまい,画像が取得されないという結論になりました。間違っていたらごめんなさい。

あとがき

  • とりあえずuseHead()でbodyAttrsのstyleを変更すれば動く
  • 背景画像を動的に変更するのに取り組んだところ,ライフサイクルの概念や,renderについて学ぶいいきっかけになった
  • 解決に3時間くらいかかったので,これを見て将来の自分や他の人の時短になれば幸い

Discussion