En las implementaciones actuales de los navegadores con CSS, no es posible dividir por tipos de longitud; calc(100vw / 5px) no funciona. Eventualmente lo hará, ya que está en la especificación, y con suficiente soporte podría suceder pronto. Pero, por ahora, no hay forma de producir escalares basados en el tamaño.
Con una excepción emergente, técnicamente hablando: atan2():
¿Cómo funciona atan2() y tan() en CSS?
La función atan2() en CSS es una función trigonométrica que toma dos parámetros: el primero representa la altura (height) y el segundo el ancho (width). Estos parámetros definen una pendiente, donde la altura es el “aumento” y el ancho es la “base”. Al aplicar atan2(height, width), obtenemos el ángulo que representa esa pendiente, midiendo desde la base (parte inferior) hasta la cima.
Pero aquí viene lo interesante: si tomamos ese ángulo y aplicamos la función tan() (la tangente del ángulo), obtenemos lo que se llama un “escalar”. Este escalar es un valor numérico que refleja la relación entre la altura y el ancho, o dicho de otra manera, es la proporción entre ambas dimensiones:
- atan2(height, width) devuelve el ángulo de la pendiente formada entre height y width.
- Luego, tan(atan2(height, width)) devuelve un número que indica la relación entre estas dos dimensiones.
Este escalar puede ser muy útil en CSS, ya que nos permite hacer cálculos que dependen de la proporción entre el alto y el ancho de un elemento o ventana. Por ejemplo, podríamos usar este valor para escalar dinámicamente el tamaño de un elemento en función de la relación entre su altura y anchura.
Ejemplo Práctico
Imagina que tienes un contenedor cuyo tamaño debe ajustarse dinámicamente según las dimensiones de la ventana del navegador. Usando atan2() y tan(), podríamos calcular un valor de escala que se mantenga proporcional, sin importar cómo el usuario redimensione la ventana:
En este caso:
- –angle calcula el ángulo entre el alto (100vh) y el ancho (100vw) de la ventana.
- –scale toma la tangente de ese ángulo, que es el escalar entre estas dos dimensiones.
- Finalmente, usamos el valor de –scale para aplicar una transformación scale() al contenedor, ajustando su tamaño dinámicamente según la relación entre el alto y el ancho de la ventana.
¿Por qué es útil?
Este tipo de técnicas trigonométricas en CSS abre la puerta a crear diseños completamente dinámicos y adaptables sin necesidad de JavaScript. Podríamos ajustar tamaños, rotaciones o incluso posiciones de elementos simplemente basándonos en las dimensiones del viewport.
tan(atan2()) es solo un escalar
Fundamentalmente, tan(atan2()) es solo un escalar entre dos dimensiones.
A continuación veremos cómo usar el escalado de identidad para convertir (o “typecast”) dimensiones en un valor numérico. Sin embargo, hay muchas otras formas en las que este concepto puede aplicarse para comparar cualquier par de dimensiones.
Tamaño de Pantalla
Una de las cosas que muchos desarrolladores desean es obtener el valor numérico en píxeles del ancho (o alto) del viewport para poder calcular la relación de aspecto u otros cálculos más adelante, y hoy en día es mucho más fácil y rápido usando tan(atan2()).
Esto debería ser tan simple como:
Sin embargo, actualmente atan2() es bastante inestable en los navegadores. (La combinación de vw y px estaba destinada a funcionar).
- Chrome devuelve 100 en este caso, lo cual es extraño y no deseado.
- Firefox devuelve cero porque la combinación de unidades falla. Si ambas son vw o ambas son px, Firefox devuelve correctamente 100.
- Safari parece devolver siempre cero para cualquier combinación de Y y X en tan(atan2(Y, X)), ya sea con o sin unidades, mezcladas o coincidentes. (a menos que lo envuelvas en calc()).
Por lo tanto, por ahora necesitamos obtener 100vw como NNNpx, lo cual es sencillo en CSS, ya que esto ocurre automáticamente si registras una variable como <lenght> y la estableces con un valor como –100vw: 100vw.
Ahora, esto funciona en Chrome tal como esperábamos:
En este caso, –px-width será el ancho de la pantalla como un número, generalmente un entero.
Aquí está en funcionamiento, incluyendo un ejemplo para 100vh también: (este ejemplo es mejor verlo en codepen redimensionando la ventana del navegador)
Obtener el tamaño de fuente y más
Puedes utilizar esta misma idea para cualquier unidad en consultas de contenedores, calcular tamaños que contengan unidades mixtas, averiguar el tamaño en píxeles de rem, lo que necesites. Solo tienes que registrar una longitud, establecer su valor y convertirlo a píxeles numéricos con tan(atan2()).
Obtener el tamaño de fuente y más
Puedes utilizar esta misma idea para cualquier unidad en consultas de contenedores, calcular tamaños que contengan unidades mixtas, averiguar el tamaño en píxeles de rem, lo que necesites. Solo tienes que registrar una longitud, establecer su valor y convertirlo a píxeles numéricos con tan(atan2()).
Aqui otro ejemplo con <time>
Cuestión de trigonometría
No es necesario entender la trigonometría detrás de esto para poder usarla, pero me surgieron un par de preguntas en privado al respecto:
tan(ángulo) es una función que toma un ángulo y produce un resultado que es igual a “el lado opuesto sobre el lado adyacente” — es decir, la altura dividida por el ancho de un triángulo rectángulo:
atan(ratio) es una función que toma el valor de la altura dividida por el ancho y devuelve el ángulo; es la inversa de tan().
atan2(Y, X) es una adaptación en lenguajes de programación de atan() que toma la altura (Y) y el ancho (X) como argumentos separados, en lugar de dividirlos antes de pasarlos, y luego devuelve lo mismo que atan habría devuelto.
Entonces, lo que este truco hace es un poco “curioso” en la mayoría de los casos (y probablemente por eso nadie lo mencionó antes), porque estamos usando dos funciones trigonométricas en lugar de simplemente hacer una división, algo que calc() aún no puede hacer.
atan2(Height, Width) = ángulo del triángulo en la imagen de arriba
tan(ángulo) = Altura / Ancho en la imagen de arriba
tan(atan2(Height, Width)) = Altura / Ancho
Si bien estos código pueden tener limitaciones técnicas debido al estado actual del soporte para atan2() y tan() en CSS, es un interesante experimento sobre lo que el futuro del CSS puede ofrecer sin necesidad de JavaScript.
Este articulo está basado en otro escrito en inglés por Jaine Ori