DEV Community

Joel Humberto Gómez Paredes
Joel Humberto Gómez Paredes

Posted on

CSS @layer: ¿Héroe o amenaza?

La vida del developer es una vida donde siempre vas a estar aprendiendo. Ya sea por los cambios constantes del mercado, la organización, nuevas tools que te ayudan a hacer mejor tu trabajo, nuevas features que se remueven/agregan a la plataforma o alguna IA que te va a robar el trabajo (saludos al Devin XD)

Hoy vamos a hablar de @layer, una regla de CSS que viene a resolver uno de los tantos "problemas" que podemos tener en la creación de estilos ... "LA ESPECIFICIDAD".

En si no hay ningún problema pero cuando manejamos aplicaciones grandes es complicado manejar la especificidad. Si bien podemos usar metodologías para organizar nuestro CSS y controlar el origen y la especificidad; hay una pieza faltante que esta regla puede resolver ... definir la prioridad (sin usar !important) de manera consistente.

Meme: ah caray eso si me interesa

CSS at-rule @layer

@layer esta en baseline desde 2022, aunque en algunos Browsers de Android se agregó hasta marzo de 2024 (según caniuse).

Antes de continuar, quiero que hagamos 2 cosas simples:

  1. Cada vez que te veas el texto "Atinale al color", lee el código y responde cual color será el del elemento.
  2. Realiza el ejercicio y verifica la respuesta.

Para mi es como un juego, te podría sorprender y ciertamente hará esto menos aburrido.

Ahora si, haremos varios mini demos simples pero inquebrantables.

Primero crea un index.html con el siguiente contenido



<html>
  <head>
      <link rel="stylesheet" href="layer.css">
  </head>
  <body>
    <main class="main" />
  </body>
</html>


Enter fullscreen mode Exit fullscreen mode

Y ahora vamos crear un archivo layer.css y agregar el siguiente código



@layer {
  .main {
    background: blue;
  }  
}

.main {
  height: 50px;
}


Enter fullscreen mode Exit fullscreen mode

Atinale al color

SPOILER ALERT

..........

Creo que estuvo fácil o quizás no, es azul.

Y si cambias por este código?



@layer theme {
  .main {
    background: blue;
  }  
}

.main {
  height: 50px;
}


Enter fullscreen mode Exit fullscreen mode

Atinale al color

SPOILER ALERT

..........

Esto es juego de niños, es azul.

Meme: Y eso que decian que nunca iba a servir para nada

Ahora, un poco de explicación teoría aburrida. @layer es una CSS at-rule, quiere decir que esta internamente tiene un bloque de código y esta puede tener un nombre o no tenerlo.

Y si cambias por este código?



@layer theme {
  .main {
    background: blue;
  }  
}

@layer dummy {
  .main {
    background: red;
  }  
}

.main {
  height: 50px;
}


Enter fullscreen mode Exit fullscreen mode

Atinale al color

SPOILER ALERT

..........

Too easy, es rojo, seguramente te estas replanteando que haces aún aquí leyendo esto, vamos hacerlo más interesante. Cuando usas @layer, las declaraciones posteriores siempre tendrán mas prioridad que las primeras.



@layer theme {
  main.main {
    background: blue;
  }  
}

@layer dummy {
  .main {
    background: red;
  }  
}

.main {
  height: 50px;
}


Enter fullscreen mode Exit fullscreen mode

Atinale al color

Meme: asustado potter?

SPOILER ALERT

..........

Probablemente si nos basamos en la espeficidad tu respuesta fue azul, pero la regla @layer lo que predomina es el orden no la especificidad, incluso si agregaras un id en el selector del layer theme funcionaría igual (hazlo para que veas que no te miento).

Here we go again



@layer theme {
  .main {
    background: blue !important;
  }  
}

@layer dummy {
  .main {
    background: red;
  }  
}

.main {
  height: 50px;
}


Enter fullscreen mode Exit fullscreen mode

Atinale al color

SPOILER ALERT

..........

Recuerden, la cascada es la que determina que estilos se aplican. En esta se toma en cuenta la ubicación y la importancia. En este caso la @layer theme aplica un estilo con !important, eso hace que el orden e incluso la especificidad no importen.

