Cartes✨ Premium

Masonry to Grid

Six items basculent en douceur entre un layout masonry organique et une grille stricte grâce à la technique FLIP — zéro bibliothèque, CSS flexbox + un seul requestAnimationFrame.

CSSLayoutTransition

Vous aurez accès à la démo interactive avec un compte gratuit.

Cet effet fait partie d'Effect.Labs — 811 effets vanilla, une partie gratuite, une partie premium. Cartes comprend 41 effets, dont 6 gratuits. Découvrir la catégorie →

3 exemples d'usage

Galerie photos — Vue masonry organique vs grille comparatrice — Masonry to Grid exemple 1

① Galerie photos — Vue masonry organique vs grille comparatrice

QuandUne galerie d'images avec des ratios variés (portraits, paysages, carrés) que l'utilisateur veut parcourir librement en masonry ou aligner en grille pour comparer.
PourquoiLe FLIP anime chaque photo individuellement vers sa nouvelle place : l'utilisateur garde le fil entre les deux modes. La fluidité supprime la déstabilisation visuelle d'un rechargement ou d'un fade brutal.
RéglagesTransition 0.5s ease-out pour la rapidité, gap 8px, hauteurs masonry entre 80 et 150 px pour des proportions photo réalistes, 4 colonnes en grille (calc(25% - 8px)).
Catalogue produits — Mise en avant asymétrique vs grille normalisée — Masonry to Grid exemple 2

② Catalogue produits — Mise en avant asymétrique vs grille normalisée

QuandUn catalogue e-commerce ou SaaS où les items phares méritent plus d'espace en mode découverte, mais l'utilisateur veut une vue grille uniforme pour comparer prix et specs.
PourquoiLe masonry hiérarchise naturellement les items par leur taille. La bascule vers la grille donne une vue normalisée — les deux états répondent à des intentions de navigation distinctes sans rechargement.
RéglagesTransition 0.6s cubic-bezier(.4,0,.2,1), item vedette à width: 62% en masonry, 3 colonnes à calc(33.33% - 6px) en grille, hauteur uniforme 70px.
Liste d'articles — Mode découverte masonry vs lecture linéaire — Masonry to Grid exemple 3

③ Liste d'articles — Mode découverte masonry vs lecture linéaire

