> Manuales > Manual de Lit

Aplicar estilos CSS en componentes Lit y en Web Components en general. En qué consiste la encapsulación del CSS, cómo aplicar estilos a través de la declaración style que afecten al template y a la etiqueta host del componente.

Estilos CSS en componentes Lit

Vamos a dar un giro radical en lo que respecta a la temática de los últimos artículos del Manual de Lit y comenzar a abordar otro tema importante del desarrollo de componentes, como son los estilos.

Por supuesto, el aspecto de los componentes es algo esencial para conseguir una experiencia de usuario cuidada y componentes que realmente encajen en el diseño de los sitios web, por lo que el CSS es algo que hay que trabajar convenientemente.

Como te puedes imaginar, existen muchas herramientas para gestión de los estilos en Lit, en el propio estándar de CSS y, por supuesto, en Web Components. Así que tenemos bastante que aprender. De momento vamos a abordar las cosas más básicas que debes de conocer para aplicar estilos a componentes de Lit y poco a poco iremos incorporando habilidades para mejora de los componentes.

Aplicar estilo CSS a los componentes

Comenzamos por aplicar estilos CSS, lo que podemos hacer con la propiedad estatica "styles". Esto ya lo hemos hecho repetidamente en los componentes que hemos desarrollado hasta el momento, por lo que no debería haber problema.

static styles = css`
    div {
      background-color: #f4f4f4;
    }
`;

Solo comentar que también puedes usar un código alternativo, por medio de un getter:

static get styles() {
    return css`
        span {
            border-radius: 0.3rem;
            background-color: #66e;
        }
    `
}

Una u otra manera de las vistas antes es indiferente. Para elegir entre ellas nos tendríamos que plantear que navegador pueda o no poder entenderlas. En este sentido cabe decir que el getter un poquito más antiguo en Javascript y por tanto soportado por más navegadores menos actualizados. Sin embargo, actualmente daría un poco igual y, además, como generalmente usamos herramientas de transpilación del código frontend, esas herramientas se encargarán de generar un código compatible con los navegadores usados comúnmente por los usuarios de Internet.

Los estilos están encapsulados en el Shadow DOM

Muy importante resulta decir que los estilos en Web Components están encapsulados dentro del Shadow DOM del componente. Esto quiere decir que:

Es una de las ventajas del desarrollo de componentes con el estándar Web Components, que no hay maneras de hacer interferencias del CSS global de la página, al menos interferencias no deseadas, ya que los estilos están ceñidos al ámbito del marcado del componente.

Algunos estilos como el tipo de letra sí que llegan a todas partes y se heredan en marcado de los componentes, igual que pasa generalmente en los elementos HTML. Por ejemplo, si definimos que la fuente es "arial" en el <body> se aplicará a todos los textos que haya en los componentes, a no ser que el propio componente tenga definido internamente otro tipo de letra, en cuyo caso tendría prioridad sobre el estilo global.

Técnicas para que el CSS global penetre en el shadow DOM

La encapsulación de los estilos generalmente es una ventaja a la hora de usar componentes que se puedan reutilizar en cualquier situación, con cualquier tipo de web. Sin embargo, también resulta una desventaja para muchos desarrolladores, ya que si usas un framework CSS como Bootstrap o Tailwind, los estilos definidos en ellos no penetrarán en los componentes.

Esto, sin embargo, tiene matices y existen técnicas que veremos en su momento para mitigar esta situación. A modo de resumen son las siguientes:

Como hemos dicho, algunas propiedades del CSS sí que penetran hacia dentro de los componentes, debido a la especificación del propio estándar CSS, como el color de la letra o el tamaño o font-family. Esto es algo totalmente normal y ocurre con todos los elementos de la página por lo que estás acostumbrado en tu día a día. Sin embargo, tú puedes redefinir estos estilos en el componente y, por supuesto, vencerán las declaraciones que hayas realizado dentro de ellos. Además, el estándar está publicando mejoras en este sentido que verán la luz en breve y que nos podrán permitir hacer uso mejor de las declaraciones de estilos globales.

Aplicar varias declaraciones de estilos en componentes Lit

En ocasiones ocurre que los estilos del componente pueden venir de varias declaraciones distintas. Por ejemplo, puedes tener unas clases CSS definidas en un módulo de Javascript que podrías importar y usar en varios componentes, de modo que evites duplicar tu código de estilos.

Esto lo puedes conseguir de manera sencilla, ya que la propiedad "styles" permite que le entregues un array con varias declaraciones.

static styles = [ 
  css`
    div {
      color: red;
    }
  `, 
  css`
    span {
      color: black;
    }
  `];