Esto se puso mas interesante



@layer theme {
  .main {
    background: blue !important;
  }  
}

@layer dummy {
  .main {
    background: red !important;
  }  
}

.main {
  height: 50px;
}


Enter fullscreen mode Exit fullscreen mode

Atinale al color

Meme: por fin un digno oponente

SPOILER ALERT

..........

Seguro pensaste que era rojo, yo también lo pensé pero al parecer una layer que aplique un estilo con !important prevalecerá sobre otro que venga después, sin importar la especificidad. Es por eso que @layer puede ser héroe o villano. Aunque si usas layers, el uso de !important debería estar prohibido.

Esto se puso interesante



@layer dummy, theme;

@layer theme {
  .main {
    background: blue;
  }  
}

@layer dummy {
  .main {
    background: red;
  }  
}

.main {
  height: 50px;
}


Enter fullscreen mode Exit fullscreen mode

Atinale al color

SPOILER ALERT

Meme: tranquilo tampoco lo entendí a la primera

..........

@layer se puede declarar e inmediatamente colocar un bloque o puede declararse y posteriormente definir el bloque. El orden en que se definan le dara la prioridad. Recuerda las primeras siempre tendrán menos priordad que las últimas. Por ende el color es azul, aunque solo se hubiera puesto @layer dummy; hubiera dado el mismo resultado

Vamos con otro, ya casi llegamos al final



@layer theme {
  .main {
    background: blue;
  }  
}

@layer dummy {
  main.main {
    background: red;
  }  
}

.main {
  background: green;
  height: 50px;
}


Enter fullscreen mode Exit fullscreen mode

Atinale al color

SPOILER ALERT

..........

Y el color es ...

Meme: verde, verde como que?

Verde. Los estilos fuera de las capas tienen mayor prioridad que las que tienen capas, incluso aunque pusieras la declaración de estilos antes de la declaración de @layer tendría exactamente los mismos efectos, a menos que usaras !important. Lo cual agrega mayor prioridad, vamos intentalo.

Ok, ya estamos cerca del final, este es el último mini demo, respira hondo, vacia tu mente, deja que tu mente fluya por la cascada, se la cascada



@layer dummy, theme;

@layer theme {
  .main {
    background: blue !important;
  }
}

@layer dummy {
  main.main {
   background: red;
  }
}

main.main {
  background: green !important;
  height: 50px;
}


Enter fullscreen mode Exit fullscreen mode

Atinale al color

SPOILER ALERT

Meme: era yo azul

..........

Casi podría apostar que pensaste que era verde, es mas si lo pensaste mandame un tweet, mencioname en un post o lo que mas te agrade y pon "Yo también pensé que era verde". Pero es azul, recuerda !important define prioridad, pero cuando 2 estilos son importantes el origen de donde se declara tiene más relevancia.

Cada @layer puede tener incluso nested layer pero no abordaremos ese tema en este momento, porque ya me extendí y hay algo muy importante que debo decirte antes.

Bueno ahora la parte mas importante de este post, no es seguro usar este feature de momento si mantienes una misma base de código o estilos para mobile :(

Si bien esta disponible desde 2022, si una buena parte de tu mercado es Android probablemente no sea buena idea usarla, revisa caniuse y el tipo de usuarios que llegan a tus aplicaciones para saber si es seguro usarla.

En este caso @supports no nos va a servir, porque esta solo evualua si un estilo es válido no tiene soporte para at-rules. Este soporte esta en discusión, así que mientras tanto el uso de @supports at-rule(@layer) tiene un futuro incierto.

Podríamos usar Javascript para saber si tiene soporte



if (typeof CSSLayerBlockRule !== 'undefined') {
  console.log("Si tenemos soporte :D");
}


Enter fullscreen mode Exit fullscreen mode

Pero esto solo agregaría un blocker mas al parsing y al rendering, ademas de tener que generar estilos que soporten @layer y un fallback que no, mucha arquitectura que podría no valer la pena. Pero como dije, todo dependerá de nuestros usuarios.

Gracias por llegar hasta aquí, te dejo un pen con un código similar al del último mini demo, si puedes comparte y espero que hayas aprendido algo (aunque no vayas a usar esta feature)

Top comments (0)