第27回 Vue.js入門 CSSモジュール

Wojciech KrakowiakによるPixabayからの画像 プログラミング

こんにちは、コンスキです。

今回はCSSモジュールというものについて説明します。

CSSモジュールとは

CSSモジュールとは、スコープ付きCSSと同じようにCSSをその単一ファイルコンポーネント内の要素だけに効かせることができる仕組みです。

前回説明したように、<style>要素にscoped属性をつけることで他の単一ファイルコンポーネントの要素にはCSSが効かないようにすることができます。

この方法の他に、<style>要素にmodule属性をつける方法でも、CSSをその単一ファイルコンポーネント内の要素だけに効かせることができます。

CSSモジュールの設定方法

CSSモジュールを使った単一ファイルコンポーネントの書き方は次のようになります。

<template>
  <要素名 v-bind:class="$style.class名"></要素名>
</template>
<style module>
  .適用する要素のclass名 {
  /* ここにこの単一ファイルコンポーネント内の要素だけに適用したいCSSを書きます */

  }
</style>

何が書かれているのか詳しく説明します。まずは<template>要素の部分です。

<template>
  <要素名 v-bind:class="$style.class名"></要素名>
</template>

普通であれば、「<要素名 class=”class名”></要素名>」のように書かれるのですが、CSSモジュールを使った場合は、v-bindディレクティブが使われてclass属性がバインドされていたり、見慣れない「$style」というプロパティが使われていたりします。

次に、<style>要素の部分です。

<style module>
  .適用する要素のclass名 {
  /* ここにこの単一ファイルコンポーネント内の要素だけに適用したいCSSを書きます */

  }
</style>

この部分は、scoped属性がmodule属性になっている以外は、スコープ付きCSSの設定の仕方と同じです。

<template>要素の中の要素には、「class=”class名”」のように書かれていないため、どのようにしてCSSを適用する要素を指定するのか疑問に思うかもしれません。

CSSモジュールを使う場合は、<template>要素の中の要素に「v-bind:class=”$style.class名“」のように書かれているため、この「class名」の部分を使って「.class名 { CSS }」のように書いてCSSを適用する要素を指定します。

例えば、<template>要素内に次のようなh1要素があったとします。

<h1 v-bind:class="$style.header"></h1>

この要素のclass名は「header」であるため、次のようにしてクラス名を指定してCSSを設定します。

<style module>
  .header {
    color: blue;
    text-decoration: underline;
  }
<style>

CSSモジュールを使った具体例をもう少し見てみましょう。

前回の「childComponent.vue」の中の<style scoped>の部分を<style style module>に変えてみます。

childComponent2.vue

<template>
  <div class="container">
    <h1 v-bind:class="$style.header">子コンポーネント(class="header")</h1>
    <div v-bind:class="$style.contents">
      <p>これは子コンポーネントの内容です。</p>
      <p>この内容には、子コンポーネントに設定したスタイルしか適用されません。(class="contents")</p>
    </div>
  </div>
</template>
<style>
.container {
  margin: 5px;
  padding: 5px;
  border: 1px solid black;
}
</style>
<style module>
.header {
 color: blue;
 }
.contents {
  text-decoration: underline;
  color: blue;
}
</style>

太字になっている部分が前回の「childComponent.vue」を変更した部分です。

CSSモジュールを使ったこのコンポーネントを、前回の「parentComponent.vue」というコンポーネントのimport文の部分だけを変えた「parentComponent2.vue」というコンポーネントの中で使います。

parentComponent2.vue

<template>
  <div class="container">
    <h1 class="header">親コンポーネント(class="header")</h1>
    <div class="contents">
      <p>これは親コンポーネントの内容です。</p>
      <p>この内容には、子コンポーネントで設定したスタイルが適用されません。(class="contents")</p>
    </div>
    <child-component></child-component>
  </div>
</template>
<script>
import ChildComponent from "./childComponent2"
export default {
  components: {
    ChildComponent
  }
}
</script>

コマンドラインツールで次のコマンドを使って、「parentComponent2.vue」をブラウザに表示させます。

cd parentComponent2.vueがあるフォルダのパス
vue serve parentComponent2.vue --open

すると次のようにブラウザに表示されると思います。

表示された内容は、前回、<style sccoped>の中にCSSを書いた場合と全く同じであることがわかると思います。

CSSモジュールが他のコンポーネントの要素に効かない仕組み

スコープ付きCSSの場合は、単一ファイルコンポーネントの中で要素に付けたclass名に加えて、自動で生成されるIDを使ってCSSを適用する要素を決めていました。

これによって他のコンポーネントに同じclass名が付いた要素があっても、単一ファイルコンポーネント内の要素だけにCSSが効くようにしていました。

CSSモジュールの場合は、単一ファイルコンポーネント内の要素のclass属性の属性値自体を変更することで、他のコンポーネントの要素に効かないようにしています。

Chrome DevToolsを使って、ブラウザに表示された先程のコンポーネントのHTMLを見てみましょう。

赤い四角で囲まれている部分が子コンポーネントの<template>要素に書かかれた部分です。

子コンポーネントには、「header」というclass名を付けた<h1>要素と、「contents」というclass名を付けた<div>要素があったはずです。

下の画像の赤い四角の部分を見て下さい。

しかし、ブラウザに表示したHTMLにかかれている、<h1>要素のclass名は、「childComponent2_header_3j1xp」になり、<div>要素のclass名は、「childComponent2_contents_AiXEn」に変わっています。

このことからわかるのは、実際にブラウザに表示する際には、module属性が付いた<style>要素の中で指定したclass名とは全くちがうclass名で表示されるということです。

このようにすることで、他のコンポーネントの要素に付いたclass名を使っても、そのその単一ファイルコンポーネント内の要素だけにCSSを効かせることができるようになっています。

$styleとは

module属性を付けた<style>要素の中にCSSを設定した際に、CSSを効かせる要素には次のように書きました。

<template>
  <要素名 v-bind:class="$style.class名"></要素名>
</template>

ここで急に出てきた「$style」というものは何なのでしょうか?

次のようなコンポーネントを作って、$styleをChrome DevToolsのConsoleに表示してみましょう。

forChecking.vue

<template>
  <div>
    <h1 :class="$style.sample">こんにちは!</h1>
  </div>
</template>
<script>
export default {
  created: function () {
    console.log(this.$style)
  }
}
</script>
<style module>
  .sample {
    color: blue;
    text-decoration: underline;
  }
</style>

コマンドラインツールで次のコマンドを実行します。

cd parentComponent2.vueがあるフォルダのパス
vue serve forChecking.vue --open

ブラウザにコンポーネントが表示されたら、Chrome DevToolsのConsoleを確認してみます。

$styleの正体は上のようなオブジェクトであることがわかります。

<style module>の中で指定したclass名をキーに持つプロパティが入っていますね。

このプロパティは値に自動で生成されたclass名が設定されています。

コンポーネントの<h1>要素に「v-bind:class=”$style.sample”」のように書いたことで、実際に表示されるHTMLの<h1>要素のclass名自動で生成されたclass名に変わったようです。

まとめ

今回わかったこと

  • CSSモジュールを使うことでも、コンポーネント内の要素だけにCSSを効かせる事ができる
  • $styleオブジェクトの中には、自動で生成されるIDが入っている

コメント

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