En el artículo anterior vimos las formas generales de usar CSS en Astro. Sin embargo, hay casos muy concretos y dudas frecuentes donde lo anterior se puede quedar corto. Por ejemplo, ¿qué ocurre si queremos utilizar un dato de Javascript en el CSS de Astro? ¿Cuál es la mejor forma de hacerlo? ¿Cómo pasamos un estilo CSS desde un componente a otro?
Veamos algunas formas que pueden facilitarnos estas tareas.
Compartir clases por props
En el desarrollo web, la forma más extendida de dar estilo a los elementos es mediante clases. Es por ello, que probablemente, la forma más intuitiva sea utilizar el atributo class
. Astro, por defecto, no pasa los atributos class
de un componente a otro:
---
import "../components/Component.astro";
---
<Component class="danger" />
A pesar de haber indicado el atributo class
a nuestro componente, este no lo utilizará. Esto ocurre porque para Astro, el atributo class
es realmente una prop class
. Por lo que podemos aprovechar esto para reutilizarlo:
---
const { class: className } = Astro.props;
---
<div class={className}>
<p>...</p>
</div>
Observa que desde nuestro componente, obtenemos la prop class
y la asignamos a una variable className
, ya que class
es una palabra reservada de Javascript y no se puede utilizar. Luego, simplemente asignamos className
al atributo class
de nuestro HTML.
Definir clases con class:list
Ahora imaginemos que la información la tenemos en Javascript y queremos pasarla a nuestro componente. Podemos hacerlo de varias formas, pero los atributos class:list
son bastante interesantes en este escenario:
---
const list = ["container", "danger"];
const isDanger = true;
---
<div class:list={list}>
<p class:list={ red: isDanger }>
...
</p>
</div>
En este ejemplo tenemos lo siguiente:
- 1️⃣
class:list={list}
leerá el array y añadirá cada uno de los valores en una lista de clases. - 2️⃣
class:list={ red: isDanger }
leerá el objetoisDanger
y si es verdadero, añadiráred
como clase.
El código final quedaría algo similar a esto:
<div class="container danger">
<p class="red">
...
</p>
</div>
Definir variables con define:vars
Otra forma bastante habitual en relación a los estilos es utilizando Variables CSS. Veamos como podemos utilizarlas en nuestros componentes de Astro, obteniendo la información desde Javascript:
---
const backgroundColor = "indigo";
const color = "white";
---
<style define:vars={{ backgroundColor, color }}>
h1 {
background-color: var(--backgroundColor);
color: var(--color);
}
</style>
<h1>¡Hola, amigo!</h1>
Observa que utilizamos define:vars
para pasarle las variables que tenemos en Javascript. Astro obtiene esta informacíón y las convierte a variables CSS con el mismo nombre proporcionado, por lo que podemos utilizarlas sin problema.
Estilos en línea
Aunque suele ser preferible utilizar variables CSS siempre que sea posible, podemos utilizar estilos en linea de forma muy similar a lo anterior:
---
const backgroundColor = "indigo";
const color = "white";
---
<div style={{ backgroundColor, color }}>
<p>¡Hola, amigo!</p>
</div>
Estilos directos con is:inline
Como hemos visto hasta ahora, generalmente Astro procesa y revisa los estilos CSS haciendo ciertas modificaciones que generalmente son buenas para optimizar el rendimiento de nuestros componentes. Sin embargo, en algunas ocasiones, estas optimizaciones pueden entorpecer nuestros estilos o crear comportamientos que no buscamos debido a este procesamiento.
Podemos utilizar un atributo is:inline
en nuestros bloques <style>
para indicarle a Astro que no procese el CSS indicado en ese bloque, sino que lo inserte directamente en un <style>
en nuestro HTML.
Esto puede ser muy útil en algunas situaciones:
- 1️⃣ Necesitamos estilos CSS críticos que deben renderizarse prioritariamente.
- 2️⃣ Componentes que tienen muy pocos estilos y no merece la pena crear otro archivo
.css
. - 3️⃣ No depender de archivos
.css
externos.
Por otro lado, tiene algunas posibles desventajas:
- 💔 Los estilos son globales, no están scoped al componente.
- 💔 No permite utilizar
:global()
, ya que no es procesado por Astro. - 💔 Si usamos preprocesadores, no es preprocesado.