Lesson 14 / 25

Class and Style Bindings, Scoped CSS

Dynamic appearance and component styles.

Objects, arrays and scoped styles

:class accepts a string, an object ({ active: isActive } adds the class when the value is truthy) or an array, and merges with a static class attribute. :style accepts an object of CSS properties in camelCase or kebab-case. In a Single-File Component, <style scoped> adds a unique data attribute so rules apply only to that component's elements; the root element of a child is also affected by the parent's scoped styles. Use the :deep() pseudo-class to target elements inside child components. v-bind() inside <style> links a CSS value to component state, and <style module> exposes CSS Modules through $style.

Dynamic classes, inline styles and scoped CSS

A status badge.

<script setup>
import { ref, computed } from 'vue'

const status = ref('error')
const size = ref(14)
const color = ref('#2563eb')

const badgeClass = computed(() => ({
  ok: status.value === 'ok',
  error: status.value === 'error',
}))
</script>

<template>
  <span class="badge" :class="badgeClass" :style="{ fontSize: size + 'px' }">
    {{ status }}
  </span>
  <div class="panel"><slot /></div>
</template>

<style scoped>
.badge { padding: 2px 8px; border-radius: 4px; border: 1px solid v-bind(color); }
.ok { background: #dcfce7; }
.error { background: #fee2e2; }
.panel :deep(a) { color: v-bind(color); }  /* reaches into child content */
</style>

Prefer classes over inline styles

Toggle classes defined in CSS for most visual states; reserve :style for truly dynamic values such as positions or user-chosen sizes.

Quick check: What does <style scoped> do?

  • Makes the styles global
  • Loads the CSS only on mobile
  • Inlines every rule as a style attribute
  • Limits the CSS rules to the component's own elements
Answer

Limits the CSS rules to the component's own elements — Vue adds a unique attribute to scope selectors.