Viewport Units en CSS: ¿Por qué existen y cómo usarlas? - Parte 1
septiembre 21, 2024 - 9 minutos de lectura
Este artículo consta de dos partes. La primera incluye el contexto y la teoría, mientras que la segunda cubre la práctica. Si lo prefieres, puedes ir directamente a la segunda parte.
La web se diseñó para dispositivos de escritorio. Por tanto, aunque en sus inicios existían diferentes unidades de medida, los píxeles y porcentajes eran más que suficientes para ajustar cualquier diseño. Con la aparición de dispositivos móviles y la complejización de las UI, surgieron también nuevas unidades de medida.
vw
y vh
, las primeras viewport units
El porcentaje es una medida relativa al padre. Por tanto, para hacer un contenedor que usara el 100% del alto de la pantalla, todos los altos de sus ancestros debían ser también de 100%. De no ser así, el tema se complicaba. Para eso llegaron al rescate el vw
(viewport width) y el vh
(viewport height). Con estas unidades de medida ya no dependemos de las dimensiones del padre, sino del viewport, que para términos prácticos, lo definiremos como el rectángulo que ocupa tu página web en la pantalla, quitando los elementos gráficos propios del navegador (barras de navegación, de favoritos, etc.).
1vw
equivale al 1% del ancho de viewport y1vh
al 1% del alto del viewport.
Así pues, si queremos que un contenedor tenga exactamente el 100% del ancho y la mitad del alto de la pantalla (del viewport, para ser más exactos), debería bastar con definir el ancho y alto con las unidades vh
y vw
.
.element {
height: 50vh;
width: 100vw;
}
El problema de los móviles
En desktop, este enfoque funciona sin problemas. El viewport allí casi siempre es del mismo tamaño, y cuando cambia es por alguna acción del usuario que afecta toda la visualización: redimensionar el navegador, mostrar u ocultar la barra de favoritos, abrir el modo de pantalla completa, etc. En estos casos, el tamaño del viewport se reajusta, reajustando también la medida de los componentes dependientes de él.
En móviles funcionó al inicio cuando los navegadores tenían diseños estáticos: en la parte superior había una barra de navegación siempre visible y debajo la página web. Supongamos que un teléfono móvil de 320px
de alto abría un navegador con una barra superior ocupando 30px
. Esto dejaba 290px
para la página web. Esa era la altura del viewport y correspondía a los 100vh
de modo que 1vh = 2,9px
.
Pero las pantallas de los móviles son pequeñas y esto llevó a los navegadores a buscar una experiencia de usuario más cómoda. Aunque no todos lo han hecho igual, el patrón se parece bastante: el navegador carga con algunos elementos propios de su interfaz (una barra de direcciones, flechas de navegación, etc.) y un espacio dedicado a la página. A medida que el usuario interactúa con la página (normalmente al hacer scroll hacia abajo), el navegador "achica" sus elementos gráficos propios, ya sea haciéndolos más compactos u ocultándolos por completo. En cuanto el usuario realiza cierto gesto (normalmente scroll hacia arriba o tap), los elementos gráficos del navegador vuelven a su tamaño original, achicando el espacio disponible para la página.
Esto hizo que los viewports no tuvieran un tamaño estático, sino que variara según las interacciones. El primer enfoque que llevaron a cabo los navegadores fue ajustar dinámicamente las medidas vh
y vw
al tiempo que se ajustaba el viewport. Parecía lógico, pero trajo más problemas que ventajas. Volvamos al ejemplo de un celular con una altura de 320px
, una barra de navegación de 30px
y 290px
de espacio para la página. En este punto, 100vh = 290px
, por lo que 1vh = 2,9px
. Supongamos que ese navegador, durante el scroll, oculta por completo la barra de navegación, haciendo que el espacio para la página crezca hasta los 320px. Cuando esto ocurre, 1vh = 3,2px
, ajustando toda la UI.
Imaginemos que la página es un marketplace que muestra 20 productos verticalmente, uno bajo el otro, cada uno ocupando media pantalla verticalmente. Inicialmente, cada producto ocupará 50vh = 145px
de altura, haciendo que la página completa mida 2900px
. Pero cuando el usuario empieza a hacer scroll y la barra se oculta, el viewport crece hasta los 320px
y, con ello, cada producto ahora ocupa 50vh = 160px
, para una altura total de 3200px
. Este simple reajuste causó una diferencia de 300px
en la altura total de la página, que además se suman y se restan continuamente según las interacciones del usuario.
Esto, por supuesto, generó miles de problemas y efectos no deseados que llevaron a cambiar el enfoque.
Adiós al vh
y vw
con ajuste automático
En aquel entonces, el estándar de la W3C no especificaba cómo debían comportarse el vh
y el vw
en esos casos, sencillamente porque cuando el estándar del momento se definió aún no existía el problema. En cuanto apareció, fueron los mismos navegadores quienes tuvieron que tomar la decisión, empezando con Safari. Y la decisión fue que estas medidas no deberían ajustarse automáticamente.
¿Entonces? Sencillo: El vh
y el vw
debían ajustarse siempre al mayor tamaño que el viewport pudiera tomar. Para nuestro ejemplo, 100vh = 320px
siempre, tanto si la barra estaba visible como si no.
Esto resolvió el problema de los cambios de tamaño automáticos inesperados, pero trajo nuevos problemas: muchas páginas web en móviles están planteadas para mostrar información por bloques de acuerdo con el tamaño de la pantalla. En nuestro ejemplo del marketplace, sin importar el scroll, siempre deberían caber dos productos en pantalla. Con este nuevo enfoque, cada producto mediría siempre 50vh = 160px
. Cuando la barra fuera visible, faltarían 30px
para mostrar los dos y no habría cómo solucionar ese problema con las unidades de medida existentes.
Otros navegadores prefirieron lo contrario: quedarse con la medida más pequeña que el viewport pudiera tomar, es decir, aquella en la que todos los elementos gráficos del navegador están en su tamaño máximo. En nuestro ejemplo, sería 100vh = 290px
. Como podrías imaginar tendríamos el mismo problema, pero al revés.
Solución: Que el programador decida
Como pudimos ver en el ejemplo, no hay una solución definitiva que resuelva el problema usando vh
y vw
. Según la necesidad de la página, podría ser más útil un enfoque que otro. Entonces, la solución fue salomónica: crear nuevas unidades de medida para todos los enfoques descritos (y otros más), de modo que, según las propias necesidades, cada quien pueda usar el que más le convenga.
Hasta aquí la contextualización e historia detrás del problema. Para ver las nuevas (ya no tan nuevas) unidades de medida, su detalle, explicación y ejemplos de uso, puedes leer la segunda parte de este artículo haciendo clic aquí.