Web Liquid Glass
Un matériau verre de production pour sites web, extrait d'un site Next.js + Tailwind en production. Le code source complet se trouve dans reference/ :
reference/liquid-glass.css: l'intégralité du matériau (tokens, surface, variantes, verre façonné, réfraction, dégradation). Environ 2 200 lignes avec des commentaires détaillés expliquant chaque valeur. Lisez la section dont vous avez besoin plutôt que le fichier entier.reference/glass.tsx: le composant React<Glass>et le filtre de réfraction SVG.reference/glass-specular.tsx: le reflet spéculaire avec suivi du pointeur et de l'inclinaison.
La référence importe deux helpers du site (cn et LITE_CLASS d'un module de mode allégé). Remplacez-les par le cn/clsx du projet, ainsi qu'un nom de classe pour "effets désactivés". Les règles nommées sky-*, kiosk-* et les sélecteurs liés à la prière sont des exemples de variantes spécifiques au site. Supprimez-les ou utilisez-les comme modèles.
Ce qu'est le verre
Le verre comporte quatre parties. Une version web semble bon marché lorsqu'elle ne livre que la première :
- Matériau : un flou ET une augmentation de la saturation (environ 200 %). En dessous de ~150 %, il donne l'impression d'un plastique gris. Ajoutez une augmentation de la luminosité et une réduction du contraste pour que le contenu chargé derrière se diffuse en un lavis doux.
- Bord : un filet lumineux là où la lumière attrape le bord, plus sombre sur le bord opposé. Un flou sans bord ne donne jamais l'impression du verre.
- Brillant : un reflet spéculaire doux à l'intérieur du bord supérieur.
- Profondeur : une ombre large, très douce et de faible opacité, pas une ombre de carte serrée.
La réfraction (le contenu se plie au bord) est une cinquième partie, et la seule que le Web ne peut pas faire à moindre coût. Elle nécessite backdrop-filter: url(#svg-filter), qui fonctionne uniquement dans Chromium.
Où mettre du verre
Mettez du verre sur la couche de navigation (barres, navs capsule, contrôles flottants, panneaux), pas sur le contenu du corps. Le contraste du texte sur le verre dépend de ce qui défile derrière, il ne peut donc pas être garanti. Gardez les cartes opaques par défaut pour le contenu et rendez le verre optionnel par surface (.lg).
Règles qui coûtent du temps réel
- Le CSS du verre doit vivre dans le même fichier que
@tailwind base, à l'intérieur de@layer. Tailwind résout@layerpar fichier, donc un fichier CSS séparé génère une erreur sur@layer base. Supprimer le wrapper rend les règles non ordonnées en couches, et les règles non ordonnées battent chaque utilitaire Tailwind..lg { position: relative }remplace alors silencieusementfixedsur une nav. - N'écrivez jamais
--x: calc(var(--x) * 0.7). C'est un cycle : invalide au moment du calcul de la valeur, il retombe silencieusement sur la valeur héritée sans erreur. Utilisez une deuxième variable (--lg-clarity-bump,--lg-press). - Une surface en verre a exactement un bord, et
::beforele dessine. Deux bords (un bord::beforeplus des biseauxbox-shadowintérieurs, ou une ombre étendue en dehors de la boîte de bordure) donnent une "double bordure" qu'aucun réglage d'alpha ne peut corriger. corner-shapen'est pas hérité. Aveccorner-shape: squirclesur la surface, chaque pseudo-élément dessinant sur la bordure a besoin à la fois deborder-radius: inheritetcorner-shape: inherit, sinon le bord suit une courbe différente du corps.- Pas de
backdrop-filtersur du verre imbriqué dans du verre. Il échantillonne un arrière-plan déjà teinté et devient terne. Une puce de sélection dans une barre en verre (.lg-chip) est une lentille teintée sans son propre flou. - N'animez pas une propriété personnalisée héritée sur
:root. Cela invalide le style de tout le document : environ 11,6 ms par image sur une page de 60 surfaces, contre 2 ms pour écrire la même valeur par élément. - Les barres refloutent à chaque image de défilement. Donnez à
.lg-barun rayon de flou plus petit pluscontain: paint. Si un appareil est encore saccadé, réglez--lg-blur-bar: 0px; le bord et le brillant portent l'essentiel du rendu. - N'aplatissez pas le verre givré pour corriger un défaut. Une barre de "couleur unie" presque opaque perd le rendu. Cherchez plutôt la cause géométrique (des masques amincissant le corps au bord, un bord doublé).
- Une lentille de réfraction SVG ne doit jamais échantillonner au-delà de sa propre boîte. Chrome renvoie du transparent à cet endroit et le contenu original apparaît en fantômes.
Safari et iPhone
WebKit prend en charge backdrop-filter mais rejette les filtres SVG à l'intérieur. Safari obtient donc moins que Chrome : pas de réfraction, jamais. Ce que Safari peut réfracter, c'est sa propre barre d'outils. Réglez viewportFit: "cover" pour que la page s'exécute en dessous, puis env(safe-area-inset-*) devient obligatoire sur la barre de navigation et le pied de page.
Accessibilité et solutions de repli (toujours les livrer)
Chaque surface doit se dégrader en une teinte presque opaque qui semble proche et ne coûte rien par image :
@media (prefers-reduced-transparency: reduce)@supports not (backdrop-filter: blur(1px))@media (prefers-contrast: more): une teinte plus forte et un bord solide- une classe racine telle que
.lg-offqui supprime toutes les surfaces en verre d'un coup (pour un basculement utilisateur ou un mode basse consommation)
Donnez aux barres leur propre teinte maximale plus élevée (--lg-tint-max-bar) afin que les liens de navigation conservent le contraste du texte lorsque le contenu défile sous eux.
Comment appliquer
- Copiez le bloc de tokens et la section de surface de
reference/liquid-glass.cssdans le fichier CSS principal du projet, à l'intérieur de ses blocs@layerexistants (règle 1). - Mappez les tokens de couleur à la palette du projet. La référence utilise des tokens de style shadcn
hsl(var(--card)). - Utilisez
<Glass>dereference/glass.tsxou les classes simples.lg,.lg-bar,.lg-nav,.lg-pane,.lg-chipet.lg-refract. - Ajoutez le reflet spéculaire de
reference/glass-specular.tsxuniquement là où il vaut son coût (contrôles hero, la barre de navigation principale), et respectezprefers-reduced-motion. - Vérifiez dans Chrome ET Safari, en mode clair ET sombre, sur une photo chargée et sur du texte simple.
Contrôles prêts à l'emploi : Glisse
Glisse par Kelvin Zhang (npm install glisse, MIT, React 18+, aucune autre dépendance) livre des contrôles Liquid Glass interactifs avec le comportement de lentille press-to-lift déjà intégré : Button, Switch, Slider, TabBar, SegmentedControl, Menu, Input, SearchField et une surface Glass simple. Ses styles sont injectés par le bundle JS, donc il n'y a pas de fichier CSS à importer.
Quand utiliser quoi :
- Glisse pour les contrôles : interrupteurs, curseurs, barres d'onglets et contrôles segmentés dont le pouce se soulève dans une lentille lors du glissement. Construire cela à la main représente des jours de travail.
- Ce matériau pour les surfaces : barres de navigation, navs capsule, panneaux, feuilles, cartes sur des photos, et tout ce qui doit correspondre à un système de design existant ou à un thème Tailwind.
Pièges lors de la combinaison :
- Les deux utilisent le préfixe
lg-. Glisse définit.lg-glass,.lg-button,.lg-tab-baret les variables--lg-blur,--lg-tint,--lg-rimet--lg-filter, qui entrent en conflit avec les tokens de ce matériau. Sur une page qui utilise les deux, renommez le préfixe de ce matériau (par exemple enylg-) ou limitez Glisse à l'intérieur d'un wrapper qui réinitialise ces variables. Sinon, chacun ajuste silencieusement l'autre. - Le mode sombre de Glisse s'active via
data-theme="dark"ouprefers-color-scheme, pas la classe.darkde Tailwind. Avec un mode sombre basé sur les classes, définissezdata-themesur<html>en plus de.dark, sinon Glisse reste en mode clair. - Glisse gère
prefers-reduced-motionmais pasprefers-reduced-transparencyniprefers-contrast. Ajoutez les solutions de repli de la section accessibilité de cette compétence autour des contrôles Glisse. - Le
.lg-glassde Glisse dessine déjà un bord avec unbox-shadowintérieur. N'ajoutez pas de bord::beforepar-dessus (règle 3 : un seul bord).