SFC CSS 機能
スコープ付き CSS
<style>
タグに scoped
属性が指定されている場合、その CSS は現在のコンポーネントの要素のみに適用されます。これは、Shadow DOM に見られるスタイルのカプセル化に似ています。これはいくつかの注意点がありますが、ポリフィルは必要ありません。これは、PostCSS を使って変換することで実現されます。次のコードは:
vue
<style scoped> .example { color: red; } </style> <template> <div class="example">hi</div> </template>
以下のように変換されます:
vue
<style> .example[data-v-f3f3eg9] { color: red; } </style> <template> <div class="example" data-v-f3f3eg9>hi</div> </template>
子コンポーネントのルート要素
scoped
を使用すると、親コンポーネントのスタイルが子コンポーネントに漏れることはありません。しかし、子コンポーネントのルートノードは親のスコープ付き CSS と子のスコープ付き CSS の両方の影響を受けることになります。これは、親コンポーネントがレイアウトのために子コンポーネントのルート要素のスタイルを設定できるようにするための設計です。
deep セレクター
scoped
スタイルのセレクターを "deep" にしたい場合、つまり子コンポーネントに影響を与えたい場合は、:deep()
擬似クラスを使用できます:
vue
<style scoped> .a :deep(.b) { /* ... */ } </style>
上記は次のようにコンパイルされます:
css
.a[data-v-f3f3eg9] .b { /* ... */ }
TIP
v-html
で作成された DOM コンテンツは、スコープ付きスタイルの影響を受けませんが、deep セレクターを使用してスタイルを設定可能です。
slotted セレクター
<slot/>
によってレンダリングされるコンテンツは、デフォルトでは親コンポーネントによって所有されていると見なされるため、スコープ付きスタイルの影響を受けません。明示的にスロットのコンテンツをターゲットにするには、:slotted
疑似クラスを使用します:
vue
<style scoped> :slotted(div) { color: red; } </style>
global セレクター
もし 1 つのルールだけをグローバルに適用したい場合は、別の <style>
を作成するかわりに、:global
疑似クラスを使用できます(以下を参照):
vue
<style scoped> :global(.red) { color: red; } </style>
ローカルスタイルとグローバルスタイルの混在
スコープ付きスタイルとスコープなしスタイルの両方を同じコンポーネントに含めることもできます:
vue
<style> /* グローバルスタイル */ </style> <style scoped> /* ローカルスタイル */ </style>
スコープ付きスタイルのヒント
スコープ付きスタイルでクラスが不要になるわけではありません。ブラウザーの様々な CSS セレクターのレンダリング方法により、
p { color: red }
をスコープ付きにした場合(つまり属性セレクターと組み合わせた場合)、何倍も遅くなります。その代わり、.example { color: red }
のようにクラスや ID を使用すれば、このパフォーマンス低下をほぼ排除できます。再帰的コンポーネントでの子孫セレクターに注意!
.a .b
というセレクターがある CSS ルールにおいて、.a
にマッチする要素が再帰的な子コンポーネントを含む場合、その子コンポーネントのすべての.b
がルールにマッチされます。
CSS モジュール
<style module>
タグは CSS モジュールとしてコンパイルされ、結果として得られる CSS クラスを $style
というキーの下にオブジェクトとしてコンポーネントに公開します:
vue
<template> <p :class="$style.red">This should be red</p> </template> <style module> .red { color: red; } </style>
生成されたクラスは衝突を避けるためにハッシュ化され、CSS を現在のコンポーネントのみにスコープするのと同じ効果を得ることができます。
グローバルの例外やコンポジションなどの詳細は、CSS モジュールの仕様を参照してください。
カスタム注入名
module
属性に値を与えることで、注入されるクラスオブジェクトのプロパティキーをカスタマイズできます:
vue
<template> <p :class="classes.red">red</p> </template> <style module="classes"> .red { color: red; } </style>
Composition API での使用
注入されたクラスは、useCssModule
API を介して setup()
や <script setup>
の中でアクセスできます。カスタム注入名を持つ <style module>
ブロックの場合、useCssModule
は最初の引数としてマッチする module
属性の値を受け取ります:
js
import { useCssModule } from 'vue' // setup() スコープの内側... // デフォルトでは <style module> のクラスを返します useCssModule() // 名前付きの例、<style module="classes"> のクラスを返します useCssModule('classes')
- 例
vue
<script setup lang="ts"> import { useCssModule } from 'vue' const classes = useCssModule() </script> <template> <p :class="classes.red">red</p> </template> <style module> .red { color: red; } </style>
CSS の v-bind()
SFC の <style>
タグでは v-bind
という CSS 関数を使用して、CSS の値をコンポーネントの動的な状態にリンクすることをサポートします:
vue
<template> <div class="text">hello</div> </template> <script> export default { data() { return { color: 'red' } } } </script> <style> .text { color: v-bind(color); } </style>
この構文は <script setup>
で動作し、JavaScript の式(引用符で囲む必要あり)をサポートします:
vue
<script setup> import { ref } from 'vue' const theme = ref({ color: 'red', }) </script> <template> <p>hello</p> </template> <style scoped> p { color: v-bind('theme.color'); } </style>
実際の値は、ハッシュ化された CSS カスタムプロパティにコンパイルされるため、CSS は静的なままです。カスタムプロパティは、インラインスタイルによってコンポーネントのルート要素に適用され、ソース値が変更されるとリアクティブに更新されます。