QuandUn blog ou un magazine proposant deux modes : masonry pour explorer visuellement les articles, 2 colonnes pour lire dans l'ordre.
PourquoiL'animation FLIP ancre l'utilisateur dans le même contenu — les articles ne disparaissent pas, ils se réorganisent. Ce signal de continuité est plus clair qu'un simple rerenderdu layout.
RéglagesTransition 0.7s ease-in-out pour un tempo éditorial, hauteurs masonry entre 65 et 100 px (proportionnelles à l'extrait), 2 colonnes en grille (calc(50% - 6px)), hauteur uniforme 80px.

Comment ça marche

Deux classes CSS — .masonry-mode et .grid-mode — définissent les deux états sur le même conteneur flexbox enveloppant. En mode masonry, chaque item reçoit des dimensions individuelles via :nth-child (largeurs 40–55 %, hauteurs 40–70 px). En mode grille, tous passent à calc(33.33% - 6px) et 50 px de hauteur. Le swap de classe suffit — le moteur de layout recalcule seul ; aucun positionnement absolu.

La fluidité vient de la technique FLIP (First, Last, Invert, Play). Avant le changement de classe, setMasonryGrid() capture la géométrie de chaque item avec getBoundingClientRect() (First). Après le swap (Last), elle calcule le delta de position et d'échelle, puis applique immédiatement transform: translate(dx, dy) scale(sx, sy) avec transition: none pour maintenir les items visuellement à leur ancienne place (Invert).

Dans le frame suivant (requestAnimationFrame), la transition all 0.6s cubic-bezier(.4, 0, .2, 1) est restituée et le transform forcé est effacé (Play). Le navigateur anime chaque item depuis sa position fictive jusqu'à sa vraie cible CSS. Les deux layouts partagent les mêmes nœuds DOM — aucune création, aucune destruction d'élément au toggle.

La fonction globale setMasonryGrid(btn, mode) gère aussi l'état visuel des boutons toggle (.morph-toggle.active). L'implémentation est intégralement vanilla : CSS pour les layouts, un unique requestAnimationFrame pour le départ d'animation — pas de Framer Motion, pas de GSAP, pas de Web Animations API.

Accessibilité

  • prefers-reduced-motion absent : la transition .6s s'applique même si l'utilisateur a activé la réduction de mouvement dans son OS. À corriger avant production : tester window.matchMedia('(prefers-reduced-motion: reduce)').matches et passer transition: none directement à la place de 0.6s cubic-bezier(…).
  • Les boutons de bascule sont des <button> natifs — focusables au clavier sans configuration supplémentaire. Ajouter type="button" pour éviter une soumission de formulaire parent accidentelle.
  • Aucun aria-label ni role sur le conteneur .masonry-grid-container. Si les items contiennent des images, ajouter alt descriptifs ; si purement décoratifs, ajouter aria-hidden="true" sur le conteneur.
  • Les boutons .morph-toggle.active passent en background: #6366f1; color: #fff — contraste blanc sur indigo-500 ≈ 4,5:1, seuil WCAG AA atteint.
  • Aucun état aria-pressed sur les boutons toggle : ajouter aria-pressed="true/false" depuis la fonction setMasonryGrid pour signaler l'état actif aux lecteurs d'écran.

Compatibilité navigateur

Requiert CSS flexbox et requestAnimationFrame — supportés dans tous les navigateurs modernes. Zéro dépendance externe.

Chrome 88+✓ Complet
Firefox 87+✓ Complet
Safari 14+✓ Complet
Edge 88+✓ Complet
Mobile iOS✓ Complet
Android Chrome✓ Complet

Sans JS, le conteneur reste en mode masonry initial (.masonry-mode) — layout statique valide, aucune erreur console. Les boutons toggle restent visibles mais inactifs.

Le code

Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :

index.html — structure
<div class="morph-toggle-group">
  <button class="morph-toggle active" type="button"
          onclick="setMasonryGrid(this, 'masonry')">Masonry</button>
  <button class="morph-toggle" type="button"
          onclick="setMasonryGrid(this, 'grid')">Grille</button>
</div>

<div class="masonry-grid-container masonry-mode" id="masonryDemo">
  <!-- Un .masonry-item par élément — background ou contenu en inline style -->
  <div class="masonry-item" style="background: linear-gradient(135deg, #6366f1, #818cf8);"></div>
  <div class="masonry-item" style="background: linear-gradient(135deg, #8b5cf6, #a78bfa);"></div>
  <div class="masonry-item" style="background: linear-gradient(135deg, #d946ef, #e879f9);"></div>
  <div class="masonry-item" style="background: linear-gradient(135deg, #ec4899, #f472b6);"></div>
  <div class="masonry-item" style="background: linear-gradient(135deg, #f43f5e, #fb7185);"></div>
  <div class="masonry-item" style="background: linear-gradient(135deg, #f59e0b, #fbbf24);"></div>
</div>
🔒 Débloquer le code complet — à partir de 2,99 € le 1er mois

HTML + CSS + JS complet, prêt à coller — avec des centaines d'effets premium.

Personnaliser

Options passées à l'API ou attributs data-* :

Option / propriétéDéfautEffet
transition sur .masonry-item .6s cubic-bezier(.4,0,.2,1) Durée et easing de l'animation. Remplacez par .4s ease-out pour un rendu vif, ou .9s ease-in-out pour un tempo éditorial lent.
gap sur .masonry-grid-container 6px Espacement entre items dans les deux modes. 12px pour une galerie aérée, 2px pour un assemblage mosaïque serré.
width / height dans .masonry-mode:nth-child(n) 45–55 % / 40–70 px Dimensions de chaque item en masonry. Modifiez par :nth-child pour créer votre rythme organique — grand item en tête, secondaires plus petits.
width dans .grid-mode .masonry-item calc(33.33% - 6px) Largeur uniforme en mode grille. Changez 33.33% en 25% pour 4 colonnes, 50% pour 2 colonnes.
height dans .grid-mode .masonry-item 50px Hauteur uniforme en grille. Augmentez pour des cartes plus hautes ou passez à auto si les items ont du contenu texte à hauteur variable.
border-radius sur .masonry-item 6px Arrondi des coins. 12px pour un rendu carte, 0 pour une mosaïque stricte sans bords.

FAQ

Oui. Ajoutez ou supprimez des .masonry-item dans le HTML, puis ajustez les règles :nth-child dans le CSS pour définir la largeur et la hauteur de chaque item en mode masonry. En mode grille, le calc(33.33% - 6px) s'applique automatiquement à tous les items présents — aucune modification JS n'est nécessaire.
La fonction globale setMasonryGrid(btn, mode) attend un élément bouton pour mettre à jour l'état .active. Si vous n'avez pas de bouton visible, passez null et protégez la ligne e.parentElement.querySelectorAll(…) avec un if (e). Appelez ensuite setMasonryGrid(null, 'grid') sur n'importe quel événement : scroll, timer, fin de chargement.
Oui, c'est 100 % vanilla. Dans React, appelez setMasonryGrid depuis un useEffect ou un handler onClick après que le composant est monté dans le DOM. Dans Vue, utilisez mounted() ou un @click handler. La fonction ne touche qu'au DOM — pas de state framework, pas de conflit.