EM VS REM: ¿Cuál debería usar?

Lupita Code 🌄
14 min readSep 28, 2021

--

¡Hola gente bonita!👋

En este articulo voy a explicar todo lo que tienes que saber sobre las unidades em y rem y porque se llaman de esa manera. Además voy a responder a la pregunta más común que se hacen todos: ¿Cuándo usar em y cuando usar rem?

🤔 ¿De donde viene el nombre em?

Si pensabas que la em tiene algo que ver con la letra “m”, te has equivocado❌ Pero si pensabas que tiene algo que ver con la letra “M”, has acertado ✅

La em debe su nombre originalmente a la anchura de la letra M mayúscula. La unidad em tiene una larga tradición en tipografía, esto significa que no ha sido creada por CSS sino que lleva décadas utilizándose en el campo de la tipografía, donde se ha utilizado para medir anchos horizontales. Por ejemplo, el guion largo ( — ) se conoce como “em-dash”, ya que históricamente ha tenido la misma anchura que la letra “M”.

✅ En la web las unidades em y rem no se basan en el ancho de la letra M, sino que se basan en el valor del font-size.

📐 EM & REM

em y rem son unidades CSS pensadas para trabajar con tipografía, aunque también se utilizan para especificar dimensiones en otros elementos HTML.

Tanto em como rem son considerados unidades relativas, pero ¿relativo a que? o ¿respecto a que? 🤔 la respuesta es que son relativas al font-size.

🔄 em y rem se computan o se traducen a valores de pixel. Por ejemplo si colocas 1em o 1rem como valor a un elemento HTML el navegador va a computar o convertir ese valor en un valor de pixel (px). Esto lo podemos comprobar con el siguiente ejemplo:

🔎 Si inspeccionas el elemento <h1> y lo analizas en la DevTools (herramienta de desarrollo) de tu navegador y haces click en la pestaña de "Styles" (Estilos), el elemento <h1> tiene un font-size: 2em;, esto es porque por defecto el navegador asigna a los elementos <h1> un tamaño de fuente de 2em.

Pero si haces click en la pestaña “Computed” (calculado) podrás observar que el navegador convierte el tamaño de fuente de 2em a 32px

Pero, ¿Por que lo convierte a 32px? 🤔 Primero tienes que saber que la mayoría de los navegadores tienen un estándar en el que el tamaño base de la fuente o font-size que asignan al texto es de 16px , excluyendo por supuesto a los encabezados <h1> a <h6> y el elemento <small> ya que el navegador les asigna otro tamaño de fuente.

El tamaño de fuente base que son16px puede ser cambiado (en las preferencias del navegador) por el usuario a cualquier valor entre 9px a 72px.

Imaginemos que el tamaño de la fuente establecida en el navegador del usuario es exactamente 16px. Un 1em equivaldría a 16px, mientras que 2em sería el doble: 32px. Por otro lado, 0.5em sería la mitad: 8px.

Entonces si calculamos, el valor es: 2em x 16px = 32px. Probablemente te estarás preguntando si siempre se va a multiplicar por 16px, y la respuesta es que no, y es aquí donde se genera una diferencia entre las unidades em y rem:

👉 Las unidades em para la propiedad font-size serán relativas al font-size del elemento padre, pero las unidades em en otras propiedades (que no sean font-size) serán relativas al font-size del elemento actual.

👉 Las unidades rem siempre serán relativas al font-size del elemento raíz que es html .

Vamos a explorar estas diferencias a continuación.

📏 EM

La unidad em permite establecer el tamaño de fuente o font-size de un elemento en base al font-size de su elemento padre mas cercano.

Ejemplo 1

Vemos este ejemplo sencillo:

.parent {
font-size: 18px;
}
.child {
font-size: 1.5em;
}

En este ejemplo, el elemento hijo .child tendrá un font-size de 27px (1.5em x 18px = 27px). Esto es porque se multiplica por el font-size del elemento padre ya que como dice la definición la unidad em se basa en el font-size del padre. Esta es la respuesta del porque no siempre se multiplica por los 16px del navegador.

Pero…si el elemento padre .parent no tuviera un valor en el font-size , se buscara un valor mas arriba en el árbol DOM. Si no se especifica el font-size hasta el elemento raíz (<html> ), se utilizara el valor predeterminado del navegador que es 16px .

Ejemplo 2

Puede ser un mal entendido decir que las unidades em son relativas al font-size del elemento padre. De hecho, como lo especifica el W3, son relativos al font-size “del elemento en el que son usadas”.

