Class and Style Bindings - 状態に応じた見た目の制御
ロードマップ: Vue.js学習ロードマップ
What(何についてか)
Vue では v-bind を class と style に対して使う際、単なる文字列だけでなく object や array を使って動的に見た目を制御できる。これにより、状態に応じた class の付け外しや inline style の変更を宣言的に記述できる。
Why(なぜ必要か)
文字列連結で class や style を組み立てると、条件分岐が増えた時に可読性が下がり、保守もしづらくなる。Vue の class/style binding は、状態と見た目の対応関係をデータ構造として表現できるため、テンプレートを簡潔に保ちながら UI の変化を明示的に記述できる。
特に、複数の状態に応じて見た目を切り替える実装では computed() と組み合わせることで整理しやすくなる。
How(どう動くか)
Class binding
:class には object または array を渡せる。
object 構文
<div :class="{ active: isActive, 'text-danger': hasError }"></div>- key: class 名
- value: その class を付与する条件
この構文は class名: 条件 の対応が明快であり、日常的な実装では最も使いやすい。
object を外に切り出す
const classObject = reactive({
active: true,
'text-danger': false
})<div :class="classObject"></div>条件が増えた時は template 直書きより整理しやすい。
computed と組み合わせる
const isActive = ref(true)
const error = ref(null)
const classObject = computed(() => ({
active: isActive.value && !error.value,
'text-danger': error.value && error.value.type === 'fatal'
}))<div :class="classObject"></div>class 条件が複数の state に依存する場合、class 自体を派生値として computed で表すのが有効である。
array 構文
<div :class="[activeClass, errorClass]"></div>複数の class 名をリストとして合成できる。さらに object 構文と混在も可能である。
<div :class="[{ [activeClass]: isActive }, errorClass]"></div>ただし日常的な実装では object 構文の方が読みやすいため、基本は object を主軸にし、array は補助的に扱うとよい。
Component に対する class
component に class を付けると、single root element を持つ子 component ではその root 要素に class がマージされる。
<MyComponent class="baz boo" />子 component が複数 root を持つ場合は、自動では適用先が決まらないため、$attrs.class を明示的に受け取る必要がある。
Style binding
:style には object または array を渡せる。
object 構文
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>CSS プロパティを JavaScript object として扱う。fontSize のような camelCase が推奨されるが、'font-size' のような kebab-case も使える。
style object を外に切り出す
const styleObject = reactive({
color: 'red',
fontSize: '30px'
})<div :style="styleObject"></div>template を薄く保ちたい時に有効である。複雑な条件では computed と組み合わせて style object を返す設計も自然である。
array 構文
<div :style="[baseStyles, overridingStyles]"></div>複数の style object を順にマージできる。ベースのスタイルに対して状態別の上書きを重ねる時に使いやすい。
静的属性との共存
class と :class、style と :style は共存でき、最終的にマージされる。
<h1 style="color: red" :style="'font-size: 1em'">hello</h1>ベンダープレフィックス
ベンダープレフィックスは、ブラウザごとの実験的・過渡期の CSS 実装に付いていた接頭辞である。
例:
-webkit--moz--ms-
これらは CSS プロパティ名に付く場合と、値に付く場合がある。
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;display: -webkit-box;
display: -ms-flexbox;
display: flex;Vue の :style では、複数値を配列で渡して、ブラウザが対応する最後の値を採用させる書き方ができる。
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>現代の実務ではビルドツールや Autoprefixer が吸収する場面も多く、初学段階で頻繁に意識する必要はない。
実務上の判断軸
- class は基本 object 構文でよい
- class 条件が複雑なら computed で object を返す
- array 構文は補助的機能として知っておけば十分
- style は object 構文が基本
- style の array 構文はベース + 上書きの合成で有効
- component への class 継承は root 要素へ適用されると理解しておけば学習初期は十分
Options API → Composition API 差分(補足)
| 項目 | Options API(旧) | Composition API(新) |
|---|---|---|
| class 条件 | :class は同じだが state 参照は this.isActive | ref / computed を直接参照する |
| style 条件 | data() / computed で style object を返す | reactive() / computed() で style object を返す |
| ロジックの配置 | data, computed に分散しやすい | <script setup> で近接配置しやすい |
Key Concepts
| 用語 | 説明 |
|---|---|
:class | class 属性を動的にバインドする仕組み |
| object 構文 | class名: 条件 の対応で class を制御する書き方 |
| array 構文 | 複数 class / style をリストとして合成する書き方 |
:style | inline style を動的にバインドする仕組み |
| class merging | 静的 class と動的 class が最終的に統合されること |
| style merging | 複数の style 指定が最終的に統合されること |
| vendor prefix | ブラウザ固有の過渡的 CSS 記法に付く接頭辞 |