Skip to content

Unidad 10: Estilizando Componentes en Vue.js

Objetivo: Aprender a aplicar estilos a los componentes en Vue.js utilizando archivos CSS externos, estilos globales y estilos scoped para mejorar la organización y apariencia de las aplicaciones.


10.1 Introducción a la Estilización en Vue.js

¿Por qué es importante la estilización en Vue.js?

La apariencia de una aplicación web es fundamental para mejorar la experiencia del usuario. En Vue.js, existen varias formas de aplicar estilos a los componentes, permitiendo tanto la reutilización de estilos globales como la encapsulación de estilos específicos para cada componente.

Métodos de estilización en Vue.js

Archivos CSS externos → Para definir estilos globales reutilizables.
Estilos dentro de los componentes (<style>) → Para encapsular estilos específicos en un solo archivo.
Scoped CSS → Para evitar conflictos de estilos entre componentes.


10.2 Uso de Archivos CSS Externos

Ejemplo de un archivo CSS externo (styles.css)

Ejemplo de styles.css

1
2
3
4
5
6
7
8
body {
font-family: Arial, sans-serif;
background-color: #f8f9fa;
}

h1 {
color: #333;
}

Importando el archivo CSS externo en main.js

Código de main.js

1
2
3
4
5
    import { createApp } from 'vue';
    import App from './App.vue';
    import './assets/styles.css';

    createApp(App).mount('#app');

Explicación:

  • Se define un archivo CSS global (styles.css) para estilos reutilizables.
  • Se importa en main.js para asegurarse de que se aplique a toda la aplicación.

10.3 Estilos Globales en Componentes de Archivo Único (SFC)

Los estilos globales pueden definirse directamente dentro de un componente Vue, afectando a toda la aplicación.

Ejemplo de estilos globales en App.vue

Código de App.vue con estilos globales

<template>
    <div id="app">
        <h1>Bienvenido a Vue.js</h1>
        <ToDoList />
    </div>
</template>
<script>
    import ToDoList from './components/ToDoList.vue';
    export default {
        components: { ToDoList }
        };
</script>
<style>
    #app {
    text-align: center;
    color: #2c3e50;
    margin-top: 20px;
}
</style>

Explicación: - La sección <style> en App.vue define estilos globales dentro del archivo Vue. - No se usa scoped, por lo que estos estilos afectan a toda la aplicación.


10.4 Estilos Específicos de Componente con Scoped CSS

Para evitar que los estilos de un componente afecten a otros, se puede utilizar el atributo scoped en la etiqueta <style>.

Ejemplo de Scoped CSS en ToDoList.vue

Código de ToDoList.vue con estilos scoped

<template>
  <div>
    <h2>Lista de Tareas</h2>
    <ul>
      <li v-for="(tarea, index) in tareas" :key="index" class="tarea-item">
        {{ tarea.texto }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tareas: [
        { texto: 'Aprender Vue.js' },
        { texto: 'Practicar con un proyecto' }
      ]
    };
  }
};
</script>

<style scoped>
    .tarea-item {
        background-color: #fff;
        border: 1px solid #ddd;
        padding: 10px;
        margin: 5px 0;
        border-radius: 5px;
    }
</style>

Explicación: - Se usa el atributo scoped para evitar que los estilos afecten a otros componentes. - Los estilos de .tarea-item solo se aplicarán dentro del componente ToDoList.vue.


10.5 Vamos a cambiar la apariencia de nuestra aplicación: ToDo

Por fin ha llegado el momento de mejorar la apariencia de nuestra aplicación. Exploraremos las diferentes maneras de aplicar estilo a los componentes de Vue con CSS.

Archivos de Estilos Externos

Para empezar, crea un archivo llamado reset.css en el directorio src/assets. Los archivos de esta carpeta son procesados ​​por webpack. Esto significa que podemos usar preprocesadores CSS (como SCSS) o posprocesadores CSS (como PostCSS).

Si bien este curso no utilizará dichas herramientas, es bueno saber que al incluir dicho código en la carpeta de activos, se procesará automáticamente.

Añade el siguiente contenido a reset.css:

