Le labo

Expérience 02

Le verre

Toutes les cartes de ce site sont des panneaux translucides. La recette tient en une ligne de CSS — mais si on se trompe d'ingrédient, on obtient du gris flouté, pas du verre.

L'ingrédient qu'on oublie

Presque tout le monde écrit backdrop-filter: blur(20px) et s'arrête là. Le résultat est décevant sans qu'on sache dire pourquoi : ça fait sale, terne, plastique. Il manque un mot.

Regarde les deux panneaux ci-dessous. Même flou, même fond, même bordure. Le seul écart est saturate().

Le même panneau, à un mot près

blur(20px)

saturate(100%)

Sans saturation

blur(20px)

saturate(180%)

Avec saturation

Celui de droite ressemble à du verre. Celui de gauche à une vitre sale. La raison est physique : flouter, c'est faire la moyenne des pixels voisins. Or la moyenne de couleurs vives est toujours plus terne que les couleurs d'origine — le rouge et le bleu voisins donnent un gris violacé. Le flou délave mécaniquement ce qu'il traverse.

Le vrai verre ne fait pas ça. Il diffuse la lumière sans lui retirer sa couleur. saturate(180%) rend ce que le flou a pris.

Ce qu'il faut retenir : ce n'est pas le flou qui fait le verre, c'est la saturation restituée après le flou. Sans elle, l'effet retombe systématiquement — et on cherche en vain du côté du rayon de flou ou de l'opacité.

À toi de régler

Réglage en direct

Panneau de verre

blur(20px) saturate(180%)

Passe la saturation à 100 % : le panneau meurt instantanément, quel que soit le flou. Puis coupe l'arête lumineuse — c'est le troisième ingrédient.

L'arête qui capte la lumière

Une vraie plaque de verre a une épaisseur. Sa tranche supérieure attrape la lumière et forme un liseré clair d'un pixel. C'est ce que simule cette ombre intérieure :

box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22);

Un pixel blanc à 22 %, en haut seulement. C'est ridicule à écrire et c'est ce qui donne l'épaisseur — sans cette ligne, le panneau est une découpe plate posée sur le fond.

Le liseré iridescent

Sur la page d'accueil, la carte principale porte un arc de lumière qui tourne lentement. Le problème : CSS ne sait pas appliquer un dégradé à une bordure. La technique contourne l'obstacle.

.iris::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;                        /* l'épaisseur du futur liseré */
  background: conic-gradient(from var(--angle), …);
  mask: linear-gradient(#000 0 0) content-box,
        linear-gradient(#000 0 0);
  mask-composite: exclude;             /* garde la couronne, jette le centre */
}

On pose un rectangle entièrement rempli du dégradé, puis on en découpe le centre. Deux masques se superposent : l'un couvre la boîte de contenu, l'autre la boîte entière ; exclude ne conserve que leur différence — soit exactement l'anneau de 1 px du padding. Ce qui reste est une bordure en dégradé.

L'angle est animé via @property, qui déclare --angle comme un vrai angle. Sans cette déclaration, le navigateur traite la variable comme du texte et l'animation saute de 0° à 360° sans passer par les valeurs intermédiaires.

Ce qui casse, et le filet

  • Il faut quelque chose derrière. backdrop-filter floute ce qui est sous l'élément. Sur un fond uni, l'effet est rigoureusement invisible — d'où le fond coloré et rayé des démos de cette page.
  • Ça coûte cher. Chaque panneau force le navigateur à recomposer la zone sous lui. Une dizaine à l'écran et un téléphone d'entrée de gamme rame.
  • Tout le monde ne l'a pas. D'où le filet, qui remplace la transparence par un gris opaque quand le navigateur ne sait pas faire — plutôt qu'un texte blanc sur fond blanc :
@supports not (backdrop-filter: blur(1px)) {
  .glass { background: rgba(20, 20, 24, .85); }
}
Expérience précédente Le réseau