Menu

rem vs em vs px: unidades CSS, porcentajes, vw y vh

rem es relativo al tamaño de letra de la raíz, em al tamaño de letra del propio elemento, px es fijo y % depende de la propiedad. Mira cada unidad medida en una demo anidada, por qué em se acumula, cuándo usar cada una y cómo funcionan vw, vh y dvh.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

rem vs em en una demo anidada

rem es relativo al tamaño de letra de la raíz (el elemento <html>, 16px por defecto). em es relativo al tamaño de letra actual, que en font-size significa el del padre. Anida la misma clase tres veces y se ve la diferencia:

Los tamaños impresos son los que calculó el navegador. Cada 1.25em multiplica al de su padre: 20px, luego 25px, luego 31.25px. Cada 1.25rem solo mira a la raíz: 20px, 20px, 20px. Esa acumulación es la razón por la que los tamaños de letra en em se descontrolan en listas y menús anidados, y por la que la mayoría de los sitios definen los tamaños de letra en rem.

Respecto a qué es relativa cada unidad

UnidadRelativa a1 unidad por defecto
pxnada (un píxel CSS)1px
remel tamaño de letra del elemento raíz (html)16px
emel tamaño de letra del elemento; para el propio font-size, el del padre16px en el nivel superior
%depende de la propiedad (ver abajo)
vw / vhel 1% del ancho / alto del viewport
dvh, svh, lvhel 1% de la altura dinámica, pequeña o grande del viewport
vmin / vmaxel 1% del lado menor / mayor del viewport
chel ancho del "0" en la fuente actualmás o menos medio em
exla altura de la x de la fuente actualmás o menos medio em

Un píxel CSS no es un píxel del dispositivo: en un teléfono con pantalla 3x, 1px mide 3 píxeles del dispositivo. Mantiene más o menos el mismo tamaño visual en todas las pantallas, y por eso px sigue sirviendo para bordes y sombras.

em para espaciados que escalan con el texto

em no es solo para tamaños de letra. En padding, margin, width o border-radius significa "veces el tamaño de letra de este elemento". Eso hace que una sola clase de botón funcione a cualquier tamaño:

El padding de cada botón es la mitad de su tamaño de letra en vertical y un tamaño de letra en horizontal, así que los tres parecen el mismo botón en tres tamaños. Con un padding en px necesitarías una regla de padding distinta para cada tamaño.

Ten en cuenta que los botones no heredan por defecto el tamaño de letra de la página (los navegadores les dan a los controles de formulario el suyo), así que el botón del medio mide aquí 13.33px en Chrome, no 16px. Agrega font: inherit a los botones e inputs cuando quieras que coincidan con la página.

Porcentajes: depende de la propiedad

% no tiene un significado único. Cada propiedad indica de qué es porcentaje:

Propiedad% es relativo a
width, max-width, left, rightel ancho del padre (del bloque contenedor)
height, top, bottomla altura del padre, y solo si el padre tiene una altura definida
padding, margin (los cuatro lados)el ancho del padre
font-sizeel tamaño de letra del padre (150% = 1.5em)
line-heightel tamaño de letra del propio elemento
transform: translate()el tamaño del propio elemento

width: 50% son 200px, la mitad del padre. padding-top: 5% son 20px: el 5% del ancho del padre, no de su alto. Y height: 50% no hace nada, porque el padre no tiene una altura definida, así que el hijo solo mide lo que su texto más ese padding. La página de width y height explica esa regla en detalle.

vw, vh y la barra de direcciones del celular

1vw es el 1% del ancho del viewport y 1vh el 1% de su altura. Son útiles para secciones de pantalla completa y para tamaños fluidos (a menudo dentro de clamp()). En los teléfonos, vh tiene una trampa: la barra de direcciones del navegador entra y sale al desplazarte, y 100vh es la altura sin la barra, así que un hero con height: 100vh queda cortado abajo cuando se ve la barra. Las unidades más nuevas lo resuelven:

UnidadAltura que usa
100vhel viewport grande (barras ocultas) en la mayoría de los navegadores móviles
100svhel viewport pequeño (barras visibles): siempre cabe
100lvhel viewport grande, de forma explícita
100dvhel viewport dinámico: cambia a medida que se mueven las barras
.hero {
  min-height: 100vh;  /* fallback for older browsers */
  min-height: 100svh; /* fits the screen even with the address bar visible */
}