Como decimos, las declaraciones de estilos pueden llegar de un import.

import {formStyles} from '../../../styles/form-styles';

Luego podríamos usar esta declaración importada en el array de styles. Generalmente colocarás primero los estilos que vienen del módulo externo y luego los estilos que quieras incrementar en el componente. Al poner los estilos del módulo primero tendrás la oportunidad de redefinirlos de nuevo dentro del componente, ya que los estilos se van aplicando en cascada y los definidos más tarde en el array se aplicarían después.

static get styles() {
  return [
    formStyles, 
    css`
      :host {
        display: block;
        line-height: 1em;
      }
    `
  ];
}

Bindear valores las declaraciones de estilos

Aunque a decir verdad no es algo demasiado usado, a veces necesitamos hacer uso de las características de interpolación de propiedades dentro del CSS del componente.

const espaciado = css`0.5rem 1rem`;
static styles = css`
        .button {
            padding: ${espaciado};
            background-color: orange;
        }
`;

Sobre esta técnica debes saber:

No obstante, existe una posibilidad de uso de declaraciones CSS que no hayan pasado por el tagget template string "css", que es usar la directiva "unsafeCSS" de Lit.

Primero tendrías que importar esta directiva:

import { LitElement, html, css, unsafeCSS } from 'lit';

Luego la puedes usar de esta manera:

const espaciado = '0.5rem 1rem';

static styles = css`
        .button {
            padding: ${unsafeCSS(espaciado)};
            background-color: orange;
        }
`;

Muy importante! Esta directiva unsafeCSS se debe de usar solamente con alguna entrada en la que confíes, es decir, no puedes usarla a no ser que sepas seguro que nadie te puede inyectar código en la declaración.

Definición de estilos en la etiqueta del componente

Para acabar de abordar las cosas más básicas sobre estilos vamos a explicar una de las declaraciones más típicas a la hora de definir el CSS de un componente, :host.

En un componente puedes definir un CSS por medio de selectores que nos permiten aplicar estilos en todo lo que sería el marcado del componente, es decir en el template definido por render() y todos los subtemplates.

Pero hay un elemento que forma parte del propio componente pero que no está definido en el propio template: la propia etiqueta del componente.

Es decir, cuando usas un componente, como por ejemplo así:

<dw-loader active></dw-loader>

Tú puedes aplicar CSS a todos los elementos que había definidos en el template del componente, pero ¿qué pasa si le quieres aplicar estilos al componente completo, a toda la etiqueta dw-loader?

Desde fuera del componente sería muy fácil, porque podrías simplemente usar, por ejemplo, el selector de etiqueta así:

dw-loader {
  border: 1px solid black;
}

Pero dentro del componente no se conoce esa etiqueta dw-loader. Es algo que está en el contenido del HTML donde usas el componente, pero no en su template. Espero que se consiga entender la situación.

Entonces, cuando estás dentro del componente, si deseas aportar CSS a la propia etiqueta del componente, puedes usar el selector :host.

Esto es muy importante por ejemplo cuando queremos aplicar al componente el comportamiento de las etiquetas de bloque, ya que el display de los custom elements es por defecto inline. Así que, si nuestro componente tiene que comportase con un display block, es fundamental colocar el estilo siguiente.

static styles = css`
    :host {
        display: block;
    }
`;

Puedes aprender más sobre este tema en el artículo sobre el Selector CSS :host.

Pero puede ser igualmente importante para muchas reglas CSS que puedas necesitar aplicar a las etiquetas del componente, por ejemplo que tengan un margen en la parte de abajo.

static styles = css`
    :host {
        display: block;
        margin-bottom: 1.5rem;
    }
`;

Muchas veces me verás referirme a la etiqueta del componente como "etiqueta host", justamente por el nombre del selector CSS que usamos para aplicar estilos al componente en sí.

Conclusión

Hemos aprendido las cosas básicas para comenzar a trabajar con el CSS en nuestros componentes, aunque la verdad es que casi todo lo que hemos señalado ya lo habíamos usado de una u otra forma a lo largo de lo que llevamos de manual.

Este artículo no tiene componente de ejemplo, pero lo cierto es que cualquiera de los componentes que hemos hecho hasta ahora te sirven perfectamente como ejemplos, ya que hemos usado siempre algún CSS, aunque fuera poco.

En el siguiente artículo vamos a abordar ya prácticas sobre estilos CSS, viendo algo tan importante como son las variables CSS para personalizar el aspecto de los componentes al look & feel de los sitios donde se usen.

Miguel Angel Alvarez

Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...

Manual