✅ Las unidades em pueden usarse para mucho mas que solo para establecer el font-size , pueden usarse en otras propiedades como padding, margin, width, height, max-width, etc. Cuando las unidades em se usan en otras propiedades que no sea el font-size , el valor es relativo al propio font-size del elemento. Te explico con este ejemplo:

h2 {
font-size: 20px;
margin-top: 2em;
}
h3 {
margin-top: 2.5em;
}
<h2>Hello</h2>
<h3>World</h3>

¿Cuál es el valor real del margin-top del elemento <h2>? La respuesta es 40px puedes comprobarlo tu misma, de nuevo abre las DevTools de tu navegador, selecciona el <h2> y ve a la pestaña “Computed”, como puedes ver el valor calculado que se muestra es 40px .

¿Cómo se ha obtenido este valor? La formula del calculo para la propiedad CSS considerada (margin-top) del elemento <h2> es:

Multiplicar el valor em (2em) por el valor real del font-size en px del elemento HTML al que se va aplicar el estilo (20px ). Para nuestro ejemplo, esto significa: 2em x 20px = 40px .

Ahora, ¿Cuál seria el valor del margin-top para el elemento <h3> de este ejemplo?. En este caso el valor final es: 46.8px . ¿Por que? 🤔

Como puedes ver en el código del ejemplo ⬆️, ambos elementos (<h2> y <h3> ) son hermanos y son hijos de <body> . Sin embargo no hemos declarado explícitamente un valor en el font-size del elemento <h3> como hicimos con el elemento <h2> .

Pero en realidad el elemento <h3> si tiene un valor en el font-size que es de 1.17em ya que este es el valor que asigna por defecto el navegador a los encabezados <h3> . Lo puedes comprobar tu misma en la hoja de estilos del navegador:

Bien, pero esto tampoco es un valor en pixeles px . Entonces tenemos que subir por la jerarquía de elementos padre hasta encontrar un valor en px .

Con la ayuda de DevTools nos podemos dar cuenta que el elemento <body> tiene un valor absoluto en font-size que es de 16px derivado del valor por defecto del navegador ya que no hemos especificado un valor personalizado.

Entonces con esta información podemos calcular el valor especifico: 2.5em x 1.17em x 16px = 46.8px

Así que recuerda lo siguiente: Cuando se utilizan unidades em en el font-size el tamaño es relativo al font-size del padre. Cuando se utiliza en otras propiedades es relativo al font-size del propio elemento.

Ejemplo 3

Veamos otro ejemplo para que quede mas claro:

.parent {
font-size: 18px;
}
.child {
font-size: 1.5em; 👆 /* = 27px */
padding: 2em 1em; 👆
}

El padding-top y padding-bottom del elemento hijo .child será de 54px , si hacemos los cálculos: 2em x 27px = 54px.

El padding-left y padding-right del elemento hijo .child sera de 27px , si hacemos los cálculos: 1em x 27px = 27px.

👨‍👦 El efecto compuesto: la herencia en unidades em

Hasta aquí todo va bien con el uso de la unidad em, pero puede complicarse cuando se trata de la herencia, porque cada elemento HTML automáticamente hereda su valor del font-size de su elemento padre y esto puede llevar a un comportamiento no deseado en elementos anidados con valores em. Cabe mencionar que las unidades como px , vw o rem NO están sujetas a la herencia.

Como bien sabes la propiedad font-size es una propiedad heredable. Las propiedades heredables y no heredables las explique en mi articulo de la herencia, así que te invito a leerlo.

Vamos a explicar esto con un ejemplo, solo que con varios elementos anidados, así que vamos a utilizar las listas:

