wandres.dev
NIVEL DIOS · Síntesis del CSS moderno

La hoja de estilos de 2026, de principio a fin

La arquitectura completa: el orden de capas y por qué ese, qué va exactamente en cada una, el reset que queda cuando el lenguaje ya resuelve casi todo, y cómo se carga sin romper el orden.

⏱ 21 min

Esta es la arquitectura entera de una hoja de estilos moderna, sin nada que sobre. No es una plantilla para copiar sino un conjunto de decisiones con su justificación, porque lo que hace que una arquitectura funcione no es su forma sino que todo el equipo sepa por qué cada cosa está donde está. Si de todo el track vas a releer una lección para arrancar un proyecto, probablemente sea esta.

🎯 Al terminar esta lección sabrás
  • Declarar un orden de capas y justificar la posición de cada una.
  • Decidir qué va en cada capa sin ambigüedad.
  • Escribir el reset mínimo que sigue haciendo falta en 2026.
  • Cargar el CSS por partes sin que el orden dependa de la red.

El orden de capas

Una sola línea, en la primera hoja que carga el documento, antes de cualquier otra cosa:

@layer tokens, reset, base, layout, componentes, utilidades;

Esa línea fija el orden de la cascada para todo el proyecto. A partir de ahí, en qué fichero esté cada regla, en qué orden lleguen los ficheros y qué especificidad tenga cada selector dejan de determinar quién gana. Es, con diferencia, la decisión de arquitectura con mejor relación entre coste y beneficio que puedes tomar.

flowchart TB
A[tokens - solo valores, ninguna regla visible] --> B[reset - normaliza el agente de usuario]
B --> C[base - elementos sin clase y tipografia]
C --> D[layout - las divisiones grandes de la pagina]
D --> E[componentes - la interfaz]
E --> F[utilidades - un proposito, ganan casi siempre]
F --> G[sin capa - emergencias y terceros, gana a todas]
style A fill:#cba6f7,color:#11111b
style B fill:#89b4fa,color:#11111b
style C fill:#89b4fa,color:#11111b
style D fill:#94e2d5,color:#11111b
style E fill:#a6e3a1,color:#11111b
style F fill:#f9e2af,color:#11111b
style G fill:#f38ba8,color:#11111b

La flecha se lee como “pierde contra”. Cada capa vence a todas las anteriores independientemente de la especificidad de sus selectores, y lo que está fuera de toda capa vence a todas.

Las razones de este orden concreto, capa por capa:

tokens primero porque son valores que todo lo demás debe poder sobrescribir. Si estuvieran al final, un componente no podría redefinir un token para su subárbol y todo el mecanismo de configuración descrito en los contratos de componente dejaría de funcionar.

reset antes que base porque el reset dice “olvida lo que trae el navegador” y base dice “esto es lo que traigo yo”. Invertirlos haría que el reset borrara tu propia tipografía.

layout antes que componentes porque un componente debe poder ajustar su propio espaciado dentro de una rejilla, y no al revés. Es la separación de estructura y contenido de OOCSS convertida en orden de cascada.

utilidades al final porque una utilidad se escribe precisamente para ganar. Esta capa es la que elimina el !important que ITCSS necesitaba, tal como se explicó en el nivel 50.

Fuera de las capas, nada tuyo. Ese espacio es el más fuerte del documento y conviene dejarlo reservado para dos cosas: las anulaciones de emergencia con fecha de caducidad, y el CSS de terceros que no puedes envolver.

⚠️
La primera mención fija el orden

Una capa queda colocada donde se la nombra por primera vez. Si un @import de una biblioteca crea utilidades antes de que tu declaración de orden se ejecute, el orden real no es el que escribiste. Por eso la línea @layer va la primera de todas, antes incluso de los @import, y por eso conviene envolver el CSS de terceros al importarlo: @import url(biblioteca.css) layer(terceros);

Qué va exactamente en cada capa

La regla de oro para que la arquitectura sobreviva es que la pregunta “¿dónde va esto?” tenga siempre una única respuesta. Estas fronteras la garantizan.

tokens. Solo asignaciones de custom properties. Ninguna regla visible, ni una. Los tres niveles —primitivos, semánticos y de componente— y la regla de dirección única que impide que un componente lea un primitivo. Es la única capa que puede generarse desde un fichero de definiciones sin intervención humana.

reset. Correcciones a la hoja del agente de usuario. Nada más. Si estás decidiendo un valor de diseño aquí, va en base.

base. Los elementos sin clase: la tipografía del documento, los encabezados, los enlaces, las listas, las tablas, la imagen fluida por defecto. Es la capa que decide cómo se ve el contenido que llega sin marcado tuyo —de un gestor de contenidos, de Markdown, de un editor— y por eso es la más importante en un sitio editorial y casi irrelevante en una aplicación.

layout. Las divisiones grandes: la rejilla de la página, el contenedor de ancho máximo, la disposición de cabecera, contenido y pie. Reglas sobre dónde van las cosas, nunca sobre qué aspecto tienen.

componentes. La interfaz. Cada componente con su bloque de tokens al principio, sus selectores envueltos en :where() para que su especificidad sea cero, y su estado gestionado por tokens y no por propiedades directas.