vw tiene su propia trampa: 100vw incluye el ancho de una barra de desplazamiento vertical cuando esa barra ocupa espacio (como en Windows), así que width: 100vw puede ser más ancho que la página y agregar una barra horizontal. Usa width: 100% para "todo el ancho del padre".

ch para una longitud de línea legible

ch es el ancho del carácter "0", así que max-width: 65ch limita un párrafo a unos 65 caracteres por línea, una longitud de lectura cómoda, con cualquier tamaño de letra:

Qué unidad usar

ParaUsaPor qué
Tamaños de letraremCoherente en todas partes, respeta la configuración de tamaño de letra del lector
Padding y gaps en componentesrem o emem cuando debe crecer con el propio texto del componente
Bordes, líneas finas, sombraspxDeben seguir siendo finos con cualquier tamaño de letra
Anchos de layout%, fr, max-width en rem o chSiguen al contenedor, limitan la longitud de línea
Secciones de pantalla completasvh / dvh (con vh de respaldo)Manejan las barras de direcciones móviles
Tipografía fluidaclamp() combinando rem y vwCrece con la pantalla dentro de unos límites

Por qué rem respeta a los lectores y px no

Los navegadores tienen una configuración para el tamaño de letra por defecto, que usan las personas que necesitan un texto más grande. Cambia el tamaño de letra de la raíz, así que todo lo que está en rem y em crece con él. Un font-size: 14px se queda en 14px elija lo que elija el lector. El zoom del navegador también escala los px, pero la configuración de tamaño de letra es la que usan muchos lectores. Esta es la razón principal para definir los tamaños de letra en rem.

Algunos sitios definen html { font-size: 62.5%; } para que 1rem equivalga a 10px y las cuentas sean más fáciles. Sigue respetando la configuración del lector (el 62.5% de lo que haya elegido), pero acuérdate de poner un font-size legible en body, o todos los elementos sin tamaño propio muestran texto de 10px.

Errores comunes

  • Tamaños de letra en em en elementos anidados. Se multiplican en cada nivel. Usa rem para los tamaños de letra.
  • Un height: 50% que no hace nada. El padre necesita una altura definida para que funcione una altura en porcentaje.
  • Esperar que padding-top: 10% siga la altura del padre. Los porcentajes de padding y margin verticales usan el ancho del padre.
  • width: 100vw que provoca una barra de desplazamiento horizontal. Incluye la barra de desplazamiento. Usa 100%.
  • Un height: 100vh cortado en los teléfonos. Usa 100svh o 100dvh.
  • Definir html { font-size: 12px }. Un valor en px en la raíz sobrescribe la configuración de tamaño de letra del lector en toda la página. No toques la raíz o usa un porcentaje.

Preguntas frecuentes

¿Qué diferencia hay entre rem y em?

rem es relativo al tamaño de letra del elemento raíz (<html>), así que 1.5rem tiene el mismo tamaño en toda la página. em es relativo al tamaño de letra del propio elemento (en font-size, al del padre), así que se acumula cuando los elementos están anidados.

¿Cuántos píxeles es 1rem?

16px por defecto, porque los navegadores ponen el tamaño de letra de la raíz en 16px. Si el usuario sube el tamaño de letra por defecto en la configuración de su navegador, o defines html { font-size: ... }, 1rem cambia con él.

¿Uso rem o px para el tamaño de letra?

Usa rem para los tamaños de letra. Respeta la configuración de tamaño de letra por defecto del lector en el navegador, que px ignora. El zoom del navegador escala los dos, pero no todos los lectores usan el zoom.

¿Cuándo uso em en lugar de rem?

Usa em para espaciados que deben escalar con el propio texto del elemento, como el padding de un botón o el tamaño de un ícono junto al texto. Así la misma clase se ve bien con cualquier tamaño de letra. Usa rem para los tamaños de letra y los espaciados de la página, para que nada se acumule.

¿Qué diferencia hay entre 100vh y 100dvh?

En los navegadores móviles, 100vh es la altura con la barra de direcciones oculta, así que una sección de 100vh es más alta que la pantalla visible mientras se ve la barra. 100dvh (altura dinámica del viewport) sigue a la barra cuando aparece y desaparece, y 100svh es siempre la altura más pequeña.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR