# SFC スタイルの機能
# <style scoped>
<style>
タグが scoped
属性を持つとき、その CSS は現在のコンポーネントの要素にだけ適用されます。これは Shadow DOM に見られるスタイルのカプセル化に似ています。いくつかの注意点がありますが、ポリフィルは必要ありません。これは PostCSS を使った次のような変換で実現しています:
<style scoped>
.example {
color: red;
}
</style>
<template>
<div class="example">hi</div>
</template>
2
3
4
5
6
7
8
9
次のようになります:
<style>
.example[data-v-f3f3eg9] {
color: red;
}
</style>
<template>
<div class="example" data-v-f3f3eg9>hi</div>
</template>
2
3
4
5
6
7
8
9
# 子コンポーネントのルート要素
scoped
を使うと、親コンポーネントのスタイルは子コンポーネントに漏れません。しかし、子コンポーネントのルートノードは、親スコープの CSS と子スコープの CSS の両方が影響を受けます。これは親コンポーネントがレイアウトの目的で子コンポーネントのルート要素をスタイルできるようにするという設計のためです。
# ディープセレクタ
scoped
スタイルのセレクタを「深く」したい場合、例えば子コンポーネントに影響を与えたい場合は、:deep()
擬似クラスを使用できます:
<style scoped>
.a :deep(.b) {
/* ... */
}
</style>
2
3
4
5
上記は次のようにコンパイルされます:
.a[data-v-f3f3eg9] .b {
/* ... */
}
2
3
TIP
v-html
で作られた DOM コンテンツは、スコープ付きスタイルの影響を受けませんが、ディープセレクタを使ってスタイルすることができます。
# スロットセレクタ
デフォルトでスコープ付きスタイルは、親コンポーネントが所有しているコンテンツとみなして、<slot/>
でレンダリングされたコンテンツに影響を与えません。スロットのコンテンツを明示的に対象にするには、:slotted
擬似クラスを使用できます:
<style scoped>
:slotted(div) {
color: red;
}
</style>
2
3
4
5
# グローバルセレクタ
グローバルに 1 つのルールだけを適用したい場合、別の <style>
を作るのではなく、:global
擬似クラスを使用できます(後述):
<style scoped>
:global(.red) {
color: red;
}
</style>
2
3
4
5
# ローカルとグローバルのスタイル併用
スコープ付きとスコープなしのスタイルの両方を同じコンポーネントに含めることもできます:
<style>
/* グローバルスタイル */
</style>
<style scoped>
/* ローカルスタイル */
</style>
2
3
4
5
6
7
# スコープ付きスタイルのヒント
スコープ付きスタイルでもクラスが不要になるわけではないです。ブラウザがさまざまな CSS セレクタをレンダリングする方法のため、
p { color: red }
はスコープ付きの場合(例えば属性セレクタと合わせた場合)に何杯も遅くなります。.example { color: red }
のようにクラスや ID を代わりに使えば、このパフォーマンスへの影響をほぼ解消することができます。再帰的コンポーネントの子孫セレクタには注意が必要です!
.a .b
セレクタを使った CSS ルールでは、.a
に一致する要素に再帰的な子コンポーネントが含まれている場合、その子コンポーネントに含まれるすべての.b
がルールに一致してしまいます。
# <style module>
<style module>
タグは CSS Modules (opens new window) としてコンパイルされ、結果として得られる CSS クラスを $style
というキーの下にオブジェクトとしてコンポーネントに公開します:
<template>
<p :class="$style.red">
This should be red
</p>
</template>
<style module>
.red {
color: red;
}
</style>
2
3
4
5
6
7
8
9
10
11
この結果として得られるクラスは、衝突を避けるためにハッシュ化され、CSS を現在のコンポーネントだけにスコープするのと同じ効果を実現します。
Global exceptions (opens new window) や Composition (opens new window) などの詳細については CSS Modules の仕様 (opens new window) を参照してください。
# カスタム注入名
module
属性に値を指定することで、注入されたクラスオブジェクトのプロパティキーをカスタマイズできます:
<template>
<p :class="classes.red">red</p>
</template>
<style module="classes">
.red {
color: red;
}
</style>
2
3
4
5
6
7
8
9
# Composition API での使用
注入されたクラスは、useCssModule
API を介して setup()
や <script setup>
からアクセスできます。カスタム注入名のある <style module>
ブロックは useCssModule
が一致する module
属性の値を最初の引数として受け取ります:
// デフォルトでは <style module> を返します
useCssModule()
// 名前付きでは <style module="classes"> のクラスを返します
useCssModule('classes')
2
3
4
5
# 状態ドリブンな動的 CSS
SFC の <style>
タグは v-bind
CSS 関数を使って、CSS の値を動的コンポーネントの状態にリンクすることをサポートしています:
<template>
<div class="text">hello</div>
</template>
<script>
export default {
data() {
return {
color: 'red'
}
}
}
</script>
<style>
.text {
color: v-bind(color);
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
この構文は <script setup>
で動作して、JavaScript 式(引用符で囲む必要があります)をサポートしています:
<script setup>
const theme = {
color: 'red'
}
</script>
<template>
<p>hello</p>
</template>
<style scoped>
p {
color: v-bind('theme.color');
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
実際の値はハッシュ化された CSS カスタムプロパティにコンパイルされるため、CSS は静的なままです。このカスタムプロパティは、インラインスタイルを介してコンポーネントのルート要素に適用され、ソースの値が変更されるとリアクティブに更新されます。