DEV Community

Joel Humberto Gómez Paredes
Joel Humberto Gómez Paredes

Posted on

@supporting lo insoportable en tu CSS

Con el paso del tiempo los major browsers han estado agregando soporte a varias features de CSS, lo cual es bastante genial :D ... pero, siempre hay un pero. Es complicado que todos se pongan de acuerdo y liberen las mismas features importantes a la vez, además de que es prácticamente imposible que todos nuestros usuarios tengan su browser actualizado en todo momento.

Gatito triste

En CSS es complicado seguir una estrategía multi-target bundle (En resumen definir un baseline para con un bundle legacy y uno "moderno"). Ya que no tenemos en el tag link un atributo similar a nomodule del tag script. Adémas de que este approach poco a poco dejará de ser usado porque cada vez son menos los browsers donde valga la pena dar ese soporte.

Actualmente lo que hacemos es usar una estrategia de fallbacks para resolver este problema (parcialmente). Definimos un baseline y usando browserslist e incluimos plugins de PostCSS u otras tools que agregarán los fallbacks o mantendrán intactor el código dependiendo de si la feature que usamos tiene soporte o no en el baseline definido.

Patricio estrella diciendo "¿El Para que cosa de quien?

Aún así es complicado soportar ciertas features de CSS modernas o no estandarizadas porque solo sabemos si el soporte existe en tiempo de ejecución y la estrategia mencionada anteriormente se realiza en tiempo de compilación.

Antes usabamos Modrnizr pero JS es parse blocking y tendríamos el mismo problema para features nuevas.

Para esto podemos usar algo que en CSS se llama Feature queries, que al igual que los media queries, son una forma de definir un grupo de reglas basado en ciertas condiciones.

Para esto usamos la regla @supports, esta lo que evalua es que la condición sea válida y solo eso (caniuse nos respalda XD).

@supports <condicion> {
  /* Tu CSS va aquí */
}
Enter fullscreen mode Exit fullscreen mode

Esto no es nada nuevo, igual y este post no te aporta nada pero vamos a tratar de que lo haga. Con un caso práctico que me sucedio recientemente: Las nuevas unidades del viewport.

Soy fan del min-height: 100vh pero esta regla no da los resultados deseados en dispositivos móviles debido al comportamiento de la UI, por ejemplo la toolbar que se agrega en la parte de abajo en dispositivos iOS en Safari.

Patricio levantando el meñique

Según caniuse esta feature esta desde noviembre del 2022 en major browser pero en Android Browser(chromium) se libreró febrero de 2024.

Ahora vamos a lo bueno, un mini demo. Haremos algo simple, que una página tenga el 100% del viewport, algo común pero muy significativo.

Meme ahora si se viene lo chido

Comenzamos creando un index.html con el esqueleto de la página

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="styles.css">
  <title>Viewport</title>
</head>
<body>
  <main class="main" />
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Creamos nuestro archivo styles.css. Como primer paso usaremos vh y después agregaremos el soporte.

html, body {
  margin: 0;
  padding: 0;
}

.main {
  background-color: #ffdd00; /* Si, es el color del super saiyajin */
  min-height: 100vh;
}
Enter fullscreen mode Exit fullscreen mode

Si pruebas esto en un iphone, lo mas probable es que tengas un horrible scroll.

Ahora vamos a agregar el soporte para usar un min-height: 100dvh pero usando custom properties para no tener que recordar el selector y compartir esto usando la cascada.

Luciría así

html, body {
  margin: 0;
  padding: 0;
}

:root {
  --page-height: 100vh;
}

@supports (min-height: 100dvh) {
  :root {
    --page-height: 100dvh;
  }
}

.main {
  background-color: #ffdd00;
  min-height: var(--page-height);
}
Enter fullscreen mode Exit fullscreen mode

Ahora si pruebas en un dispositivo iOS o similar, ese scroll debería haber desaparecido.

Meme me atrapaste es cine

Bueno, vamos a explicar paso por paso. Siguiendo una estrategia estilo progressive enhancement, lo primero que se hace es definir una custom property --page-height en el selector :root con el valor base que debería tomar para representar el alto mínimo de una página.

:root {
  --page-height: 100vh;
}
Enter fullscreen mode Exit fullscreen mode

Ahora usaremos supports para asignar el valor a 100dvh a nuestra custom property --page-height.

La sintaxis me pide evaluar una condición y esta debe ir entre paréntesis, esta condición es formada por <propiedad>: <valor> (un estilo). Si el estilo es válido la evaluación es verdadera y si no es falsa.

@supports (min-height: 100dvh) {
  :root {
    --page-height: 100dvh;
  }
}
Enter fullscreen mode Exit fullscreen mode

Si dvh no existe como unidad, este bloque jamas se ejecutará porque no sería un estilo válido.

Meme sabes yo también tengo algo de científico

Y al final simplemente usamos la custom property que definimos:

.main {
  background-color: #ffdd00;
  min-height: var(--page-height);
}
Enter fullscreen mode Exit fullscreen mode

Recomiendo que sigas el ejemplo que hicimos pero si quieres también te dejo un código similar en codepen. Aunque te recomiendo descargarlo y ejecutarlo en tu maquina porque en los codepen se ejecuta en un iframe (probablemente debí guardarlo en otro lado pero ya estaba ahí XD)

Gracias por llegar hasta aquí si puedes da like y comparte :)

Top comments (0)