@supporting lo insoportable en tu CSS
Published: 2024-03-16 09:13:14

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yxj6gjoyglbsjxx8r5ih.png)

En CSS es complicado seguir una estrategía [multi-target bundle](https://medium.com/centraalacademy/multi-target-bundling-porque-tenemos-que-pensar-en-el-presente-74d2bf852d72) (En resumen definir un baseline para con un bundle legacy y uno "moderno"). Ya que no tenemos en el tag [link](https://developer.mozilla.org/es/docs/Web/HTML/Element/link) un atributo similar a [nomodule del tag script](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#nomodule). 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](https://browsersl.ist/) e incluimos [plugins de PostCSS](https://postcss.org/docs/postcss-plugins) 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?](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/04oqitwr4q8464o5zeg4.png)

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](https://modernizr.com/) 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](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_conditional_rules/Using_feature_queries), que al igual que los media queries, son una forma de definir un [grupo de reglas basado en ciertas condiciones](https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule#conditional_group_rules).

Para esto usamos la regla [@supports](https://developer.mozilla.org/en-US/docs/Web/CSS/@supports), esta lo que evalua es que la condición sea válida y solo eso ([caniuse](https://caniuse.com/css-featurequeries) nos respalda XD).

```css
@supports <condicion> {
  /* Tu CSS va aquí */
}
```

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](https://web.dev/blog/viewport-units).

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qww3ue0ti8zkwzzlnxn7.png)

Según [caniuse](https://caniuse.com/viewport-unit-variants) 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3uqdv83r48mu0gyeccmx.png)

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

```html
<!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>
```

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

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

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

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](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) para no tener que recordar el selector y compartir esto usando la cascada.

Luciría así

```css
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);
}
```

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

![Meme me atrapaste es cine](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9a0y4qv2f0ottp7bwhal.png)

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](https://developer.mozilla.org/es/docs/Web/CSS/:root) con el valor base que debería tomar para representar el alto mínimo de una página.

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

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.

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

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9mv5wb889ldj4e553xdl.png)

Y al final simplemente usamos la custom property que definimos:

```css
.main {
  background-color: #ffdd00;
  min-height: var(--page-height);
}
```

Recomiendo que sigas el ejemplo que hicimos pero si quieres también te dejo un [código](https://codepen.io/dezkareid/pen/PoLMMVE) 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 :)