Classes
We can add classes dynamically using the v-bind
directive on the class
attribute. It accepts an object being the keys the classes names and the values the boolean flags that determine if the class is added or not. It also accepts arrays of classes.
<script setup> import { ref, reactive } from 'vue' const isActive = ref(true) const hasError = ref(false) const classObject = reactive({ active: true, 'text-danger': false }) const error = ref({ type: 'fatal'}) const classComputedProperty = computed(() => ({ active: isActive.value && !error.value, 'text-danger': error.value && error.value.type === 'fatal' })) </script>
<template> <!-- The class attribute can receive an inline object, reactive objects, and computed properties. --> <div :class="{ active: isActive }"></div> <div :class="{ 'is-active': isActive }"></div> <div :class="classObject"></div> <div :class="classComputedProperty"></div> <!-- The dynamic classes are concatenated to existing classes. --> <div class="static" :class="{ active: isActive, 'text-danger': hasError }"></div> <!-- It also accepts array of classes. --> <div :class="[isActive ? activeClass : '', errorClass]"></div> <div :class="[{ [activeClass]: isActive }, errorClass]"></div> </template>
In custom components, the classes are concatenated to existing root element inside the component’s template.
<!-- Template in MyComponent.vue --> <template> <p class="foo bar">Hi!</p> </template> <!-- When added classes --> <MyComponent class="baz boo" /> <MyComponent :class="{ active: isActive }" /> <!-- Will render --> <p class="foo bar baz boo">Hi!</p> <p class="foo bar active">Hi!</p>
In case that component’s template had multiple root elements, we can determine which one takes the classes defined from parent component by using $attrs.class
.
<!-- Template in MyComponent.vue --> <template> <p :class="$attrs.class">Hi!</p> <span>This is a child component</span> </template> <!-- When added classes --> <MyComponent class="baz" /> <!-- Will render --> <p class="baz">Hi!</p> <span>This is a child component</span>
Styles
Similar to classes, styles can receive objects and arrays to determine dynamically the CSS properties to render and their values.
<script setup> import { ref, reactive } from 'vue' const activeColor = ref('red') const fontSize = ref(30) const styleObject = reactive({ color: 'red', fontSize: '30px' }) const baseStyles = reactive({ color: 'red' }) const overridingStyles = reactive({ color: 'black' display: 'flex' }) </script>
<template> <!-- The class attribute can receive an inline object, reactive objects, and computed properties. --> <div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div> <div :style="styleObject"></div> <div :style="{ 'font-size': fontSize + 'px' }"></div> <!-- Dynamic styles are concatenated to existing styles --> <h1 style="color: red" :style="'font-size: 1em'">hello</h1> <!-- Will render: --> <!-- <h1 style="color: red; font-size: 1em;">hello</h1> --> <!-- It can receive an array of objects. --> <div :style="[baseStyles, overridingStyles]"></div> <!-- Also every property can receive an array of multiple (prefixed) values. --> <!-- This will only render the last value in the array which the browser supports. --> <div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div> </template>
References