本文へジャンプ

クラスとスタイルのバインディング

データバインディングは、HTML 要素に持たせる CSS クラスのリストやインラインのスタイルを自在に操作したいという、よくあるニーズに応えます。classstyle はどちらも属性なので、他の属性と同じように v-bind を使用して動的に文字列の値を割り当てることができます。しかし、文字列の連結を使ってこれらの値を生成しようとすると、手間がかかり、間違いが起きやすくなるものです。そこで、Vue では classstyle に対して v-bind を用いるとき、特別な拡張が利用できるようになっています。文字列のほかに、オブジェクトまたは配列として評価される式も利用できます。

HTML クラスのバインディング

オブジェクトへのバインディング

:classv-bind:class の省略記法)では、オブジェクトを渡して CSS クラスを動的に切り替えることができます:

template
<div :class="{ active: isActive }"></div>

上の構文は、コンポーネントのデータの isActive というプロパティが真値であるかどうかによって active という CSS クラスを含めるかどうかを決定する、という意味になります。

オブジェクトのフィールドを増やせば、複数のクラスをトグルすることができます。さらに、:class ディレクティブは通常の class 属性と共存させることもできます。例えば、次のような状態があるとします:

js
const isActive = ref(true)
const hasError = ref(false)
js
data() {
  return {
    isActive: true,
    hasError: false
  }
}

そしてテンプレートが次のようになっているとします:

template
<div
  class="static"
  :class="{ active: isActive, 'text-danger': hasError }"
></div>

このとき、レンダリング結果は次のようになります:

template
<div class="static active"></div>

isActivehasError が変化すると、それに合わせてクラスのリストも更新されます。例えば、hasErrortrue になればクラスのリストは "static active text-danger" に変わります。

バインドするオブジェクトはインラインにしなくても構いません:

js
const classObject = reactive({
  active: true,
  'text-danger': false
})
js
data() {
  return {
    classObject: {
      active: true,
      'text-danger': false
    }
  }
}
template
<div :class="classObject"></div>

レンダリング結果は以下になります:

template
<div class="active"></div>

オブジェクトを返す算出プロパティにクラスをバインドすることも可能です。次の例は、よく使われる強力なパターンです:

js
const isActive = ref(true)
const error = ref(null)

const classObject = computed(() => ({
  active: isActive.value && !error.value,
  'text-danger': error.value && error.value.type === 'fatal'
}))
js
data() {
  return {
    isActive: true,
    error: null
  }
},
computed: {
  classObject() {
    return {
      active: this.isActive && !this.error,
      'text-danger': this.error && this.error.type === 'fatal'
    }
  }
}
template
<div :class="classObject"></div>

配列へのバインディング

次のように :class を配列にバインドすると、クラスのリストを適用することができます:

js
const activeClass = ref('active')
const errorClass = ref('text-danger')
js
data() {
  return {
    activeClass: 'active',
    errorClass: 'text-danger'
  }
}
template
<div :class="[activeClass, errorClass]"></div>

レンダリング結果は次のようになります:

template
<div class="active text-danger"></div>

リストに含まれる特定のクラスを条件に基づいて切り替えたい場合には、三項演算子を使えば実現できます:

template
<div :class="[isActive ? activeClass : '', errorClass]"></div>

この場合、errorClass は常に適用され、activeClassisActive が真のときだけ適用されます。

しかし、条件を付けたいクラスが複数あると、これでは少し冗長になります。そこで、配列構文の中でオブジェクト構文を使うこともできるようになっています:

template
<div :class="[{ activeClass: isActive }, errorClass]"></div>

コンポーネントでの使用

このセクションは、コンポーネントについての知識があることを前提にしています。読み飛ばして、後で戻ってくるのでも大丈夫です。

ルート要素が 1 つだけのコンポーネントで class 属性を使用すると、そこで指定したクラスがコンポーネントのルート要素に追加され、すでに指定されている既存のクラスとマージされます。

例えば、MyComponent という名前のコンポーネントがあり、次のようなテンプレートになっているとします:

template
<!-- 子コンポーネントのテンプレート -->
<p class="foo bar">Hi!</p>

そして、コンポーネントを使う際にクラスをいくつか追加します:

template
<!-- コンポーネントを使用する時点 -->
<MyComponent class="baz boo" />

レンダリングされる HTML は次のようになります:

template
<p class="foo bar baz boo">Hi!</p>

クラスバインディングでも同様です:

template
<MyComponent :class="{ active: isActive }" />

isActive が真値のとき、レンダリングされる HTML は次のようになります:

template
<p class="foo bar active">Hi!</p>

コンポーネントに複数のルート要素を持たせているときは、どの要素にクラスを渡すか指定する必要があります。これは、以下のように $attrs コンポーネントプロパティを使って行います:

template
<!-- $attrs を使った MyComponent のテンプレート -->
<p :class="$attrs.class">Hi!</p>
<span>This is a child component</span>
template
<MyComponent class="baz" />

レンダリング結果は次のようになります:

html
<p class="baz">Hi!</p>
<span>This is a child component</span>

コンポーネントの属性の継承については、フォールスルー属性のセクションで詳しく説明しています。

インラインスタイルのバインディング

オブジェクトへのバインディング

:style では次のような JavaScript のオブジェクト値へのバインディングがサポートされ、HTML 要素の style プロパティ に対応します:

js
const activeColor = ref('red')
const fontSize = ref(30)
js
data() {
  return {
    activeColor: 'red',
    fontSize: 30
  }
}
template
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

CSS プロパティのキーにはキャメルケース(camelCase)が推奨されますが、:style では CSS の実際の書き方に対応するケバブケース(kebab-case)のキーもサポートされています。例:

template
<div :style="{ 'font-size': fontSize + 'px' }"></div>

テンプレートをすっきりさせるため、多くの場合、次のようにスタイルオブジェクトを直接バインドするとよいでしょう:

js
const styleObject = reactive({
  color: 'red',
  fontSize: '30px'
})
js
data() {
  return {
    styleObject: {
      color: 'red',
      fontSize: '13px'
    }
  }
}
template
<div :style="styleObject"></div>

スタイルへのオブジェクトのバインディングも、オブジェクトを返す算出プロパティと組み合わせて使用することが多くあります。

配列へのバインディング

:style は、複数のスタイルオブジェクトからなる配列にバインドすることができます。各オブジェクトはマージされ、同じ要素に適用されます:

template
<div :style="[baseStyles, overridingStyles]"></div>

自動プレフィックス

:styleベンダープレフィックスを必要とする CSS プロパティを指定すると、Vue が適切なプレフィックスを自動的に追加します。Vue は、実行時にブラウザーでどのスタイルプロパティがサポートされているかをチェックして、適切なものを追加します。特定のプロパティがブラウザーでサポートされていない場合、Vue はさまざまなプレフィックスのバリエーションをテストし、サポートされているものを見つけようと試みます。

複数の値

style プロパティには、プレフィックス付きを含む複数の値を、配列で指定することができます。例:

template
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>

このように指定すると、配列に含まれる値のうち、ブラウザーでサポートされる最後の値のみがレンダリングに使われます。この例では、接頭辞なしのバージョンのフレックスボックスをサポートするブラウザーでは、display: flex がレンダリングに使われます。

クラスとスタイルのバインディングが読み込まれました