Código de reset.css
/*reset.css*/
/* RESETS */
*,
*::before,
*::after {
    box-sizing: border-box;
}
*:focus {
    outline: 3px dashed #228bec;
}
html {
    font: 62.5% / 1.15 sans-serif;
}
h1,
h2 {
    margin-bottom: 0;
}
ul {
    list-style: none;
    padding: 0;
}
button {
    border: none;
    margin: 0;
    padding: 0;
    width: auto;
    overflow: visible;
    background: transparent;
    color: inherit;
    font: inherit;
    line-height: normal;
    -webkit-font-smoothing: inherit;
    -moz-osx-font-smoothing: inherit;
    appearance: none;
}
button::-moz-focus-inner {
    border: 0;
}
button,
input,
optgroup,
select,
textarea {
    font-family: inherit;
    font-size: 100%;
    line-height: 1.15;
    margin: 0;
}
button,
input {
    /* 1 */
    overflow: visible;
}
input[type="text"] {
    border-radius: 0;
}
body {
    width: 100%;
    max-width: 68rem;
    margin: 0 auto;
    font:
        1.6rem/1.25 "Helvetica Neue",
        Helvetica,
        Arial,
        sans-serif;
    background-color: #f5f5f5;
    color: #4d4d4d;
    -moz-osx-font-smoothing: grayscale;
    -webkit-font-smoothing: antialiased;
}
@media screen and (min-width: 620px) {
    body {
        font-size: 1.9rem;
        line-height: 1.31579;
    }
}
/*END RESETS*/

A continuación, en el archivo src/main.js, importa el archivo reset.css de la siguiente manera:

import "./assets/reset.css";

Esto hará que el archivo se seleccione durante el paso de compilación y se agregue automáticamente a nuestro sitio.

Importaante

Nota: Hemos de tener en cuenta que en las versiones previas de nuestra aplicación hemos estado utilizando estilos de Bootstrap. Si quieremos aplicar los estilos de este tema para ir viendo como se aplican dberíamos elimnar la importación de bootstrap en el archivo src/main.js, y quitar las clases de Bootstrap de los componentes. Sería recomendable hacer una copia de seguridad de nuestro proyecto antes de realizar estos cambios, por si queremos volver a Bootstrap.

Ahora si volvemos a mirar ya se deben haber aplicado los estilos de reset.css a nuestra aplicación.

Estilos de reset.css aplicados a la aplicación

Los cambios notables incluyen la eliminación de las viñetas de la lista, cambios en el color de fondo y cambios en el botón base y los estilos de entrada. Si hemos quitado las clases de 'Bootstrap' de los componentes, la apariencia de la aplicación será diferente.

Agregar estilos globales a componentes de archivo único

Ahora que hemos restablecido nuestro CSS para que sea uniforme en todos los navegadores, necesitamos personalizar un poco más los estilos. Hay algunos estilos que queremos aplicar en todos los componentes de nuestra aplicación. Aunque añadir estos archivos directamente a la hoja de estilos reset.css funcionaría, los añadiremos a las etiquestas <style> de App.vue para demostrar cómo se puede usar.

El archivo ya incluye algunos estilos. Eliminémoslos y reemplácelos con los estilos a continuación. Estos estilos permiten añadir estilo a botones y entradas, y personalizar el elemento #app y sus elementos secundarios.

Actualice el elemento <style> de su archuvo App.vue de su archivo para que se vea así:

Ejmeplo de estylos globales para ToDo

```html numlins="1" ```

Si revisas la aplicación, verás que nuestra lista de tareas pendientes ahora está en una tarjeta y que tenemos un mejor formato para nuestras tareas. Ahora podemos empezar a editar nuestros componentes para usar algunos de estos estilos.

Agregar clases de CSS en Vue

Debemos aplicar las clases CSS del botón <button> a nuestro componente ToDoForm. Dado que las plantillas de Vue son HTML válido, esto se hace de la misma manera que en HTML simple: añadiendo un atributo class="" al elemento.

Añade class="btn btn__primary btn__lg" al elemento <button> de tu formulario:

<button type="submit" class="btn btn__primary btn__lg">Add</button>

Ya que estamos aquí, hay un cambio semántico y de estilo más que podemos hacer. Dado que nuestro formulario representa una sección específica de nuestra página, podría beneficiarse de un elemento <h2>. Sin embargo, la etiqueta ya indica el propósito del formulario. Para evitar repeticiones, enciérrela con un <h2>. Hay otros estilos CSS globales que también podemos agregar. También agregaremos la calse input__lg a nuestro <input>.

Actualice su plantilla ToDoForm para que se vea así:

Plantilla ToDoForm

<template>
<form @submit.prevent="onSubmit">
    <h2 class="label-wrapper">
    <label for="new-todo-input" class="label__lg">
        What needs to be done?
    </label>
    </h2>
    <input
        type="text"
        id="new-todo-input"
        name="new-todo"
        autocomplete="off"
        v-model.lazy.trim="label"
        class="input__lg" />
        <button type="submit" class="btn btn__primary btn__lg">Add</button>
