Lo que me gusta de los estilos de escritura con Svelte | Programar Plus

Ha habido mucha publicidad bien merecida en torno a Svelte recientemente, con el proyecto acumulando más de 24,000 estrellas de GitHub. Posiblemente el marco de JavaScript más simple que existe, Svelte fue escrito por Rich Harris, el desarrollador detrás de Rollup. Hay muchas cosas que me gustan de Svelte (rendimiento, administración de estado integrada, escritura de marcas adecuadas en lugar de JSX), pero el gran atractivo para mí ha sido su enfoque de CSS.

Componentes de archivo único

​​

React no tiene una opinión sobre cómo se definen los estilos.
—Documentación de reacción​

​​​​

Un marco de interfaz de usuario que no tiene una forma integrada de agregar estilos a sus componentes no está terminado.
—Rich Harris, creador de Svelte

En Svelte, puede escribir CSS en una hoja de estilo como lo haría normalmente en un proyecto típico. También puede usar soluciones CSS-in-JS, como componentes con estilo y Emoción, si lo desea. Cada vez es más común dividir el código en componentes, en lugar de por tipo de archivo. React, por ejemplo, permite la colocación de un marcado de componentes y JavaScript. En Svelte, esto va un paso lógico más allá: el Javascript, el marcado y el estilo de un componente pueden coexistir en un único archivo `.svelte`. Si alguna vez ha usado componentes de un solo archivo en Vue, entonces Svelte le resultará familiar.

// button.svelte
<style>
  button {
    border-radius: 0;
    background-color: aqua;
  }
</style>

<button>
  <slot/>
</button>

Los estilos tienen un alcance predeterminado

De forma predeterminada, los estilos definidos dentro de un archivo Svelte tienen un alcance. Al igual que las bibliotecas CSS-in-JS o los módulos CSS, Svelte genera nombres de clase únicos cuando se compila para asegurarse de que los estilos de un elemento nunca entren en conflicto con los estilos de otro.

Eso significa que puede usar selectores de elementos simples como div y button en un archivo de componente Svelte sin necesidad de trabajar con nombres de clase. Si volvemos a los estilos de botón en nuestro ejemplo anterior, sabemos que un conjunto de reglas para <button> sólo se aplicará a nuestro <Button> componente: no a ningún otro elemento de botón HTML dentro de la página. Si tuviera varios botones dentro de un componente y quisiera diseñarlos de manera diferente, aún necesitaría clases. Las clases también serán abordadas por Svelte.

Las clases que genera Svelte parecen un galimatías porque se basan en un hash de los estilos de los componentes (p. ej. svelte-433xyz). Esto es mucho más fácil que una convención de nomenclatura como BEM. Sin embargo, es cierto que la experiencia de mirar estilos en DevTools es un poco peor ya que los nombres de las clases carecen de significado.

El marcado de un componente Svelte en DevTools.

No es una situación de uno u otro. Puede usar el estilo con ámbito de Svelte junto con una hoja de estilo normal. Yo personalmente escribo estilos específicos de componentes dentro de .svelte archivos, pero hacen uso de las clases de utilidad definidas en una hoja de estilo. Para que los estilos globales estén disponibles en toda una aplicación (propiedades personalizadas de CSS, animaciones CSS reutilizables, clases de utilidad, cualquier estilo de ‘reinicio’ o un marco CSS como Bootstrap), sugiero colocarlos en una hoja de estilo vinculada en el encabezado de su documento HTML. .

Nos permite crear estilos globales

Como acabamos de ver, puede usar una hoja de estilo regular para definir estilos globales. Si necesita definir estilos globales desde dentro de un componente Svelte, también puede hacerlo usando :global. Esta es esencialmente una forma de optar por no participar en el alcance cuando y donde lo necesite.

Por ejemplo, un componente modal puede querer alternar una clase para diseñar el elemento del cuerpo:

<style>
:global(.noscroll) {
  overflow: hidden;
}
</style>

Los estilos no utilizados están marcados

Otro beneficio de Svelte es que lo alertará sobre cualquier estilo no utilizado durante la compilación. En otras palabras, busca lugares donde los estilos están definidos pero nunca se usan en el marcado.

Las clases condicionales son concisas y sin esfuerzo.

Si el nombre de la variable JavaScript y el nombre de la clase son iguales, la sintaxis es increíblemente concisa. En este ejemplo, estoy creando accesorios modificadores para un botón de ancho completo y un botón fantasma.

<script>
  export let big = false;
  export let ghost = false;
</script>

<style>
  .big {
    font-size: 20px;
    display: block;
    width: 100%;
  }
  
  .ghost {
    background-color: transparent;
    border: solid currentColor 2px;
  }
