Inicio / Artículos / De 66% a 185px: Cómo resuelven los navegadores los valores CSS antes del diseño

De 66% a 185px: Cómo resuelven los navegadores los valores CSS antes del diseño

Sigue el valor CSS a través de las etapas declarada, en cascada, especificada, calculada, utilizada y real, y comprende por qué las unidades relativas y el truco de conversión a rem se comportan de la manera en que lo hacen.

1920 palabras

Ganar la cascada no marca el final del recorrido de una declaración CSS. Aunque width: 50% supere a todas las reglas competidoras, el navegador aún no puede entregar 50% a su motor de maquetación; debe determinar qué representa el cincuenta por ciento en el contexto actual y convertirlo en un tamaño concreto. Esta guía sigue a un único valor a través de cada etapa de procesamiento definida en la especificación, muestra dónde se resuelven las unidades relativas como rem y los porcentajes, y explica el popular truco de conversión de px a rem junto con su limitación en términos de accesibilidad.

El valor que escribes no es el valor que se utiliza

Gran parte de lo que escribes en una hoja de estilos representa una relación más que una medida. Un ancho puede ser una parte del elemento padre:

width: 50%;

o, en otra regla, una parte diferente:

width: 66%;

El tamaño de la fuente puede ser relativo al tamaño de la fuente del elemento raíz:

font-size: 2rem;

y una altura puede ser una fracción de la ventana de visualización:

height: 50vh;

Ninguno de estos valores está expresado en píxeles, pero el diseño finalmente necesita dimensiones reales para decidir dónde irá cada elemento. Para superar esta diferencia, cada valor pasa por una serie fija de etapas:

Declared Value
      ↓
Cascaded Value
      ↓
Specified Value
      ↓
Computed Value
      ↓
Used Value
      ↓
Actual Value

A primera vista, los nombres parecen jerga técnica, pero cada etapa responde a una pregunta específica. Las secciones siguientes las explican en orden utilizando un único ejemplo continuo.

Valor declarado: lo que solicitaste

El valor declarado es simplemente el valor tal como aparece en una declaración. Dado:

width: 66%;

el valor declarado para width es 66%. Se trata de una solicitud, nada más. Un elemento puede tener fácilmente varios valores declarados para la misma propiedad provenientes de reglas diferentes, por lo que la primera tarea es elegir uno.

Valor en cascada: la declaración que sobrevive

Imagínese dos reglas que ambas establecen el ancho de un párrafo. Una utiliza un selector de tipo:

p {
  width: 100px;
}

y la otra utiliza una clase:

.amazing {
  width: 66%;
}

Si un párrafo lleva la clase amazing, ambas reglas se aplican a él. El selector de clase es más específico que el selector de elemento simple, por lo que la cascada elige:

width: 66%;

Ese 66% que sobrevive es el valor en cascada. Este paso es importante porque cada etapa posterior solo funciona con el ganador único; las declaraciones perdedoras se descartan en lugar de procesarse.

Valor especificado: asegurarse de que cada propiedad tenga uno

