Inicio / Artículos / De la hoja de estilos a la pantalla: dónde encaja CSS en el proceso del navegador

De la hoja de estilos a la pantalla: dónde encaja CSS en el proceso del navegador

Sigue el proceso del CSS desde su descarga hasta los píxeles: cómo se construyen el DOM, CSSOM y el árbol de renderizado, dónde tiene lugar la cascada de estilos y qué fuentes de estilo compiten por cada elemento.

1733 palabras

La mayoría de los desarrolladores escriben CSS por intuición: cambian una propiedad, vuelven a cargar la página y revisan el resultado. Eso funciona hasta que alguna regla se niega misteriosamente a aplicarse, una página muestra contenido sin formato o un cambio de estilo “simple” hace que el desplazamiento sea intermitente. Cada uno de estos problemas se vuelve más fácil de comprender una vez que sabes qué hace realmente el navegador entre recibir la hoja de estilo y dibujar los píxeles.

Esta guía explica ese proceso a nivel general. Verás cómo el navegador convierte el HTML en el DOM, cómo las hojas de estilo se transforman en CSSOM, cómo ambos se combinan para formar un árbol de renderizado, dónde se resuelven las declaraciones conflictivas mediante la cascada y qué fuentes de estilo compiten por cada elemento. También es una pregunta frecuente en las entrevistas, generalmente formulada como “¿cómo funciona CSS en el fondo?”, y la respuesta que sigue te ofrece una forma estructurada de responder.

Paso uno: El HTML se convierte en el DOM

Cuando abre una URL, el navegador primero recibe el documento HTML. Analiza el marcado de arriba hacia abajo y, a medida que lo hace, construye el Modelo de Objetos de Documento. El DOM es un árbol que representa todo el documento: cada elemento es un nodo, y los nodos se relacionan entre sí como padres, hijos e hermanos, al igual que en un árbol genealógico. Todo lo que describe el HTML ahora reside en esta estructura, y también es lo que JavaScript lee y modifica.

El análisis se realiza de forma incremental. El navegador no espera a recibir todo el archivo antes de comenzar a crear nodos, y por eso puede detectar otros recursos mucho antes de que el documento haya terminado de descargarse.

Paso dos: las hojas de estilo se convierten en CSSOM

Mientras analiza el HTML, el navegador se encuentra con hojas de estilo, ya sea que estén enlazadas mediante <link rel="stylesheet"> en la sección head o incrustadas en elementos <style>, y también comienza a descargarlas y analizarlas. El CSS se procesa en su propia estructura en forma de árbol, el Modelo de Objetos CSS, o CSSOM. Desempeña el mismo papel para los estilos que el DOM desempeña para el marcado.