</style>    
    
<button class:big class:ghost>
  <slot/>
</button>

una clase de ghost se aplicará al elemento cuando un ghost prop se utiliza, y una clase de big se aplica cuando un big se utiliza el apoyo.

<script>
  import Button from './Button.svelte';
</script>

<Button big ghost>Click Me</Button>

Svelte no requiere que los nombres de las clases y los nombres de las propiedades sean idénticos.

<script>
  export let primary = false;
  export let secondary = false;
</script>

<button
  class:c-btn--primary={primary}
  class:c-btn--secondary={secondary}
  class="c-btn">
  <slot></slot>
</button>

El componente de botón anterior siempre tendrá un c-btn class pero incluirá clases de modificadores solo cuando se pase el accesorio relevante, así:

<Button primary>Click Me</Button>

Eso generará este marcado:

<button class="c-btn c-btn--primary">Click Me</button>

Se puede pasar cualquier número de clases arbitrarias a un componente con una sola propiedad:

<script>
let class_name="";
export { class_name as class };
</script>

<button class="c-btn {class_name}">
  <slot />
</button>

Entonces, las clases se pueden usar de la misma manera que lo haría con el marcado HTML:

<Button class="mt40">Click Me</Button>

De BEM a Svelte

Veamos cuánto más fácil hace Svelte escribir estilos en comparación con una convención de nomenclatura CSS estándar. Aquí hay un componente simple codificado usando BEM.

.c-card {
  border-radius: 3px;
  border: solid 2px;
}

.c-card__title {
  text-transform: uppercase;
}

.c-card__text {
  color: gray;
}

.c-card--featured {
  border-color: gold;
}

Usando BEM, las clases se vuelven largas y feas. En Svelte, las cosas son mucho más simples.

<style>
div {
  border-radius: 3px;
  border: solid 2px;
}

h2 {
  text-transform: uppercase;
}

p {
  color: gray;
}

.featured {
  border-color: gold;
}
</style>

<div class:featured>
  <h2>{title}</h2>
  <p>
    <slot />
  </p>
</div>

Funciona bien con preprocesadores.

Los preprocesadores CSS se sienten mucho menos necesarios cuando se trabaja con Svelte, pero pueden funcionar perfectamente uno al lado del otro haciendo uso de un paquete llamado Svelte Preprocess. El soporte está disponible para Less, Stylus y PostCSS, pero aquí veremos Sass. Lo primero que tenemos que hacer es instalar algunas dependencias:

npm install -D svelte-preprocess node-sass

Luego necesitamos importar autoPreprocess en rollup.config.js en la parte superior del archivo.

import autoPreprocess from 'svelte-preprocess';

A continuación, encontremos la matriz de complementos y agreguemos preprocess: autoPreprocess() a esbelta:

export default {
  plugins: [
    svelte({
      preprocess: autoPreprocess(),
      ...other stuff

Luego, todo lo que tenemos que hacer es especificar que estamos usando Sass cuando estamos trabajando en un archivo de componente, usando type="text/scss" o lang="scss" a la etiqueta de estilo.

<style type="text/scss">
  $pink: rgb(200, 0, 220);
  p {
    color: black;
    span {
      color: $pink;
    }
  }
</style>

Valores dinámicos sin tiempo de ejecución

Hemos visto que Svelte viene con la mayoría de los beneficios de CSS-in-JS listos para usar, ¡pero sin dependencias externas! Sin embargo, hay una cosa que las bibliotecas de terceros pueden hacer que Svelte simplemente no puede: usar variables de JavaScript en CSS.

El siguiente código es no es válido y no funcionará:

<script>
  export let cols = 4;
</script>

<style>
  ul {
    display: grid;
    width: 100%;
    grid-column-gap: 16px;
    grid-row-gap: 16px;
    grid-template-columns: repeat({cols}, 1fr);
  }
</style>

<ul>
  <slot />
</ul>

Sin embargo, podemos lograr una funcionalidad similar mediante el uso de variables CSS.

<script>
  export let cols = 4;
</script>

<style>
  ul {
    display: grid;
    width: 100%;
    grid-column-gap: 16px;
    grid-row-gap: 16px;
    grid-template-columns: repeat(var(--columns), 1fr);
  }
</style>

<ul style="--columns:{cols}">
  <slot />
</ul>

He escrito CSS en todo tipo de formas diferentes a lo largo de los años: Sass, Shadow DOM, CSS-in-JS, BEM, atomic CSS y PostCSS. Svelte ofrece la API de estilo más intuitiva, accesible y fácil de usar. Si desea leer más sobre este tema, consulte el acertadamente titulado The Zen of Just Writing CSS de Rich Harris.

(Visited 9 times, 1 visits today)