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 は静的なままです。カスタムプロパティは、インラインスタイルによってコンポーネントのルート要素に適用され、ソース値が変更されるとリアクティブに更新されます。