Skip to content
This page has been auto-translated and may contain errors.View in English

Dimensionamiento y unidades

docs.scrimba.com

Estableces un tamaño de fuente en píxeles, publicas la página, y un lector que ha aumentado el texto de su navegador para mayor comodidad no ve ningún cambio. Le das a una tarjeta un ancho fijo y se desborda en un teléfono. Ambos casos se reducen a la misma pregunta: cuando escribes un número en CSS, ¿contra qué se mide ese número? Algunas unidades son fijas, algunas se escalan a una fuente, algunas se escalan al padre, y algunas se escalan a la pantalla. Una vez que sabes cuál es cuál, dejas de adivinar y empiezas a elegir la unidad que hace el trabajo.

Unidades absolutas versus relativas

Las unidades de CSS se dividen en dos familias. Una unidad absoluta es un tamaño fijo que nunca cambia: px (un píxel) es la que encontrarás en todas partes. Una unidad relativa es un tamaño que se escala a otra cosa, como el tamaño de fuente del lector o el ancho de la pantalla.

Piensa en medir una habitación. Los centímetros son absolutos: una pared mide 400 cm si eres alto o bajo. "Tres de mis pasos" es relativo: depende de quién esté caminando. Las unidades absolutas te dan control exacto; las unidades relativas permiten que la página se adapte a la persona que la observa.

Esa adaptación importa. Algunos lectores establecen un tamaño de texto predeterminado más grande porque es más fácil para sus ojos. Si dimensionas tu texto en una unidad relativa, su configuración se mantiene y la página crece para adaptarse a ellos. Si lo bloqueas en píxeles, se queda igual e los ignora.

Cada longitud en CSS es absoluta o relativa, y la diferencia decide si tu diseño puede adaptarse. Una unidad absoluta se resuelve a un tamaño fijo independientemente del contexto: px es la única unidad absoluta que usarás en la práctica, ya que cm, pt y el resto están dirigidos a impresión. Una unidad relativa se resuelve contra una referencia, y cuál referencia depende de la unidad: rem y em se escalan a un tamaño de fuente, % se escala al padre, vw y vh se escalan a la ventana gráfica.

La razón para preferir unidades relativas para la mayoría del dimensionamiento es la accesibilidad y la capacidad de respuesta. Cuando un lector aumenta el tamaño de fuente predeterminado de su navegador, cualquier cosa dimensionada en rem crece con él, mientras que cualquier cosa fija en px se queda en su lugar y puede romper el diseño alrededor de ella. Lo mismo ocurre en diferentes tamaños de pantalla: las unidades relativas permiten que una hoja de estilos se ajuste a un teléfono y a un monitor, que es la base para el diseño responsivo.

La unidad que elijas es una decisión sobre a qué está anclado tu número, y ese ancla es lo que determina si el diseño responde al lector o lo ignora. Una unidad absoluta se resuelve a la misma longitud calculada en cada contexto. En CSS para pantalla eso es efectivamente solo px: las unidades físicas (cm, mm, in, pt, pc) se definen en relación al píxel de todas formas (1in es 96px por definición) y pertenecen a hojas de estilos de impresión. Una unidad relativa se resuelve contra una referencia que puede cambiar, lo que permite que se adapte.

La referencia es lo importante, así que vale la pena nombrar a qué apunta cada unidad relativa. rem y em son relativas a fuente: se resuelven contra un tamaño de fuente (el de la raíz o el del elemento). % es relativa al padre para la mayoría de propiedades: un ancho de porcentaje es una fracción del ancho del bloque contenedor. vw y vh son relativas a la ventana gráfica: una fracción de la ventana gráfica del navegador (el área visible de la página). La regla práctica surge de esto: dimensiona el tipo y el diseño en unidades relativas, mantén px para lo que no debe escalar. Un lector que establece un tamaño de fuente predeterminado más grande o amplía la página mueve la referencia a la que apuntan las unidades relativas, por lo que la página crece para satisfacerlos; un valor px no tiene referencia que mover y se queda en su lugar, que es el fallo de accesibilidad que estás intentando evitar.