Convertir el CSS en estilos que puedan utilizarse para un elemento implica más trabajo que convertir HTML en nodos. Destacan dos tareas:

  1. Resolución de conflictos. Varias declaraciones suelen dirigirse a la misma propiedad en el mismo elemento. El navegador resuelve esos conflictos con un algoritmo llamado cascada.
  • Procesamiento de valores finales. La declaración del ganador puede indicar 2em, 50% o inherit, lo cual aún no es algo que el motor de maquetación pueda utilizar. El navegador convierte estos valores en cantidades concretas.
  • Estrictamente hablando, el CSSOM es la representación analizada de las hojas de estilo, y la cascada así como el cálculo de valores ocurren cuando el navegador calcula el estilo de cada elemento. Sin embargo, para tener una idea mental, es adecuado pensar en ello como “el CSS se analiza, se resuelven los conflictos, se definen los valores y el resultado se aplica a los elementos”.

    Una consecuencia práctica: como el navegador necesita los estilos antes de poder renderizar cualquier contenido, las hojas de estilo en el bloque head se procesan hasta que se han cargado y analizado. Por eso, las hojas de estilo grandes y lentas retrasan la primera pintura en la pantalla, y es por ello que mantener el CSS crítico de tamaño reducido es importante para el rendimiento.

    Paso tres: DOM y CSSOM se combinan en el árbol de renderizado

    Una vez que el marcado se ha analizado y formado parte del DOM y los estilos forman parte del CSSOM, el navegador combina ambos en un árbol de renderizado. Este árbol contiene los nodos que realmente se mostrarán, cada uno asociado a sus estilos calculados. Los nodos que no generan salida visual, como el contenido de <head> o los elementos con display: none, se excluyen.

    En este punto, el navegador sabe qué dibujar y cómo se estilizará cada elemento, pero aún no dónde irá cada cosa ni cuán grande será.

    Paso cuatro: el diseño y el modelo de formato visual

    Para convertir los nodos con estilo en cajas posicionadas, el navegador sigue lo que las especificaciones CSS denominan modelo de formato visual. Esta parte de las especificaciones CSS describe cómo se dispone la estructura del árbol de documentos para medios visuales como la pantalla de una computadora portátil o un teléfono. Aborda el modelo de cajas, el formato en bloque e en línea, los flotantes, la posición y las demás reglas que determinan el tamaño y la ubicación de cada caja.

    Una vez que el diseño ha calculado la geometría de cada caja, el navegador las dibuja, rellenándolas con texto, colores, bordes, imágenes y sombras, y el resultado final aparece en la pantalla.

    Toda la secuencia de procesamiento de un vistazo

    Al combinar las etapas se obtiene una secuencia sencilla que va desde el marcado hasta los píxeles. Cada flecha oculta una cantidad considerable de trabajo, pero el orden es lo que importa para analizar errores y el rendimiento:

    HTML
      ↓
    DOM
      ↓
    CSS
      ↓
    CSSOM
      ↓
    DOM + CSSOM
      ↓
    Render Tree
      ↓
    Layout
      ↓
    Paint
      ↓
    Pixels on the Screen
    

    Los navegadores reales superponen estos pasos e añaden otros (como capas de composición, por ejemplo), y cambiar un estilo posteriormente puede hacer que el navegador vuelva a calcular los estilos, volver a diseñar la interfaz o volver a pintarla, dependiendo de la propiedad en cuestión. Para conocer mejor esos costos, consulte cuánto cuesta al navegador cada cambio en CSS.

    Por qué las declaraciones entran en conflicto

    El resto de esta guía se centra en la primera de las dos tareas de procesamiento de CSS: la resolución de conflictos. El algoritmo responsable es la cascada. Combina todas las hojas de estilo que se aplican a un documento y, siempre que más de una declaración establezca la misma propiedad en el mismo elemento, decide cuál prevalece.

    Los conflictos son inevitables, y no solo porque su propia hoja de estilo pueda establecer el color de un enlace en dos lugares diferentes. Los estilos provienen de varias fuentes independientes, denominadas orígenes, y todas ellas se aplican a los mismos elementos al mismo tiempo.

    Estilos del autor

    Se trata de las declaraciones que usted y su equipo escriben: sus hojas de estilo, los bloques <style> y los atributos style en línea. En la mayoría de los sitios, son con diferencia la fuente más importante de reglas.

    Estilos del usuario

    La persona que visualiza la página también puede influir en los estilos. Los navegadores permiten a los usuarios ajustar configuraciones como el tamaño de fuente predeterminado, y algunos también admiten hojas de estilo personalizadas o extensiones que las aplican. Estas preferencias son especialmente importantes para la accesibilidad, ya que permiten a las personas con baja visión o dificultades de lectura adaptar la página a sus necesidades.

    Estilos del user-agent

    Finalmente, el navegador (el user-agent) incluye su propia hoja de estilo predeterminada. Por eso un elemento <a> sin estilos aparece en azul y subrayado, por qué los títulos están en negrita y son más grandes que el texto del cuerpo, y por qué <body> tiene un pequeño margen. Estos valores predeterminados se conocen como estilos del user-agent.

    Cuando la cascada combina las tres fuentes de estilos, la misma propiedad en el mismo elemento puede recibir fácilmente varios valores conflictivos, y el navegador necesita una forma determinista para elegir uno.

    Cómo decide la cascada

    La cascada compara las declaraciones conflictivas utilizando una secuencia fija de criterios, pasando al siguiente solo cuando el anterior resulte en un empate:

    1. Origen e importancia. De dónde proviene la declaración y si está marcada con !important.
    2. Especificidad. Cuán precisamente el selector apunta al elemento; un selector de ID tiene prioridad sobre uno de clase, que a su vez la tiene sobre un selector de tipo.
    3. Orden de origen. Si todo lo demás es igual, gana la declaración que aparece más tarde.

    Clasificación de los orígenes

    Para el primer criterio, el orden clásico de precedencia va de mayor a menor de la siguiente manera:

    1. Declaraciones del usuario marcadas con !important.
    2. Declaraciones del autor marcadas con !important.
    3. Declaraciones normales del autor.
  • Declaraciones de usuario normales.
  • Declaraciones de user-agent (valores predeterminados del navegador).
  • Tenga en cuenta lo que esto significa. Sus estilos habituales sobrescriben las preferencias normales del usuario y los valores predeterminados del navegador, lo cual es lo que le permite diseñar una página. Pero !important invierte el orden entre los usuarios y los autores: un usuario que realmente necesita una fuente más grande o un contraste mayor puede marcar esa preferencia como importante y anular incluso sus reglas !important. Los valores predeterminados del propio navegador quedan en último lugar y solo se aplican cuando nadie más indica lo contrario.

    El CSS moderno perfecciona esta estructura. La cascada actual también tiene en cuenta las capas de cascada (@layer), los estilos definidos por animaciones y transiciones en ejecución, así como las declaraciones !important de user-agent, que tienen prioridad sobre todas las demás declaraciones importantes. La lista simplificada anterior sigue reflejando la relación más relevante en el día a día; consulte la referencia de cascada de MDN mencionada anteriormente para conocer el orden completo.

    La especificidad y el orden de origen merecen un tratamiento detallado por separado, incluyendo cómo se comparan los pesos de los selectores y por qué !important suele causar más problemas de los que resuelve. Esto se aborda en cómo elige la cascada al ganador.

    Por qué este conocimiento es útil

    Comprender este proceso cambia la forma en que depuras y escribes estilos:

    • Las reglas que no se aplican son casi siempre pérdidas en cascada. Conocer el orden de origen, la especificidad y el orden de las fuentes te indica dónde buscar en lugar de recurrir a !important.
    • Los destellos de contenido sin estilos o con estilos aplicados tarde se deben a la naturaleza que bloquea la renderización de las hojas de estilo y a los estilos que llegan después de la primera renderización.
    • Interacciones defectuosas suelen deberse a cambios que obligan a que el layout o la pintura se ejecuten nuevamente, lo cual puedes evitar una vez que sepas en qué etapa afecta una propiedad.
    • CSS mantenible suele ser CSS con una especificidad baja y predecible, además de un orden de fuentes claro, lo que facilita su procesamiento tanto al navegador como a tus colegas.

    Conclusión

    El navegador convierte el HTML en DOM y las hojas de estilo en CSSOM, los combina para formar un árbol de renderizado con nodos visibles y estilizados, y luego utiliza el modelo de formato visual para organizar los cuadros antes de pintarlos. En la etapa del CSS, la cascada es el primer filtro: fusiona los estilos del autor, del usuario y del user-agent y resuelve cada conflicto según el origen e importancia, luego la especificidad y finalmente el orden de las fuentes. La siguiente etapa, en la que los valores ganadores se convierten en números concretos que el motor de layout puede utilizar, se explica en cómo resuelven los navegadores los valores CSS antes del layout.

    Lecturas relacionadas

  • De la barra de direcciones a los píxeles: cómo un navegador carga una página web — Una explicación sencilla para principiantes sobre la búsqueda DNS, la solicitud y respuesta HTTP, y cómo el navegador convierte HTML, CSS y JavaScript en la página que se muestra en pantalla.
  • Saltarse el renderizado fuera de la pantalla con content-visibility y contain-intrinsic-size — Aprenda cómo content-visibility: auto reduce los costos de diseño en páginas largas generadas por el servidor, por qué contain-intrinsic-size es necesario, y cómo se compara con la virtualización.