Bubble Glass Grid
Douze bulles de verre de 51 px en grille de quatre colonnes : la bulle survolée gonfle à ×1,35 en carré arrondi (pic à ×1,38 par effet ressort), ses deux voisines dans l'ordre du HTML passent à ×1,1 grâce au sélecteur :has() — CSS pur, zéro JavaScript, sur un fond déclaré que le verre floute.
Mis à jour le
Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. Glassmorphism comprend 47 effets, dont 6 gratuits. Découvrir la catégorie →
3 exemples d'usage



Comment ça marche
Une grille, douze div, quatre règles. .lg-bubble-grid pose grid-template-columns: repeat(4, 1fr), gap: 6px et width: 220px : chaque bulle mesure 50,5 px (mesuré 51 × 51 dans Chromium, Firefox et WebKit), trois rangées, grille de 256 × 200 px avec son cadre. Chaque .lg-bubble est un disque (aspect-ratio: 1, border-radius: 50%) en verre : dégradé radial blanc de 25 % à 5 % éclairé à 35 % / 30 %, liseré blanc à 15 %, backdrop-filter: blur(8px), ombre portée et reflet intérieur. Au survol, transform: scale(1.35), border-radius: 40% — le disque devient un carré aux coins très arrondis —, reflet plus fort teinté violet et z-index: 2 pour passer devant ses voisines.
La singularité tient dans une règle à deux sélecteurs : .lg-bubble:hover + .lg-bubble vise la bulle suivante, .lg-bubble:has(+ .lg-bubble:hover) la bulle précédente — un « sélecteur de frère précédent » que seul :has() permet. Les deux passent à scale(1.1) et border-radius: 45%. Mesuré au survol de la sixième bulle : la cinquième et la septième à ×1,1, la sixième à ×1,35, les autres immobiles. Le voisinage suit l'ordre du HTML, pas la géométrie : survolez la quatrième (fin de la première rangée) et c'est la cinquième, première de la rangée suivante, qui réagit ; les bulles du dessus et du dessous ne bougent pas. La transition .5s cubic-bezier(.34, 1.56, .64, 1) dépasse sa cible : mesuré, ×1,384 vers 280 ms puis retour à ×1,35 avant 500 ms, dans les trois moteurs. La grille « respire » autour du pointeur sans une ligne de script.
La grille déclare son propre fond, parce qu'un verre n'existe que s'il a quelque chose à flouter : posées sur un fond uni (celui d'une page, ou le #0a0a0f d'un cadre de démonstration), les bulles ne seraient que des disques gris, un flou de 8 px sur une couleur unie ne se voyant pas. D'où box-sizing: content-box, padding: 18px, border-radius: 26px et quatre pastilles à bord net (rose, bleu, jaune, violet) sur un dégradé indigo. Entre les bulles, les bords des pastilles restent nets ; sous chaque bulle, ils s'adoucissent : c'est ce contraste qui fait lire le verre. Les bulles gardent leurs 51 px, la grille fait 256 px de large avec sa marge intérieure.
Accessibilité
- Clavier et toucher : douze
divsanstabindexni rôle, et un effet réservé à:hover. Au clavier, rien n'est atteignable ; au doigt, un toucher déclenche le survol, qui reste collé jusqu'au toucher suivant ailleurs. Pour une grille de choix, utilisez des<button>(ou des<input type="radio">stylés) et ajoutez:focus-visibleà chaque sélecteur :.lg-bubble:is(:hover, :focus-visible),.lg-bubble:is(:hover, :focus-visible) + .lg-bubbleet.lg-bubble:has(+ .lg-bubble:is(:hover, :focus-visible)). - prefers-reduced-motion absent : sous émulation, la bulle monte toujours à ×1,38 puis redescend à ×1,35 en 0,5 s. Le mouvement ne part que d'un geste de l'utilisateur, mais le rebond est ce qui gêne les personnes sensibles :
@media (prefers-reduced-motion: reduce) { .lg-bubble { transition-timing-function: ease; transition-duration: .15s } }garde le gonflement sans le ressort. - Lecteurs d'écran : les bulles du code vendu sont vides, rien n'est annoncé. Dès qu'elles portent un libellé (parfum, humeur, teinte), donnez à la grille
role="group"et unaria-label, et à chaque bulle un texte réel plutôt qu'une couleur seule — la couleur ne peut pas être la seule information (WCAG 1.4.1). - Contraste : le verre est blanc à 5-25 % sur le fond de la grille ; un texte posé dans une bulle se lit sur la couleur floutée qui passe dessous. Les scènes de cette page mettent un texte blanc avec
text-shadow: 0 1px 4px rgba(0,0,0,.55): il tient sur les teintes moyennes et sombres, il faiblit sur les plus claires (vanille, coco) — passez le texte en sombre sur ces cases ou foncez la pastille.
Compatibilité navigateur
CSS seul : grille, aspect-ratio, backdrop-filter, :has(), transitions. Zéro JavaScript, zéro dépendance. Mesuré dans Chromium 151, Firefox 153 et WebKit 26 : mêmes tailles (bulles de 51 px), même gonflement (×1,35, pic ×1,384), mêmes voisines à ×1,1. backdrop-filter est déclaré avec et sans préfixe (-webkit-backdrop-filter), ce qui couvre Safari avant la version 18. Le point sensible est :has() : Chrome et Edge 105, Safari 15.4, Firefox 121. Un navigateur qui ne le connaît pas jette la règle entière, les deux sélecteurs avec — mesuré en remplaçant :has() par un sélecteur inconnu, la règle n'est pas retenue dans les trois moteurs : la bulle survolée gonfle toujours, mais aucune voisine ne réagit.
Sans :has() (Chrome < 105, Firefox < 121, Safari < 15.4), la règle des voisines tombe en entier : seule la bulle survolée gonfle. Pour garder au moins la voisine suivante, séparez la règle en deux, une par sélecteur. Sans backdrop-filter, les bulles restent des disques translucides sur le fond de la grille, sans flou. Sans aspect-ratio (avant 2021), les bulles s'écrasent à la hauteur de leur contenu : donnez-leur une hauteur fixe.
Le code
Structure HTML à coller dans votre page (le CSS + JS sont inclus avec Premium) :
<div class="demo-preview">
<div class="lg-bubble-grid">
<div class="lg-bubble"></div>
<div class="lg-bubble"></div>
… (12 bulles)
</div>
</div>
Le code complet HTML + CSS + JS de Bubble Glass Grid, prêt à coller — et les 840 effets. Ou 299 € TTC une fois, accès à vie.
Personnaliser
Options passées à l'API ou attributs data-* :
| Option / propriété | Défaut | Effet |
|---|---|---|
Taille de la grille (CSS — .lg-bubble-grid { width: 220px }) |
220 px de contenu, bulles de 50,5 px | Bulle = (largeur − 3 × gap) ÷ 4. 270 px donnent des bulles de 63 px, 400 px des bulles de 96 px. |
Nombre de colonnes (CSS — grid-template-columns: repeat(4, 1fr)) |
4 colonnes, 12 bulles sur 3 rangées | Les voisines sont celles du HTML : avec 3 colonnes, la bulle 3 fait réagir la 4, première de la rangée suivante. Ajoutez min-width: 0 aux bulles si elles portent du texte, sinon un mot long élargit sa colonne. |
Gonflement (CSS — .lg-bubble:hover { transform: scale(1.35); border-radius: 40% }) |
×1,35, carré arrondi à 40 % | scale(1.2) pour une grille serrée, border-radius: 50% pour garder le disque. Au-delà de ×1,5, la bulle recouvre largement ses voisines : augmentez le gap. |
Réaction des voisines (CSS — .lg-bubble:hover + .lg-bubble, .lg-bubble:has(+ .lg-bubble:hover)) |
voisine précédente et suivante à ×1,1, rayon 45 % | Pour faire reculer les voisines au lieu de les grossir : scale(0.92). Pour toucher aussi la deuxième voisine : .lg-bubble:hover + .lg-bubble + .lg-bubble et .lg-bubble:has(+ .lg-bubble + .lg-bubble:hover). |
Ressort (CSS — transition: .5s cubic-bezier(.34, 1.56, .64, 1)) |
0,5 s, pic à ×1,384 vers 280 ms | Le 1,56 crée le dépassement. cubic-bezier(.34, 1.2, .64, 1) l'atténue, ease le supprime. La même transition s'applique au retour : la bulle quittée rebondit aussi. |
Fond derrière le verre (CSS — .lg-bubble-grid { background: … }) |
4 pastilles nettes sur dégradé indigo, cadre de 18 px arrondi à 26 px | Remplacez-le par une photo (url(…) center / cover) ou une pastille par case comme dans les scènes. Un fond uni rend le flou invisible : gardez des bords nets ou des détails sous les bulles. |
Flou du verre (CSS — backdrop-filter: blur(8px)) |
8 px | 4 px laissent deviner le dessin sous la bulle, 14 px n'en gardent que la couleur. Modifiez la valeur avec et sans préfixe -webkit-. |
FAQ
z-index: 2) : elle recouvre ses voisines, elle ne se soude pas à elles. Un vrai effet de fusion demande un filtre SVG de type « gooey » (flou puis seuil de transparence) appliqué à la grille entière, et ce filtre détruit le verre : le seuil efface le dégradé translucide et le reflet. Les deux effets ne se combinent pas.+ désigne le suivant, :has(+ …) le précédent. La grille dessine des rangées, mais le HTML est une suite de douze éléments ; pour la bulle 6, les voisines sont la 5 et la 7, et pour la 4, ce sont la 3 et la 5 — la 5 étant au début de la rangée suivante. Pour viser la bulle du dessous en grille de 4, il faut sauter trois frères : .lg-bubble:hover + * + * + * + .lg-bubble, et .lg-bubble:has(+ * + * + * + .lg-bubble:hover) pour celle du dessus. Ça marche tant que le nombre de colonnes ne change pas.backdrop-filter floute ce qui est derrière l'élément ; sur un aplat, le résultat est le même aplat. C'est pourquoi la grille déclare son propre fond (pastilles nettes sur dégradé) : si vous le retirez pour poser la grille sur votre page, il faut que la page ait du détail derrière les bulles — photo, illustration, motif. Vérifiez aussi qu'aucun ancêtre de la grille n'a de filter ni d'opacity inférieure à 1 : ils créent une nouvelle racine pour le flou, qui ne voit alors plus le fond de la page.