JunoUnidades absolutas versus relativas Las unidades absolutas como px son un tamaño fijo que nunca cambia. Las unidades relativas se escalan a algo más, como el tamaño de fuente del lector o el ancho de pantalla. Las unidades relativas permiten que la página se adapte a la persona que la observa, por lo que importan para los lectores que establecen un tamaño de texto más grande.
JunoUnidades absolutas versus relativaspx es la única unidad absoluta que realmente usarás; todo lo demás se escala a una referencia. rem y em se escalan a una fuente, % al padre, vw y vh a la ventana gráfica. Usa unidades relativas para que la página crezca cuando un lector aumente su tamaño de fuente predeterminado, en lugar de ignorarlo.
JunoUnidades absolutas versus relativas Cada unidad es un número más un ancla, y el ancla decide si el diseño puede responder. px no tiene ancla que mover, así que nunca se adapta; rem y em se anclan a una fuente, % al padre, vw y vh a la ventana gráfica. Dimensiona el tipo y el diseño en unidades relativas y mantén px para las partes que deben permanecer fijas.

Píxeles y cuándo están bien

Un píxel (px) es una pequeña unidad de longitud fija. Es la más directa de razonar, porque 16px siempre es 16px. Eso la hace una buena opción para cosas pequeñas que deben mantener el mismo tamaño sin importar qué: el grosor de un borde, una pequeña esquina redondeada, un icono fijo.

css
.card {
  border: 1px solid #ccc;      /* un borde fino, siempre 1px */
  border-radius: 8px;          /* una esquina redondeada fija */
}

El inconveniente es que un píxel no se preocupa por el lector. Si alguien ha configurado su navegador para mostrar texto más grande, un encabezado bloqueado en 24px se queda en 24px e ignora su elección. Por eso px es una buena opción para bordes y pequeños detalles, pero no es la unidad que quieres para el texto.

px es la unidad que debes usar cuando quieres una longitud que se quede en su lugar: bordes, divisores finos, radios fijos pequeños, y el ocasional icono que no debe escalar. Para esos, su fijeza es el punto. Un borde 1px que creciera con el tamaño de fuente del lector se vería mal, así que fijarlo es correcto.

css
.card {
  border: 1px solid #ccc;      /* permanece como hairline independientemente del tamaño de fuente */
  border-radius: 8px;
  padding: 1rem;               /* pero el espaciado interior se escala con el tipo */
}

El inconveniente es la razón para no dimensionar texto en él. Un lector puede establecer un tamaño de fuente predeterminado más grande en su navegador para comodidad o accesibilidad, y px lo anula: un encabezado font-size: 18px se renderiza en 18 píxeles sin importar si su predeterminado es 16 o 24. Así que usa px para los detalles fijos y cambia a una unidad relativa a fuente para cualquier cosa que deba respetar la configuración del lector, que la siguiente sección cubre.

El px de CSS no es un píxel de dispositivo físico; es un píxel de referencia, una unidad angular que el navegador escala para que 1px se lea con un tamaño aparente consistente en diferentes densidades de pantalla. En una pantalla de alta densidad, un píxel CSS se asigna a varios píxeles de dispositivo, que es por qué un borde 1px permanece como una línea fina nítida en lugar de desaparecer. Esa fijeza hace que px sea la opción correcta para cosas que no deben rastrear el tamaño de fuente del lector: bordes, divisores 1px, radios pequeños, offsets box-shadow, y detalles finos.

css
.card {
  border: 1px solid #ccc;      /* línea fina fija; escalarla se vería mal */
  border-radius: 8px;
  padding: 1rem;               /* el espaciado interior rastrea el tipo en su lugar */
}

El modo de fallo es dimensionar texto en px. Establecer font-size en píxeles anula el tamaño de fuente predeterminado del lector, el tamaño base que puede establecer en las preferencias del navegador (a menudo para baja visión), porque un valor px no tiene referencia a esa preferencia para escalar. Ten en cuenta la distinción del zoom de página: los navegadores modernos sí escalan px en zoom de página completa, así que la antigua afirmación "px ignora el zoom" está anticuada, pero un tamaño de fuente px todavía ignora la configuración de tamaño de fuente predeterminado específicamente, y esa configuración es la ruta de accesibilidad en la que muchos lectores confían. La regla que se mantiene: px para detalles fijos, una unidad relativa a fuente para cualquier cosa que un lector deba poder ampliar, especialmente texto de cuerpo y tipografía.

