En Vue.js, podemos usar clases de CSS y cambiarlas dinámicamente a nuestros componentes, permitiéndonos cambiar su estilo de forma reactiva.
De hecho, esta es la forma preferida y habitual que usaremos para aplicar y cambiar la estética de nuestros componentes de forma declarativa.
Vue nos ofrece un montón de herramientas para usar clases CSS a nuestros elementos, y cambiarlas en función de condiciones y variables reactivas.
Así que vamos a verlo en acción 👇
Importación de ficheros CSS
En primer lugar tenemos que saber cómo podemos importar ficheros CSS dentro de nuestros componentes de Vue. Vue.js nos permite importar ficheros CSS de distintas maneras.
Si queréis definir estilos que se apliquen a toda la aplicación, podéis importar directamente un fichero CSS en el archivo de entrada (main.js
o main.ts
):
import { createApp } from 'vue'
import App from './App.vue'
import './assets/styles/global.css' // Importación de estilos globales
createApp(App).mount('#app')
Los estilos definidos en este fichero se aplicarán a todos los componentes de la aplicación.
En este caso, global.css
debería estar ubicado en la carpeta src/assets/styles/
(o la estructura que prefiráis
Ya hemos visto que los componentes pueden tener una sección <style>
donde definir estilos CSS. Pues bien, también podemos importar un fichero CSS directamente
<template>
<div class="mensaje">Hola desde el componente</div>
</template>
<style src="@/assets/styles/mensaje.css"></style>
Esto importa el fichero mensaje.css
solo en el componente actual. Si queréis que los estilos sean scoped (aislados), podéis hacerlo así:
<style scoped src="@/assets/styles/mensaje.css"></style>
Aplicar estilos dinámicos con :class
La directiva :class
(abreviatura de v-bind
Es decir, que podemos aplicar, añadir, o eliminar clases en función de condiciones, estados o datos reactivos.
<template>
<div :class="claseDinamica">Este es un ejemplo de clase dinámica.</div>
</template>
<script setup>
import { ref } from 'vue';
const claseDinamica = ref('mi-clase');
</script>
En este ejemplo, la clase mi-clase
se aplica al div
porque claseDinamica
contiene el valor 'mi-clase'
.
Múltiples clases
Normalmente no tendremos que aplicar una única clase, si no combinaciones más complejas. Para ello tenemos distintas opciones,
Una de las formas más habituales para aplicar múltiples clases condicionalmente, es usar un objeto que contenga,
- Como propiedad el nombre de la clase que queremos aplicar
- Como valor un booleano que indica si se deba o no aplicar la clase.
<template>
<div :class="{ 'mi-clase': esActivo, 'otra-clase': tieneError }">
Este es un ejemplo de clases dinámicas.
</div>
</template>
<script setup>
import { ref } from 'vue';
const esActivo = ref(true);
const tieneError = ref(false);
</script>
En este ejemplo:
- La clase
mi-clase
se aplica siesActivo
estrue
. - La clase
otra-clase
se aplica sitieneError
estrue
.
También es posible aplicar varias clases simplemente proporcionado un array con las clases a aplicar.
<template>
<div :class="[claseBase, claseAdicional]">
Este es un ejemplo de clases dinámicas.
</div>
</template>
<script setup>
import { ref } from 'vue';
const claseBase = ref('base');
const claseAdicional = ref('adicional');
</script>
En este ejemplo, se aplicarían ambas clases (base
y adicional
) al div
.
Para lógica más compleja, puedes usar propiedades computadas:
<template>
<div :class="clasesCalculadas">
Este elemento tiene clases computadas
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const tema = ref('oscuro')
const tamano = ref('grande')
const estaHabilitado = ref(true)
const clasesCalculadas = computed(() => {
return {
'habilitado': estaHabilitado.value,
'deshabilitado': !estaHabilitado.value,
[`tema-${tema.value}`]: true,
[`tamano-${tamano.value}`]: true
}
})
</script>
Combinar clases estáticas y dinámicas
También podemos combinar fácilmente clases estáticas (que se aplican siempre) con clases dinámicas (que pueden variar).
Para eso usamos class
para las clases estáticas combinad con :class
para las clases dinámicas.
<template>
<div class="tarjeta" :class="{ 'destacada': esDestacada }">
Este es un ejemplo de clases combinadas.
</div>
</template>
<script setup>
import { ref } from 'vue';
const claseDinamica = ref('mi-clase');
</script>
Esta tarjeta siempre tendrá la clase “tarjeta” y condicionalmente “destacada”
Ejemplos prácticos
Cambiar el estilo de un botón en función del estado
Supongamos que queremos cambiar el estilo de un botón dependiendo de si está activo o desactivado.
<template>
<button :class="{ 'btn-activo': esActivo, 'btn-inactivo': !esActivo }" @click="toggleEstado">
{{ esActivo ? 'Activo' : 'Inactivo' }}
</button>
</template>
<script setup>
import { ref } from 'vue';
const esActivo = ref(true);
function toggleEstado() {
esActivo.value = !esActivo.value;
}
</script>
<style>
.btn-activo {
background-color: green;
color: white;
}
.btn-inactivo {
background-color: red;
color: white;
}
</style>
En este ejemplo, el botón cambia de color dependiendo de si está activo o inactivo.
Aplicar clases condicionales en una lista
Supongamos que queremos resaltar elementos de una lista en función de una condición.
<template>
<ul>
<li v-for="item in items" :key="item.id" :class="{ 'resaltado': item.activo }">
{{ item.nombre }}
</li>
</ul>
</template>
<script setup>
import { ref } from 'vue';
const items = ref([
{ id: 1, nombre: 'Item 1', activo: true },
{ id: 2, nombre: 'Item 2', activo: false },
{ id: 3, nombre: 'Item 3', activo: true },
]);
</script>
<style>
.resaltado {
background-color: yellow;
}
</style>
En este ejemplo, los elementos de la lista con activo: true
se resaltan con un fondo amarillo.