En nuestro ejemplo, el font-size de los elementos anidados mas profundos es mayor de lo esperado. ¿A que se debe esto? 🤔 Vamos analizar el código:

  • El font-size para el nivel 1(top level) es de 32px : 2em (selector <li> * 16px (font-size heredado del <html> ).
  • El font-size para el nivel 2 (second level) es de 64px : 2em (selector <li> * 32px (font-size heredado del nivel 1<li> ).
  • El font-size para el nivel 3 (third level) es de 128px : 2em (selector <li> * 64px (font-size heredado del nivel 2<li> ).
  • El font-size para el nivel 4 (fourth level) es de 256px : 2em (selector <li> * 128px (font-size heredado del nivel 3<li> ).

Para solucionar este problema de forma que se garantice que todos los elementos <li> tengan el mismo tamaño de fuente, se podría añadir:

ul { font-size: 16px };

De manera que todos los <ul> tienen un valor fijo de 16px entonces los <li> ya no heredan del anterior <li> sino del <ul> que tienen cerca, por lo tanto todos los <li> tendrán un tamaño de fuente de 32px.

Lo mas probable es que no quieras usar em en este escenario, en su lugar, usa rem ya que em puede convertirse en un problema y puede llevar a consecuencias no deseadas en tus diseños.

Este problema es la razón por la que se creo la unidad rem. El uso de rem no causa un “problema de herencia” del font-size, rem no cambiara sin importar la profundidad a la que este anidado por lo que es una opción fiable y es la medida preferida para la propiedad font-size.

📏REM

La unidad rem, abreviatura de root em, se basa siempre en el valor del font-size del elemento raíz, que es el elemento <html> Si el elemento <html> no tiene un font-size especificado, se utiliza el valor por defecto del navegador que es 16px .

Los valores en rems se calculan multiplicando en base al valor del font-size del elemento root (<html>) del documento:

Si el font-size del <html> es 16px, 1rem sería igual a 16px en cualquier parte del documento.

Al utilizar la unidad rem se ignoran los valores del font-size de los elementos padre y solo se tiene en cuenta el valor del font-size del <html>.

Como puedes ver en el ejemplo anterior de Codepen 👆, el uso de unidades rem nos permite evitar el “efecto compuesto” de las unidades em . Con rem las cosas se basan siempre y consistentemente en el font-size del <html>.

Lo mismo ocurre con otros valores distintos del font-size (margin , padding ,…). El uso de las unidades rem en ellos seguirá siendo relativo al font-size del <html> .

Cuando el navegador analiza un documento HTML, crea una representación en memoria de todos los elementos de la pagina. Esta representación se llama DOM (Document Object Model). Es como una estructura de arbol, donde cada elemento esta representado por un nodo. El elemento <html> es el nodo de nivel superior, después de el están los nodos hijos que son <head> y <body> y debajo de estos están sus hijos, después los hijos de estos, y así sucesivamente.

El nodo raíz, es decir el <html>es el ancestro de todos los demás elementos del documento. Dispone de un selector especial de pseudoclase llamado :root que puede utilizarse para dirigirse a el. Esto equivale a utilizar el selector de tipo <html>

Como dije al principio el elemento <html> heredara cualquier tamaño de fuente predeterminado, establecido en el navegador. Por ejemplo, considera un sitio web donde no se haya establecido la propiedad font-size en el <html> , si un usuario tiene su navegador con el tamaño de fuente predeterminado que es 16px , el font-size del <html> será de 16px .

Si el usuario sube el tamaño de fuente de su navegador, por ejemplo a 18px , el tamaño de fuente del <html> se convierte a 18px .

🥴 ¿Cuándo usar em y rem?

El uso de em y rem van de la mano con los temas de responsive design, usabilidad y accesibilidad. En realidad no hay una unidad mejor, todo depende de tus preferencias personales.

A muchos desarrolladores les gusta diseñar todo en unidades rem para mantener la coherencia. Mientras que a otros les gusta utilizar también unidades em solo en lugares específicos en los que la influencia de elementos padre tendría sentido.

Sin embargo, te daré algunas reglas generales que se usan en algunas situaciones.

🧐 Cuando y como utilizar em:

  • Para la propiedad padding en componentes como botones o inputs.

El siguiente ejemplo se muestra cómo se puede utilizar em para el diseño de componentes responsive.

El border, el padding y el border-radius utilizan unidades em que se relacionan con el valor del font-size. El botón crece de manera proporcional al tamaño de fuente del texto. Los diferentes tamaños de los botones se definen con los selectores de clase concretos (por ejemplo, size-l).

La ventaja de este enfoque es que puedes reutilizar fácilmente estos componentes en diferentes lugares. Sólo tienes que definir diferentes valores de tamaño de fuente para los diferentes contenedores de contexto, y luego la herencia hace el resto.

  • Puedes usar em Para la propiedad letter-spacing, usando un micro valor como 0.03em, también puede ser un valor negativo.
  • Puedes usar la unidad em en los breakpoints de las media queries.

Muchas veces se configura los breakpoints en unidades em para mantener la coherencia en todos los navegadores porque Safari hace algo diferente si usa rem o pixeles en comparación con los otros navegadores.

@media (min-width: 62em){  } ✅

Zell Liew tiene un articulo de pruebas que hizo con diferentes unidades (em, rem y px), concluyendo que los em fueron “la única unidad que se mostro constante en los cuatro navegadores”. Hay algunos errores en Safari que Dan Burzo ha documentado, en los que al hacer zoom el breakpoint de un Smartphone se muestra antes de lo que debería.

🧐 Cuando y como utilizar rem:

  • Para la propiedad font-size.

En mi articulo anterior te mencione que es recomendable usar unidades rem para el texto porque tiene importantes beneficios de accesibilidad, se adaptan a las preferencias del usuario, mientras que si usa pixeles puede sobrescribir estas preferencias.

1️⃣ Muchos desarrolladores restablecen el font-size del <html> a62.5%. De este modo reducen el valor predeterminado de 16px hasta 10px y así pueden realizar los cálculos en múltiplos de 10, más simple y sencillo; de manera que si quieres un texto en 21px puede establecer el font-size del texto en 2.1rem porque 2.1 * 10 = 21.

Entonces 1rem = 10px

html {
font-size: 62.5%; /* = 10px */
}

⚠️Este patrón, o mejor dicho, antipatrón (nombrado así en el libro de CSS in Depth) ha sido común durante los últimos años.

Algunos desarrolladores no recomiendan esto, porque esto toma el tamaño de fuente por defecto del navegador que es 16px, y lo reduce a 10px. Esta práctica simplifica las matemáticas: Si tu diseñador te dice que hagas la fuente de un elemento en 14px, puedes fácilmente dividir por 10 en tu cabeza y escribir 1.4 rem, todo mientras sigues unidades relativas.

Inicialmente, esto puede ser conveniente, pero hay un problema con este enfoque. En primer lugar, le obliga a escribir un montón de estilos duplicados. Diez píxeles es demasiado pequeño para la mayor parte del texto, por lo que tendrá que anularlo en toda la página.

Es recomendable que se trabaje en una base 16 (no de 10px), ya que esta es el tamaño de fuente al que esta acostumbrado el usuario.

Te encontrarás configurando los párrafos a 1.6 rem (16px) y en todos los componentes en los que quieras ese tamaño de fuente. Esto introduce más lugares de error, más puntos de contacto en su código cuando necesita cambiar, y aumenta el tamaño de su hoja de estilos.

2️⃣ Otra que es parecida a la anterior es la de Elad Shechter que la mencionó en su cuenta de Twitter:

3️⃣ Algunos desarrolladores establecen el 100% como valor base para el font-size del elemento <html> lo que equivale a 16px que es el tamaño de fuente de la configuración del navegador.

html {
font-size: 100%; /* 100% = 16px */
}

Con este enfoque, estamos utilizando un tamaño de fuente base del 100% y rems para todo lo demás, por lo que el sitio web será accesible. El usuario puede aumentar el tamaño del contenido mostrado ajustando la configuración del tamaño de fuente de su navegador, o haciendo zoom.

Este es el enfoque estándar, que es accesible y es uno de los mas recomendados. Aunque también puedes colocar en el <body> el valor de 1rem ya que de todas maneras la unidad rem se basara en el valor del font-size de <html>que es 16px derivado de la configuración del navegador.

body {
font-size: 1rem; /* 1rem = 16px */
}

4️⃣Otro enfoque es el tema de la tipografía fluida o Fluid Typography que se refiere a una forma de ajustar las fuentes para que escalen a medida que aumente el ancho del viewport y no se requiere de media queries.

Este es un tema un poco avanzado en el que necesitas conocer sobre funciones como calc(), clamp(), unidades de viewport, etc. Hay una variedad de opciones para realizar una tipografía responsiva.

✅ Mantener un sitio web con múltiples breakpoints donde los tamaños de fuente cambian en muchos elementos diferentes puede ser una pesadilla, pero gracias al CSS moderno hay algunos enfoques diferentes que podemos tomar para hacer esto mas fácil, por ejemplo utilizando las variables CSS o funciones como clamp().

Dado que las unidades em y rem van de la mano con la tipografía, si te interesa saber sobre este tema, hice un thread en Twitter sobre los artículos recomendados para aprender sobre tipografía.

🔄Convertir de px a rem

Cuando vas empezando a diseñar sitios web es común pensar en pixeles y luego convertirlos en unidades em o rem o si te ha tocado trabajar con sistemas de diseño, puede que hayas recibido especificaciones de diseño basadas en píxeles con lo cual puedes utilizar una calculadora en línea que haga el trabajo por ti.

Aunque también puedes hacer esto automáticamente con un preprocesador como Sass y hacer una función que te permita convertir de px a ems o rems. Un ejemplo interesante es el que comparte Elad Shechter en su cuenta de Twitter:

Si aun no usas Sass puedes usar la extensión de vscode llamada px to rem.

📚 Lecturas Recomendadas

Gracias por leer 🦸🏻‍♀️
Mis redes sociales donde comparto notas de código:

--

--

Lupita Code 🌄
Lupita Code 🌄

Written by Lupita Code 🌄

🎓System Engineer 🚀 Frontend Developer 📚 Learning AI & Machine Learning 👩‍💻 Content Creator ⬇️ My youtube channel | My opinions are my own.

Responses (1)