JunoPíxeles y cuándo están bien Un píxel (px) es un tamaño fijo, así que 16px siempre es 16px. Eso la hace una buena opción para cosas pequeñas que deben permanecer en su lugar, como un borde 1px o una pequeña esquina redondeada. La compensación es que px ignora a un lector que ha establecido texto más grande, por lo que no es la unidad que quieres para las palabras en la página.
JunoPíxeles y cuándo están bien Usa px cuando una longitud no debe escalar: bordes, divisores finos, radios pequeños. Su fijeza es la característica allí. El inconveniente aparece con el texto, donde un tamaño de fuente px anula el tamaño predeterminado más grande de un lector, así que mantén px para los detalles fijos y dimensiona el texto en una unidad relativa a fuente.
JunoPíxeles y cuándo están bien El px de CSS es un píxel de referencia que el navegador mantiene visualmente consistente en diferentes densidades de pantalla, que es por qué un borde 1px permanece como una línea fina limpia. Eso lo hace correcto para detalles fijos como bordes y sombras. Es incorrecto para el texto, porque un tamaño de fuente px ignora la configuración de tamaño de fuente predeterminado del lector, así que dimensiona el tipo en rem en su lugar.

em y rem

Dos unidades relativas se escalan a un tamaño de fuente: em y rem. La que debes usar es rem. Se mide contra el tamaño de fuente raíz de la página, que es el tamaño de texto base establecido en todo el documento (16px de manera predeterminada). Así que 1rem es 16px, 1.5rem es 24px, y 2rem es 32px.

css
h1 {
  font-size: 2rem;             /* 2 x 16px = 32px */
}
p {
  font-size: 1rem;             /* 16px, el tamaño base */
  margin-bottom: 1.5rem;       /* 24px de espacio debajo */
}

Porque rem está vinculado a ese único tamaño raíz, es predecible: 1.5rem significa lo mismo en todas partes de la página. Y cuando un lector aumenta su tamaño de fuente predeterminado, todo lo dimensionado en rem crece junto. La otra unidad, em, se escala al tamaño de fuente del elemento en su lugar, lo que puede enredarse, así que comienza con rem y raramente te sorprenderás.

em y rem son ambas relativas a fuente, y la diferencia es a qué tamaño de fuente se miden. rem es relativa al tamaño de fuente raíz, el tamaño establecido en el elemento <html> (16px de manera predeterminada), así que 1.5rem se resuelve a la misma longitud en cualquier parte de la página. em es relativa al tamaño de fuente del elemento, así que su valor cambia dependiendo de dónde la uses.

css
h1 {
  font-size: 2rem;             /* siempre 2 x la raíz = 32px */
}
.card {
  font-size: 1.125rem;         /* 18px */
  padding: 1em;                /* 1 x este tamaño de fuente del elemento 18px = 18px */
}

La recomendación es dimensionar en rem y usar em solo para escala vinculada al tamaño de fuente local. em funciona bien para cosas que deben rastrear su propio texto, como el relleno dentro de un botón que crece con el tamaño de fuente del botón. Pero em se compone a través de elementos anidados, lo que sorprende a la gente, así que mantenlo para esos casos locales y deja que rem lleve tu dimensionamiento general y tipografía.

em y rem son ambas relativas a fuente, lo que significa que se resuelven contra un tamaño de fuente en lugar de una longitud fija, y la distinción es la referencia. rem (em raíz) se resuelve contra el tamaño de fuente raíz, el font-size calculado en el elemento <html>, así que es una única referencia global: 1.25rem es la misma longitud calculada en un encabezado, un pie de página, o seis niveles de profundidad. em se resuelve contra el font-size del elemento actual, así que su significado es local y se mueve con el contexto.

Esa referencia local es donde em se compone. Porque el em de un hijo se mide contra su propio font-size, y font-size se hereda, establecer font-size en em en elementos anidados se multiplica en cada nivel:

css
/* Cada nivel de lista establece font-size en em, así que los tamaños se apilan multiplicativamente */
ul { font-size: 0.9em; }       /* 0.9 x padre */

/* Una raíz de 16px se convierte en:
   profundidad 1 -> 14.4px
   profundidad 2 -> 12.96px  (0.9 x 0.9)
   profundidad 3 -> 11.66px  (0.9 x 0.9 x 0.9)  */

Nadie pidió texto que se encoja más profundamente anida; eso es composición de em, y es el argumento principal para llegar a rem de manera predeterminada. La compensación va en la otra dirección para escala local de componentes, donde quieres que un valor rastree el tamaño de fuente del elemento: un botón cuyo relleno es 0.75em y radio del borde 0.5em se reescala como una unidad cuando aumentas su font-size, que rem no puede hacer porque ignora el tamaño local. Así que la división que funciona es rem para cualquier cosa que deba permanecer estable contra la raíz, em para espaciado y radios que deben escalar con el tamaño de fuente del elemento.

Para dimensionamiento fluido, min(), max(), y clamp() permiten que una longitud sea flexible entre límites. min(a, b) elige el que sea más pequeño en la ventana gráfica actual, max(a, b) el más grande, y clamp(min, preferred, max) mantiene un valor preferido entre un piso y un techo. Un patrón común para un encabezado es font-size: clamp(1.75rem, 4vw, 3rem): se escala con la ventana gráfica (4vw) pero nunca cae por debajo de 1.75rem ni excede 3rem, así que el tipo permanece fluido sin una pila de puntos de quiebre. Dimensionar el tipo en rem (o rem-limitado clamp()) también respeta el zoom del usuario y el tamaño de fuente predeterminado del lector, porque esos ajustan la raíz contra la que se resuelve rem, mientras que un valor vw crudo rastrea solo la ventana gráfica e ignora la preferencia de fuente del lector. Por eso importan el piso y el techo de rem en un clamp(): mantienen la referencia accesible en la expresión.

Junoem y remrem y em ambas se escalan a un tamaño de fuente, y la que debes comenzar es rem. Se mide contra el tamaño raíz de la página, que es 16px de manera predeterminada, así que 1.5rem es 24px y significa lo mismo en todas partes. em se escala al tamaño de fuente del elemento en su lugar, lo que puede enredarse, así que llega a rem primero.
Junoem y rem Ambas son relativas a fuente: rem se mide contra el tamaño de fuente raíz, así que es estable en todas partes, mientras que em se mide contra el tamaño de fuente del elemento, así que cambia con el contexto y se compone cuando está anidado. Dimensiona en rem de manera predeterminada y mantén em para espaciado que deba rastrear el tipo del elemento, como relleno dentro de un botón.
Junoem y remrem se ancla al tamaño de fuente raíz para una única referencia estable; em se ancla al tamaño del elemento y se multiplica a través del anidamiento, que es por qué los tamaños de fuente em profundamente anidados se desvían. Usa rem para dimensionamiento general y em para escala local de componentes que deba seguir su propio tipo. Para tipo fluido, clamp(1.75rem, 4vw, 3rem) es flexible con la ventana gráfica mientras que el piso y el techo de rem la mantienen respetando zoom y configuración de fuente del usuario.

Porcentajes

Un porcentaje (%) dimensiona un elemento contra su padre. Para ancho, width: 50% significa la mitad del ancho de la caja en la que se sienta el elemento, sea cual sea el ancho.

css
.sidebar {
  width: 25%;                  /* un cuarto del ancho del padre */
}
.content {
  width: 75%;                  /* los tres cuartos restantes */
}

Esto es lo que hace un diseño fluido: porque los anchos son fracciones del padre, se encogen y crecen a medida que lo hace el padre. Cambia el tamaño de la ventana y una columna 50% permanece a media anchura en lugar de derramarse por el borde como lo haría una columna fija de 500px. Esa flexibilidad es por qué los porcentajes aparecen tan a menudo en el diseño responsivo.

Un porcentaje se resuelve contra una referencia en el padre, y para width esa referencia es el ancho de contenido del padre. Así que width: 50% te da la mitad de lo que sea actualmente la caja contenedora, que es lo que hace que las columnas basadas en porcentaje sean fluidas: rastrea al padre a medida que cambia de tamaño.

css
.container {
  width: 90%;                  /* 90% de su padre, hasta un límite inferior */
  max-width: 60rem;            /* deja de crecer después de 60rem en pantallas anchas */
  margin: 0 auto;              /* centralo */
}

La referencia no siempre es ancho, y eso desorienta a la gente. Un padding o margin de porcentaje, incluso los verticales, se resuelve contra el ancho del padre, no su altura. Un height de porcentaje se resuelve contra la altura del padre, pero solo si el padre tiene una altura definitiva para medir, si no tiene nada contra qué resolver y se ignora. Emparejar un ancho de porcentaje con un max-width en rem, como arriba, es el movimiento común: fluido hasta un punto, luego limitado para que las líneas no se estiren demasiado para leer.

Un porcentaje es relativo, pero a diferencia de rem y em su referencia no es un tamaño de fuente, es una dimensión del bloque contenedor (la caja que establece la referencia para un elemento posicionado o en el flujo, generalmente la caja de contenido del padre). La trampa que muerde es que la dimensión de referencia es específica de la propiedad, y no siempre es la que esperarías:

css
.hero {
  width: 80%;                  /* 80% del ANCHO del bloque contenedor */
  padding-top: 25%;            /* también 25% del ANCHO, no la altura */
  margin-bottom: 10%;          /* ANCHO de nuevo, aunque sea vertical */
}

Los porcentajes de width, padding y margin todos se resuelven contra el ancho del bloque contenedor, incluyendo los rellenos y márgenes verticales. Ese relleno vertical basado en ancho no es una peculiaridad que rodear; es el truco clásico para una caja de relación de aspecto fija antes de que aspect-ratio se enviara, ya que padding-top: 56.25% da un área 16:9 que se escala con el ancho. Un porcentaje de height se resuelve contra la altura del bloque contenedor, pero solo si esa altura es definitiva (explícitamente establecida o de otra manera resoluble); contra una altura automática se calcula a auto y parece no hacer nada, que es la razón habitual por la que un porcentaje de altura falla silenciosamente. En el diseño moderno, los porcentajes flex-basis y de pistas de cuadrícula se comportan más predeciblemente, así que los porcentajes permanecen útiles para anchos fluidos mientras que las unidades fr y min()/max()/clamp() cubren los casos que los porcentajes manejan de manera incómoda.

JunoPorcentajes Un porcentaje se dimensiona contra el padre, así que width: 50% es la mitad del ancho de la caja en la que se sienta el elemento. Eso hace que las columnas sean fluidas: cambia el tamaño de la ventana y crecen y se encogen en lugar de derramarse. Es una de las herramientas principales detrás de diseños que se ajustan a cualquier pantalla.
JunoPorcentajes Un ancho de porcentaje es una fracción del padre, que es lo que mantiene las columnas fluidas a medida que el contenedor cambia de tamaño. Observa la referencia: el relleno y margen de porcentaje se resuelven contra el ancho del padre, incluso los verticales, y un porcentaje de altura necesita que el padre tenga una altura definitiva. Emparejar un ancho de porcentaje con un max-width en rem lo mantiene fluido pero limitado.
JunoPorcentajes Los porcentajes se resuelven contra el bloque contenedor, y la referencia es específica de la propiedad: width, padding y margin todos usan su ancho, valores verticales incluidos, que es el truco detrás de cajas de relación de aspecto basadas en ancho. Un porcentaje de altura necesita una altura de padre definitiva o se calcula a auto y no hace nada. Mantén los porcentajes para anchos fluidos y deja que las unidades fr y clamp() manejen los casos incómodos.

Unidades de viewport

Las unidades de viewport se dimensionan contra la ventana del navegador en sí. vw es un porcentaje del ancho de la ventana gráfica y vh es un porcentaje de la altura de la ventana gráfica, donde la ventana gráfica es el área visible de la página. Así que 100vw es el ancho completo de la ventana y 100vh es su altura completa.

css
.hero {
  height: 100vh;               /* llena toda la altura de la pantalla */
}

Este es el estándar para una sección de pantalla completa, como un banner de desembarque que debe llenar la ventana sea cual sea su tamaño. Porque las unidades rastrean la ventana, la sección permanece en pantalla completa cuando alguien cambia el tamaño o gira su dispositivo, sin que establezca una altura de píxel fija que solo sería correcta en una pantalla.

