In Vue.js, we can use CSS classes and change them dynamically on our components, allowing us to change their style reactively.
In fact, this is the preferred and usual way we will use to apply and change the aesthetics of our components declaratively.
Vue provides us with a lot of tools to use CSS classes on our elements and change them based on conditions and reactive variables.
So let’s see it in action 👇
Importing CSS files
First, we need to know how we can import CSS files into our Vue components. Vue.js allows us to import CSS files in different ways.
If you want to define styles that apply to the entire application, you can directly import a CSS file in the entry file (main.js
or main.ts
):
import { createApp } from 'vue'
import App from './App.vue'
import './assets/styles/global.css' // Importing global styles
createApp(App).mount('#app')
The styles defined in this file will be applied to all components in the application.
In this case, global.css
should be located in the src/assets/styles/
folder (or the structure you prefer).
We have already seen that components can have a <style>
section where we define CSS styles. Well, we can also import a CSS file directly.
<template>
<div class="mensaje">Hello from the component</div>
</template>
<style src="@/assets/styles/mensaje.css"></style>
This imports the mensaje.css
file only in the current component. If you want the styles to be scoped (isolated), you can do it like this:
<style scoped src="@/assets/styles/mensaje.css"></style>
Applying dynamic styles with :class
The :class
directive (short for v-bind
That is, we can apply, add, or remove classes based on conditions, states, or reactive data.
<template>
<div :class="dynamicClass">This is an example of a dynamic class.</div>
</template>
<script setup>
import { ref } from 'vue';
const dynamicClass = ref('my-class');
</script>
In this example, the class my-class
is applied to the div
because dynamicClass
contains the value 'my-class'
.
Multiple classes
Normally, we won’t have to apply a single class, but rather more complex combinations. For this, we have different options,
One of the most common ways to apply multiple classes conditionally is to use an object that contains,
- As a property, the name of the class we want to apply
- As a value, a boolean indicating whether the class should be applied or not.
<template>
<div :class="{ 'my-class': isActive, 'another-class': hasError }">
This is an example of dynamic classes.
</div>
</template>
<script setup>
import { ref } from 'vue';
const isActive = ref(true);
const hasError = ref(false);
</script>
In this example:
- The class
my-class
is applied ifisActive
istrue
. - The class
another-class
is applied ifhasError
istrue
.
It is also possible to apply multiple classes simply by providing an array of classes to apply.
<template>
<div :class="[baseClass, additionalClass]">
This is an example of dynamic classes.
</div>
</template>
<script setup>
import { ref } from 'vue';
const baseClass = ref('base');
const additionalClass = ref('additional');
</script>
In this example, both classes (base
and additional
) would be applied to the div
.
For more complex logic, you can use computed properties:
<template>
<div :class="computedClasses">
This element has computed classes
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const theme = ref('dark')
const size = ref('large')
const isEnabled = ref(true)
const computedClasses = computed(() => {
return {
'enabled': isEnabled.value,
'disabled': !isEnabled.value,
[`theme-${theme.value}`]: true,
[`size-${size.value}`]: true
}
})
</script>
Combining static and dynamic classes
We can also easily combine static classes (which are always applied) with dynamic classes (which can vary).
For that, we use class
for static classes combined with :class
for dynamic classes.
<template>
<div class="card" :class="{ 'highlighted': isHighlighted }">
This is an example of combined classes.
</div>
</template>
<script setup>
import { ref } from 'vue';
const dynamicClass = ref('my-class');
</script>
This card will always have the class “card” and conditionally “highlighted”.
Practical examples
Change the style of a button based on state
Let’s suppose we want to change the style of a button depending on whether it is active or inactive.
<template>
<button :class="{ 'btn-active': isActive, 'btn-inactive': !isActive }" @click="toggleState">
{{ isActive ? 'Active' : 'Inactive' }}
</button>
</template>
<script setup>
import { ref } from 'vue';
const isActive = ref(true);
function toggleState() {
isActive.value = !isActive.value;
}
</script>
<style>
.btn-active {
background-color: green;
color: white;
}
.btn-inactive {
background-color: red;
color: white;
}
</style>
In this example, the button changes color depending on whether it is active or inactive.
Apply conditional classes in a list
Let’s suppose we want to highlight elements of a list based on a condition.
<template>
<ul>
<li v-for="item in items" :key="item.id" :class="{ 'highlighted': item.active }">
{{ item.name }}
</li>
</ul>
</template>
<script setup>
import { ref } from 'vue';
const items = ref([
{ id: 1, name: 'Item 1', active: true },
{ id: 2, name: 'Item 2', active: false },
{ id: 3, name: 'Item 3', active: true },
]);
</script>
<style>
.highlighted {
background-color: yellow;
}
</style>
In this example, the list elements with active: true
are highlighted with a yellow background.