px (píxeles) es la unidad absoluta más común. font-size: 16px significa exactamente 16 píxeles CSS, sin importar el contexto. Es predecible y directo, pero ignora preferencias de usuario (como zoom de texto) y dificulta diseño responsive. Usarlo exclusivamente rompe accesibilidad para personas con baja visión que aumentan el tamaño de fuente del navegador.
rem (root em) es relativo al font-size del elemento raíz (html). Si el root es 16px (default en navegadores), 1rem = 16px, 2rem = 32px. Cambiar el font-size del root escala todo el diseño proporcionalmente. Esto respeta preferencias de accesibilidad y facilita theming. Es la unidad recomendada para tipografía y espaciado en sistemas de diseño modernos.
em es relativo al font-size del elemento padre directo. Si un div tiene font-size: 20px y un hijo usa padding: 1em, el padding será 20px. Los em se multiplican en cascada: si un div tiene font-size: 1.2em dentro de otro div con 1.5em, el resultado es 1.2 × 1.5 = 1.8em respecto al ancestro. Esto puede ser útil para componentes modulares pero confuso sin disciplina.
La mayoría de navegadores tiene font-size root de 16px por defecto. Podés cambiarlo en html { font-size: 18px; } o usar porcentajes: font-size: 112.5%; (18px si el default es 16px). Sistemas de diseño suelen definir el root en rem para escalar todo: html { font-size: 62.5%; } hace que 1rem = 10px, facilitando cuentas (1.6rem = 16px).
Conversión mental: si el root es 16px, dividí px por 16 para obtener rem. 24px = 1.5rem, 32px = 2rem, 12px = 0.75rem. Con root en 10px (62.5%), la conversión es directa: 18px = 1.8rem. Para em, dependés del padre: si el padre es 20px, 1em = 20px, 0.5em = 10px.
En media queries, siempre usá em o rem, nunca px. Los navegadores interpretan em en media queries relativo al default de 16px (no al root alterado). Ejemplo: @media (min-width: 48em) equivale a 768px si 16px es base. Esto respeta zoom del navegador: si un usuario hace zoom 200%, un breakpoint en px no escala, pero uno en em sí.
Usá rem para: tamaños de fuente base, espaciado (margins, paddings) de layout, tamaños de componentes que deben escalar con preferencias de usuario. Ejemplo: h1 { font-size: 2.5rem; margin-bottom: 1rem; }. Esto asegura que si alguien aumenta el zoom de texto, todo el diseño responde.
Usá em para: espaciado interno de componentes que debe ser proporcional al texto del componente. Ejemplo: botones con padding: 0.5em 1em; se ajustan automáticamente si el botón tiene font-size: 1.2rem o 0.875rem. También útil en media queries y line-height (line-height: 1.5em o mejor sin unidad: 1.5).
Usá px para: bordes (border: 1px solid), sombras pequeñas, detalles que no deben escalar (íconos fijos, divisores). También en casos donde necesitás control pixel-perfect, como alineación de grids o imágenes. Evitá px para tipografía y espaciado principal: rompe accesibilidad.
Regla práctica: rem por defecto, em para componentes modulares, px solo cuando absoluto es requerido. Sistemas como Tailwind CSS usan rem para casi todo: text-base = 1rem, p-4 = 1rem padding.
Error 1: Usar px para todo. Esto ignora que usuarios pueden tener configuraciones de accesibilidad distintas. Un diseño en px puro falla WCAG 2.1 (criterio 1.4.4 Resize Text). Migrá a rem/em para cumplir estándares y mejorar UX.
Error 2: Anidar em sin control. Si tenés 5 niveles de font-size: 1.2em anidados, el texto del último nivel será enorme (1.2^5 ≈ 2.5x). Usá rem para evitar multiplicación en cascada, o em solo en un nivel de profundidad.
Error 3: No definir root explícitamente. Asumir que el root es 16px funciona hasta que un usuario o framework lo cambia. Declará tu intención: html { font-size: 100%; } o el valor específico que necesites. Documentá la base en tu sistema de diseño.
Buena práctica: usá variables CSS para escalas. --font-size-base: 1rem; --spacing-unit: 0.5rem; Así cambiás toda la escala editando una variable. Herramientas como clamp() combinan bien con rem para tipografía fluida: font-size: clamp(1rem, 2vw, 1.5rem); escala entre 16-24px según viewport, respetando rem.
Ejemplos
html { font-size: 16px; } → body { font-size: 1rem; } = 16pxhtml { font-size: 10px; } → h1 { font-size: 3.2rem; } = 32pxdiv { font-size: 20px; } → span { padding: 0.5em; } = 10px paddingbutton { font-size: 1rem; padding: 0.5em 1em; } = 16px fuente, 8px 16px padding (si root es 16px)@media (min-width: 48em) = breakpoint a 768px (si base es 16px)
Preguntas frecuentes
¿Por qué no usar px si es más fácil?
px ignora preferencias de accesibilidad del usuario. Si alguien configura su navegador para texto más grande (común en personas con baja visión o adultos mayores), un sitio en px puro no responde. Además, diseño responsive es más simple con rem: cambiar un breakpoint o escala de tipografía es editar una variable, no buscar y reemplazar cientos de valores px.
¿rem o em para media queries?
Ambos funcionan, pero em es más común porque en media queries se calcula respecto al default del navegador (16px), no al root. Usar em asegura que breakpoints escalan con zoom del navegador. Ejemplo: <code>@media (min-width: 64em)</code> es 1024px pero si el usuario hace zoom 150%, el breakpoint también escala. px en media queries no escala con zoom.
¿Cómo migro un proyecto de px a rem sin romperlo todo?
Empezá por definir <code>html { font-size: 62.5%; }</code> (1rem = 10px) para conversión fácil. Usá buscar y reemplazar con regex para convertir valores comunes: 16px → 1.6rem, 24px → 2.4rem. Priorizá tipografía y espaciado de layout, dejá borders y detalles en px por ahora. Probá con zoom de navegador al 200% y 50% para validar que todo escala. Herramientas como PostCSS tienen plugins de conversión automática.