Las unidades de viewport se miden contra la ventana gráfica, el área visible de la ventana del navegador. vw es el uno por ciento del ancho de la ventana gráfica y vh es el uno por ciento de su altura, así que 100vh es la altura de una ventana completa y 50vw es la mitad de su ancho. Son el ajuste natural para secciones de pantalla completa y banners heroicos que deben llenar la ventana en cualquier tamaño.

css
.hero {
  min-height: 100vh;           /* al menos una pantalla completa de alto */
  padding: 2rem;
}

Una cosa que saber en móvil: 100vh históricamente incluía el espacio detrás de la barra de direcciones del navegador, así que una sección de altura completa podría sentarse más alta que el área visible y cortarse en la parte inferior. La corrección es dvh, la altura de ventana gráfica dinámica, que rastrea la altura visible actual a medida que la barra de herramientas del navegador se muestra y se oculta. Llega a min-height: 100dvh en secciones de pantalla completa móvil, y ten en cuenta que vw crudo en tamaños de fuente ignora la configuración de fuente del lector, así que mantén las unidades de ventana gráfica para el diseño en lugar del tipo.

Las unidades de viewport se resuelven contra la ventana gráfica, el área de representación visible de la ventana del navegador. vw y vh son el uno por ciento de su ancho y altura; vmin y vmax son el uno por ciento del menor y mayor de los dos, útil para valores que deben responder a la orientación. Su referencia es la ventana, no ningún padre, así que son la herramienta correcta para secciones de ventana gráfica completa independientes del diseño alrededor de ellas.

css
.hero {
  min-height: 100dvh;          /* altura visible completa, segura para móvil */
  padding: 2rem;
}

El borde afilado es móvil, donde la altura de la ventana gráfica no es un número. La barra de direcciones del navegador y las barras de herramientas se expanden y cierran a medida que el usuario se desplaza, así que 100vh se fijó a la ventana gráfica más grande posible y una sección de altura completa se desbordaría detrás de la barra. CSS ahora expone tres: svh (altura de ventana gráfica pequeña, barra expandida), lvh (grande, barra colapsada), y dvh (dinámica, que sigue el estado actual en vivo). Usa dvh para secciones de pantalla completa que deben caber en el área visible, aceptando que se refluja a medida que se mueven las barras. La otra trampa es font-size en vw crudo: porque la referencia de una unidad de viewport es la ventana y no el tamaño de fuente raíz, font-size: 4vw ignora tanto el tamaño de fuente predeterminado del lector como el zoom de página que no cambia la ventana gráfica, lo que falla en la misma prueba de accesibilidad que un tamaño de fuente px. La corrección es limitarla: clamp(1rem, 4vw + 0.5rem, 2rem) mantiene el comportamiento fluido mientras que los términos rem restauran una referencia que la configuración del lector puede mover.

JunoUnidades de viewportvw y vh se dimensionan contra la ventana del navegador: 100vw es su ancho completo y 100vh es su altura completa. Son estándar para una sección de pantalla completa como un banner de desembarque, porque permanece en pantalla completa cuando la ventana cambia de tamaño en lugar de estar bloqueada a una altura de píxel.
JunoUnidades de viewportvw y vh son el uno por ciento del ancho y altura de la ventana, que los hace correctos para secciones heroicas que deben llenar la pantalla en cualquier tamaño. En móvil, 100vh puede correr más alto que el área visible detrás de la barra de direcciones, así que llega a dvh allí. Mantén las unidades de ventana gráfica para el diseño, no los tamaños de fuente, ya que vw crudo en tipo ignora la configuración del lector.
JunoUnidades de viewport Las unidades de viewport se anclan a la ventana, no a un padre, así que se adaptan a secciones de ventana gráfica completa; vmin y vmax responden a la orientación. En móvil la altura no es un valor, así que usa dvh para seguir el área visible a medida que se mueve la barra de herramientas del navegador. Nunca dimensiones el tipo en vw crudo, ya que ignora la configuración de fuente del lector; limitala en un clamp() con términos rem para que una referencia accesible permanezca en la expresión.