El valor especificado es el resultado de garantizar que cada propiedad en cada elemento tenga algún valor. La regla es sencilla:

  • si existe un valor en cascada, este se convierte en el valor especificado;
  • De lo contrario, para una propiedad heredada, el valor especificado es el valor calculado del padre;
  • De lo contrario, es el valor inicial de la propiedad, el valor predeterminado según la especificación.
  • En nuestro ejemplo existe un valor en cascada, por lo que el valor especificado sigue siendo 66% y esta etapa parece no hacer nada. Se vuelve importante para las propiedades sobre las que no se menciona ninguna regla, y ahí es donde entra en juego la herencia. Ese mecanismo se trata en la sección final.

    Valor calculado: resolver lo que se puede resolver sin diseño de la página

    El valor calculado es donde el navegador resuelve todo lo que puede determinar sin diseñar realmente la página. Las longitudes relativas basadas en los tamaños de fuente se convierten en longitudes absolutas, y las palabras clave se transforman en valores concretos. Considere:

    font-size: 2rem;
    

    La unidad aquí:

    2rem
    

    Describe una relación, “el doble del tamaño de fuente del elemento raíz”, en lugar de una medida fija. En la etapa de cálculo, el navegador busca el tamaño de fuente del elemento raíz y lo convierte en píxeles. Si el tamaño de fuente del elemento raíz es de 16px, el tamaño de fuente calculado será de 32px.

    Una razón por la que esta conversión ocurre en esta etapa es la herencia: el valor calculado es lo que heredan los elementos hijos, por lo que reciben una longitud concreta en lugar de una relación que tendrían que reinterpretar en su propio contexto. Por eso los tamaños de fuente em anidados se combinan de la manera en que lo hacen, y por qué las alturas de línea en porcentaje a veces generan texto ajustado en elementos hijos con fuentes más grandes.

    Algunos valores aún no pueden resolverse. Un ancho porcentual depende del tamaño del bloque contenedor, el cual no se conoce hasta que se define el diseño; por lo tanto, 66% generalmente permanece como un porcentaje en el valor calculado y solo se determina en la siguiente etapa.

    Valor utilizado: incorporación de información del diseño

    El valor utilizado es el resultado una vez que está disponible la información del diseño. Volver a:

    width: 66%;
    

    Por sí solo, un porcentaje es incompleto hasta que se sabe de qué representa una fracción. Para width, esa referencia es el ancho del bloque contenedor. Supongamos que la sección padre es:

    280px
    

    ancha. El navegador ahora puede calcular:

    66% of 280px
    

    lo cual da como resultado:

    184.8px
    

    Ese valor es el valor utilizado. Este es el punto de inflexión en el proceso: el navegador ya no mantiene el porcentaje que se especificó, sino una dimensión real derivada de la geometría actual de la página. Lo mismo ocurre con valores como los anchos auto, que solo tienen sentido una vez que se conoce el diseño general del entorno. Si consulta un elemento en JavaScript mediante getComputedStyle, muchas propiedades dependientes del diseño, como width, devuelven este valor en píxeles ya resuelto en lugar del porcentaje, lo cual es una forma útil de observar esta etapa en la práctica.

    Valor actual: adaptación a las limitaciones del dispositivo

    La última etapa tiene en cuenta los límites del entorno de renderizado. Un dispositivo no puede necesariamente dibujar un valor con precisión arbitraria, por lo que un valor utilizado como:

    184.8px
    

    puede terminar siendo renderizado aproximadamente así:

    185px
    

    Esa cifra ajustada es el valor real. En la práctica, los navegadores modernos distribuyen el contenido con precisión subpíxel y aplican redondeo o ajuste en diferentes momentos, dependiendo de la propiedad y del motor utilizado; por lo tanto, no hay que confiar en una regla de redondeo específica. La idea clave es simplemente que puede haber un ajuste final entre el valor calculado y lo que se muestra en la pantalla.

    En resumen, toda esta secuencia se reduce a una frase: lo que escribes en una hoja de estilos no necesariamente es lo que el navegador termina utilizando, y existen pasos bien definidos en el proceso.

    Por qué las unidades relativas pierden su misterio

    Este modelo explica por qué las unidades relativas son tan valiosas y, al mismo tiempo, tan a menudo malentendidas. Unidades como estas:

    %
    rem
    em
    vh
    vw
    

    Permite describir los tamaños en función de otro elemento (el padre, el tamaño de fuente raíz, el tamaño de fuente del propio elemento, la vista previa) en lugar de usar píxeles de forma fija. Eso es lo que hace que los diseños se adapten a diferentes pantallas y configuraciones de usuario.

    Cada una de ellas, sin embargo, debe resolverse con respecto a su referencia antes de que el diseño pueda utilizarla, y se resuelven en diferentes etapas: las unidades relativas a la fuente en la etapa de cálculo, y los porcentajes con respecto al bloque contenedor en la etapa de uso. Teniendo en cuenta este proceso, se puede reemplazar la idea vaga de que “el navegador lo resuelve por sí mismo” por una pregunta más precisa durante la depuración: ¿de qué depende este valor y cuál es esa referencia en este momento? Cuando un diseño responsive no funciona correctamente, la causa suele ser una referencia diferente a la que se asumió, como un porcentaje que se resuelve con respecto a un bloque contenedor inesperado, o un em que se compone a través de varios elementos anidados.

    Convierte px a rem con una raíz de 10px

    Comprender el procesamiento de valores también aclara un flujo de trabajo común para definir tamaños: convertir los valores de píxeles de un diseño a rem. Supongamos que un diseño especifica:

    padding: 30px;
    

    y preferirías expresarlo como:

    padding: 3rem;
    

    Un enfoque popular es establecer el tamaño de fuente raíz en un número redondo:

    html {
      font-size: 10px;
    }
    

    Con eso establecido:

    1rem = 10px
    

    las conversiones se convierten en cálculos mentales:

    30px → 3rem
    40px → 4rem
    20px → 2rem
    

    En general:

    rem = pixels / 10
    

    La ventaja no es solo contar con números más ordenados. Dado que cada rem se calcula en función del tamaño de fuente raíz en la etapa de cálculo, cambiar ese valor raíz reescala al instante todas las medidas basadas en rem de la página, lo que permite un control global único sobre el sistema de tamaños.

    Existe una advertencia importante. Establecer la raíz en un valor fijo de 10px anula el tamaño de fuente predeterminado que un usuario pueda haber elegido en la configuración de su navegador, lo cual socava una de las principales razones de accesibilidad para utilizar rem en primer lugar. Una alternativa ampliamente utilizada es html { font-size: 62.5%; }: con la configuración predeterminada de 16px del navegador, esto sigue dando como resultado 10px, pero se escala proporcionalmente cuando el usuario aumenta su tamaño preferido. Si adopta este patrón, recuerde también establecer un tamaño de fuente legible en body (por ejemplo, 1.6rem), ya que de lo contrario el texto volvería al tamaño reducido de la raíz.

    Cuando no se declara nada

    Hay una pregunta que queda sin responder con los pasos anteriores. Tenga en cuenta este marcado:

    <div class="parent">
      <p>Hello World</p>
    </div>
    

    y una regla en el contenedor:

    .parent {
      color: red;
    }
    

    No existe ninguna regla como esta en ningún lugar:

    p {
      color: red;
    }
    

    Pero el texto del párrafo es rojo. El párrafo no tiene una propiedad color en cascada, por lo que su valor especificado debe provenir de otro lugar. Dado que color es una propiedad heredada, el navegador utiliza el color calculado del elemento padre. Esto es herencia, y se integra directamente en la etapa de valor especificado descrita anteriormente. Para conocer con detalle qué propiedades se heredan, por qué los hijos reciben valores calculados en lugar de declarados, y cómo inherit y initial sobrescriben los valores predeterminados, la herencia merece un tratamiento dedicado.

    Puntos clave

    • Un valor CSS pasa por seis etapas: declarado, en cascada, especificado, calculado, utilizado y real.
    • La cascada reduce muchos valores declarados a un único valor en cascada; solo ese valor es procesado posteriormente.
  • El valor especificado recurre a la herencia o al valor inicial cuando no se declaró nada.
  • Las unidades relativas a la fuente, como rem y em, se convierten en longitudes absolutas en la fase de cálculo; los anchos porcentuales esperan al proceso de maquetación y se resuelven en la fase de uso.
  • El valor real puede ajustarse según las limitaciones del dispositivo, por lo que hay que evitar depender de un comportamiento de redondeo exacto.
  • El truco del valor base de 10px facilita la conversión a rem, pero 62.5% respeta mejor las preferencias de fuente del usuario que un valor fijo de 10px.
  • Lecturas relacionadas