</form>
</template>

Agreguemos también la clase stack-large a la etiquete <ul> de nuestro App.vue. Esto ayudará a mejorar un poco el espaciado de nuestras tareas pendientes.

Actualízalo de la siguiente manera:

1
2
3
<ul aria-labelledby="list-summary" class="stack-large">
</ul>

Agregar estilos con ámbito (scoped styles)**

El último componente al que queremos aplicar estilo es nuestro compornente ToDoItem. Para mantener las definiciones de estilo cerca del componente, podemos añadir un elemento <style> dentro de él. Sin embargo, si estos estilos alteran elementos externos al componente, podría ser difícil identificar los estilos responsables y solucionar el problema. Aquí es donde el atributi scoped puede ser útil: asigna un data selector de atributos HTML único a todos los estilos, evitando que entren en conflicto globalmente.

Para usar el scopedmodificador, cree un elemento <style> dentro ToDoItem.vue, en la parte inferior del archivo, y asígnele un atributo scoped:

1
2
3
<style scoped>
  /* … */
</style>

A continuación, copie el siguiente CSS en el elemento <style> recién creado:

scoped css para ToDoItem
.todo-item {
background-color: #fff;
border: 1px solid #ddd;
padding: 10px;
margin: 5px 0;
border-radius: 5px;
}
.todo-item__label {
display: inline-block;
width: 100%;
font-size: 1.9rem;
}
.todo-item__label--complete {
text-decoration: line-through;
color: #999;
}
.todo-item__remove {
background-color: #ca3c3c;
color: #fff;
border: 0;
padding: 0.8rem 1rem 0.7rem;
cursor: pointer;
text-transform: capitalize;
}
.todo-item__remove:focus {
outline-color: #c82333;
}

Ahora necesitamos agregar algunas clases CSS a nuestra plantilla para conectar los estilos.

A la raíz <div>, agregue una clase custom-checkbox. Al elemento <input>, agregue una clase checkbox. Por último, agregue a <label> una clase checkbox-label. La plantilla actualizada se muestra a continuación:

1
2
3
4
5
6
<template>
  <div class="custom-checkbox">
    <input type="checkbox" :id="id" :checked="isDone" class="checkbox" />
    <label :for="id" class="checkbox-label">{{label}}</label>
  </div>
</template>

Ahora la aplicación debería verse así:

Aplicación con estilos personalizados

Resumen

Hemos terminado de diseñar nuestra aplicación de ejemplo. En el próximo tema, volveremos a añadir más funcionalidades a nuestra aplicación, concretamente, el uso de una propiedad calculada para añadir un recuento de tareas completadas.

10.6 Tarea Práctica: Implementación en el Proyecto del Blog

Objetivo: Aplicar estilos a los componentes del Blog utilizando estilos globales y Scoped CSS.

Pasos a seguir:
1️⃣ Definir un archivo CSS global (styles.css) e importarlo en main.js.
2️⃣ Aplicar estilos globales en App.vue para la estructura general del blog.
3️⃣ Utilizar Scoped CSS en BlogPost.vue para estilizar las entradas individualmente.


🔒 Solución del Blog (oculta inicialmente)

Código de styles.css

Código de styles.css
1
2
3
4
5
6
7
8
9
body {
font-family: Arial, sans-serif;
background-color: #f0f2f5;
}

.container {
max-width: 800px;
margin: 0 auto;
}

Código de BlogPost.vue

Código de BlogPost.vue con Scoped CSS
<template>
<div class="post-card">
    <h3>{{ titulo }}</h3>
    <p>{{ contenido }}</p>
</div>
</template>

<script>
export default {
props: {
    titulo: String,
    contenido: String
}
};
</script>

<style scoped>
.post-card {
background-color: white;
padding: 15px;
border-radius: 5px;
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
margin-bottom: 10px;
}
</style>

Código actualizado de App.vue

Código de App.vue
<template>
<div id="app">
    <h1 class="text-center">Blog con Vue.js</h1>
    <BlogList />
</div>
</template>

<script>
import BlogList from './components/BlogList.vue';
import './assets/styles.css';

export default {
components: {
    BlogList
}
};
</script>

Este ejercicio permitirá a los alumnos aplicar estilos globales y scoped en el Blog para mejorar su apariencia sin afectar otros componentes.