こんにちは、コンスキです。
今回は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が入っている
コメント