Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Class and style bindings

An element's look often depends on data: a finished task is struck through, the active filter button is highlighted. For this v-bind has a special mode for the class and style attributes — they accept an object or an array.

An object of classes

<!-- src/App.vue -->
<script setup>
import { ref } from 'vue'
 
const todos = ref([
  { id: 1, text: 'Buy bread', done: true },
  { id: 2, text: 'Call Anna', done: false },
])
</script>
 
<template>
  <ul>
    <li
      v-for="todo in todos"
      :key="todo.id"
      :class="{ done: todo.done }"
      @click="todo.done = !todo.done"
    >
      {{ todo.text }}
    </li>
  </ul>
</template>
 
<style scoped>
.done {
  text-decoration: line-through;
  color: #999;
}
</style>

The first task on the page is struck through and grey. Clicking a task toggles its done field, and the done class appears or disappears. The object key is the class name, the value is the condition.

Static and dynamic classes together

A static class and a bound :class are merged:

<li class="todo" :class="{ done: todo.done, urgent: todo.urgent }">
  {{ todo.text }}
</li>

A finished urgent task gets class="todo done urgent", an ordinary one only class="todo". Quote a class name with a hyphen: { 'is-active': active }.

An array of classes

An array is handy when the class name is stored in a variable:

<script setup>
import { ref } from 'vue'
 
const filter = ref('active')
</script>
 
<template>
  <button :class="['filter', filter === 'active' ? 'selected' : '']">
    Active
  </button>
</template>

The button has the classes filter selected while the active filter is chosen.

Style binding

:style takes an object of CSS properties. Names are written in camelCase, as in element.style from the tutorial:

<script setup>
import { ref } from 'vue'
 
const progress = ref(40)
</script>
 
<template>
  <div class="bar">
    <div :style="{ width: progress + '%', backgroundColor: '#42b883' }"></div>
  </div>
</template>

The inner block takes 40% of the bar's width and turns green. If progress changes, the width updates itself — this is how a task progress bar is made.

Which to choose

TaskApproach
Toggle a class on a condition:class with an object
A class from a variable:class with an array
A value computed in code — width, colour:style
Fixed stylingPlain CSS in style scoped

Prefer classes: the styling stays in CSS, and the template only switches it on.

Common mistake

Passing a conditional string to :class:

<li :class="todo.done ? done : ''">

Here done without quotes is a variable, not a class name, and it is undefined. The right form is :class="todo.done ? 'done' : ''" or, simpler, an object: :class="{ done: todo.done }".

Thanks for reading!

Donate to the site — we work hard for you.