utilidades. Ayudantes de un solo propósito. Si usas un motor de utilidades, esta capa es su salida. Si no, es un puñado corto: la ocultación visual accesible, el corte de texto, el bloqueo de scroll.

El reset que queda en 2026

Los resets clásicos hacían tres cosas: corregir diferencias entre navegadores, imponer valores por defecto razonables y borrar los estilos del agente de usuario. La primera ya casi no hace falta —los motores convergieron— y la tercera es contraproducente, porque borrar los márgenes de los encabezados obliga a reponerlos todos.

Lo que queda es corto:

@layer reset {
  *, *::before, *::after { box-sizing: border-box; }

  :where(body, h1, h2, h3, h4, p, figure, blockquote, dl, dd) {
    margin: 0;
  }

  :where(body) {
    min-block-size: 100svb;
    line-height: 1.5;
  }

  :where(img, picture, video, canvas, svg) {
    display: block;
    max-inline-size: 100%;
  }

  :where(input, button, textarea, select) {
    font: inherit;
    color: inherit;
  }

  :where(p, h1, h2, h3, h4) {
    overflow-wrap: break-word;
  }

  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
      scroll-behavior: auto !important;
    }
  }
}

Cuatro decisiones merecen comentario.

:where() en casi todo. Especificidad cero, así que cualquier regla posterior gana sin esfuerzo. Un reset que hay que vencer es un reset mal escrito.

max-inline-size: 100% en los medios es, junto con box-sizing, la corrección que más desbordamientos horizontales evita en toda la web.

font: inherit en los controles es imprescindible: los controles de formulario no heredan la tipografía, la reciben del sistema, como se vio en el nivel 49.

El bloque de movimiento reducido lleva !important a propósito. Es una preferencia de accesibilidad del usuario y debe ganar a todo, incluido lo que esté fuera de las capas. Es de los pocos usos legítimos que quedan.

Y una nota sobre lo que no está: no hay normalización de listas ni de citas, porque borrar los marcadores de una lista sin reponer su semántica es un problema de accesibilidad conocido; no hay outline: none en ninguna parte, jamás; y no hay reglas de tipografía, que van en base.

Cargar sin romper el orden

La carga es donde las arquitecturas correctas se estropean en producción, y @layer resuelve el problema de raíz: una capa declarada antes sigue perdiendo aunque su CSS llegue después. Eso convierte la división de CSS en una decisión de rendimiento en lugar de en una apuesta.

La estructura que funciona:

<!-- critico: bloquea el render, va en linea o en un unico link -->
<link rel="stylesheet" href="/css/nucleo.css">

<!-- diferido: no bloquea, llega cuando llega -->
<link rel="stylesheet" href="/css/impresion.css" media="print">

El fichero crítico contiene la declaración de orden, los tokens, el reset, la base y el layout. Es pequeño, cambia poco y se cachea bien. Los componentes pueden llegar por su cuenta —por ruta, por componente, como decida tu empaquetador— porque su capa ya tiene su sitio reservado.

Tres reglas de carga que conviene no negociar:

Nada de cadenas de @import en producción. El navegador descubre el segundo fichero al parsear el primero: son viajes de red en serie donde deberían ser en paralelo. La única excepción es @import con layer() en un fichero que ya está en el camino crítico.

El atributo media no evita la descarga pero evita el bloqueo. Un link con media="print" se descarga con prioridad baja y no retrasa el primer pintado.

El CSS es el recurso más caro del camino crítico. Antes de optimizar cualquier otra cosa, mira el tamaño total del CSS que bloquea. Es lo que se discutió en el capítulo del coste real, y sigue siendo, en la mayoría de los sitios, el factor dominante.

Una arquitectura vale por las preguntas que deja de generar, no por las reglas que impone

Aquí está el criterio que conviene usar para juzgar esta arquitectura y cualquier otra que te propongan, incluida la que escribas tú. Un equipo pequeño y competente puede trabajar bien sin ninguna arquitectura, porque las cuatro personas que tocan el CSS se conocen y tienen el mismo modelo en la cabeza. La arquitectura empieza a valer cuando esa condición deja de cumplirse, y entonces su valor no está en lo que prohíbe sino en cuántas decisiones deja de haber que tomar en cada revisión de código. Con el orden de capas declarado, nadie discute nunca más sobre especificidad ni sobre orden de ficheros: la respuesta está en una línea que se lee en dos segundos. Con la regla de dirección única entre niveles de token, nadie discute qué variable usar. Con la frontera de cada capa bien definida, nadie discute dónde va una regla nueva. Esas discusiones son individualmente pequeñas y colectivamente enormes: son las que hacen que un cambio de dos líneas tarde tres días, y son la razón real por la que las hojas de estilo grandes se degradan, mucho más que cualquier defecto técnico. La prueba de que una arquitectura está funcionando no es que el CSS sea bonito: es que las revisiones de código dejen de hablar de CSS y pasen a hablar del producto. Si tu equipo sigue discutiendo dónde poner una regla, la arquitectura no está mal escrita, es que no está decidida, y ninguna cantidad de herramientas va a decidirla por ti.