# Layout Grid Flip

> Grid cells that flip and reflow between layouts — satisfying for filters, views, and adaptive catalogs.

**Definition:** Layout Grid Flip is a cards UI animation from collections.html. It is built with HTML, CSS, JavaScript, and GSAP, ships with a live preview, and is free to copy into personal and commercial projects.

## Facts
- Category: Cards
- Stack: HTML, CSS, JavaScript, and GSAP
- Added: 2026-08-01
- Canonical page: https://html.bosconvertpro.com/collection/layout-grid-flip
- Full-page preview: https://html.bosconvertpro.com/collection/layout-grid-flip/full
- Live demo: https://html.bosconvertpro.com/demos/layout-grid-flip/index.html
- Markdown mirror: https://html.bosconvertpro.com/collection/layout-grid-flip/index.md
- License: https://html.bosconvertpro.com/terms

## How to use
1. Open https://html.bosconvertpro.com/collection/layout-grid-flip/full to preview the animation in full screen.
2. Copy index.html, styles.css, and script.js from the code tabs on https://html.bosconvertpro.com/collection/layout-grid-flip.
3. Paste the files into your project and adjust timing, easing, and content as needed.

## FAQ
### What is Layout Grid Flip?

Layout Grid Flip is a cards UI animation from collections.html. Grid cells that flip and reflow between layouts — satisfying for filters, views, and adaptive catalogs.

### What is Layout Grid Flip built with?

Layout Grid Flip is built with HTML, CSS, JavaScript, and GSAP. The source for every file is shown on the animation page and can be copied straight into your project.

### How do I use Layout Grid Flip in my project?

Open the animation page (https://html.bosconvertpro.com/collection/layout-grid-flip), preview it live, then copy index.html, styles.css, and script.js from the code tabs. Paste the files into your project and adjust timing, easing, and content as needed. A standalone demo runs at https://html.bosconvertpro.com/demos/layout-grid-flip/index.html.

### Is Layout Grid Flip free to use?

Yes. The Layout Grid Flip demo code may be used in personal and commercial projects. You may not resell or redistribute the collection itself as a competing template pack. Full terms: https://html.bosconvertpro.com/terms.

## Source — index.html
````html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Layout Grid Flip</title>
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link rel="preconnect" href="https://images.unsplash.com" />
    <link rel="preconnect" href="https://freenaturestock.com" />
    <link
      href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"
      rel="stylesheet"
    />
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <!--
      Layout Grid Flip
      Nature gallery — toggle Large ↔ Small with GSAP Flip.
    -->
    <main class="page">
      <div data-layout-status="large" data-layout-group class="layout-group">
        <div class="layout-buttons">
          <button
            type="button"
            data-layout-button="large"
            class="layout-btn is--active"
            aria-pressed="true"
          >
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="100%"
              viewBox="0 0 12 12"
              fill="none"
              class="layout-btn__icon"
              aria-hidden="true"
            >
              <rect x="1" y="1" width="3.33333" height="3.33333" fill="currentColor" />
              <rect x="1" y="7.60791" width="3.33333" height="3.33333" fill="currentColor" />
              <rect x="7.66797" y="1" width="3.33333" height="3.33333" fill="currentColor" />
              <rect x="7.66797" y="7.60791" width="3.33333" height="3.33333" fill="currentColor" />
            </svg>
            <span class="layout-btn__label">Large</span>
          </button>

          <button
            type="button"
            data-layout-button="small"
            class="layout-btn"
            aria-pressed="false"
          >
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="100%"
              viewBox="0 0 12 12"
              fill="none"
              class="layout-btn__icon"
              aria-hidden="true"
            >
              <rect x="1" y="1" width="2.5" height="2.5" fill="currentColor" />
              <rect x="4.75" y="1" width="2.5" height="2.5" fill="currentColor" />
              <rect x="8.5" y="1" width="2.5" height="2.5" fill="currentColor" />
              <rect x="1" y="4.75" width="2.5" height="2.5" fill="currentColor" />
              <rect x="4.75" y="4.75" width="2.5" height="2.5" fill="currentColor" />
              <rect x="8.5" y="4.75" width="2.5" height="2.5" fill="currentColor" />
              <rect x="1" y="8.5" width="2.5" height="2.5" fill="currentColor" />
              <rect x="4.75" y="8.5" width="2.5" height="2.5" fill="currentColor" />
              <rect x="8.5" y="8.5" width="2.5" height="2.5" fill="currentColor" />
            </svg>
            <span class="layout-btn__label">Small</span>
          </button>
        </div>

        <div data-layout-grid class="layout-grid">
          <div data-layout-grid-collection class="layout-grid__collection">
            <div data-layout-grid-list class="layout-grid__list">
              <div data-layout-grid-item class="layout-grid__item">
                <div class="layout-grid__card">
                  <div class="layout-grid__card-visual">
                    <img
                      src="https://images.unsplash.com/photo-1506905925346-21bda4d32df4?auto=format&fit=crop&w=900&q=82"
                      alt="Alpine Peaks"
                      class="layout-grid__card-img"
                      loading="eager"
                      draggable="false"
                    />
                  </div>
                  <div class="layout-grid__card-details">
                    <h2 data-layout-grid-item-title class="layout-grid__card-title">
                      Alpine Peaks
                    </h2>
                  </div>
                </div>
              </div>

              <div data-layout-grid-item class="layout-grid__item">
                <div class="layout-grid__card">
                  <div class="layout-grid__card-visual">
                    <img
                      src="https://images.unsplash.com/photo-1441974231531-c6227db76b6e?auto=format&fit=crop&w=900&q=82"
                      alt="Forest Path"
                      class="layout-grid__card-img"
                      loading="eager"
                      draggable="false"
                    />
                  </div>
                  <div class="layout-grid__card-details">
                    <h2 data-layout-grid-item-title class="layout-grid__card-title">
                      Forest Path
                    </h2>
                  </div>
                </div>
              </div>

              <div data-layout-grid-item class="layout-grid__item">
                <div class="layout-grid__card">
                  <div class="layout-grid__card-visual">
                    <img
                      src="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?auto=format&fit=crop&w=900&q=82"
                      alt="Morning Mist"
                      class="layout-grid__card-img"
                      loading="eager"
                      draggable="false"
                    />
                  </div>
                  <div class="layout-grid__card-details">
                    <h2 data-layout-grid-item-title class="layout-grid__card-title">
                      Morning Mist
                    </h2>
                  </div>
                </div>
              </div>

              <div data-layout-grid-item class="layout-grid__item">
                <div class="layout-grid__card">
                  <div class="layout-grid__card-visual">
                    <img
                      src="https://images.unsplash.com/photo-1469474968028-56623f02e42e?auto=format&fit=crop&w=900&q=82"
                      alt="Golden Ridge"
                      class="layout-grid__card-img"
                      loading="lazy"
                      draggable="false"
                    />
                  </div>
                  <div class="layout-grid__card-details">
                    <h2 data-layout-grid-item-title class="layout-grid__card-title">
                      Golden Ridge
                    </h2>
                  </div>
                </div>
              </div>

              <div data-layout-grid-item class="layout-grid__item">
                <div class="layout-grid__card">
                  <div class="layout-grid__card-visual">
                    <img
                      src="https://images.unsplash.com/photo-1472214103451-9374bd1c798e?auto=format&fit=crop&w=900&q=82"
                      alt="Emerald Fields"
                      class="layout-grid__card-img"
                      loading="lazy"
                      draggable="false"
                    />
                  </div>
                  <div class="layout-grid__card-details">
                    <h2 data-layout-grid-item-title class="layout-grid__card-title">
                      Emerald Fields
                    </h2>
                  </div>
                </div>
              </div>

              <div data-layout-grid-item class="layout-grid__item">
                <div class="layout-grid__card">
                  <div class="layout-grid__card-visual">
                    <img
                      src="https://images.unsplash.com/photo-1501785888041-af3ef285b470?auto=format&fit=crop&w=900&q=82"
                      alt="Still Lake"
                      class="layout-grid__card-img"
                      loading="lazy"
                      draggable="false"
                    />
                  </div>
                  <div class="layout-grid__card-details">
                    <h2 data-layout-grid-item-title class="layout-grid__card-title">
                      Still Lake
                    </h2>
                  </div>
                </div>
              </div>

              <div data-layout-grid-item class="layout-grid__item">
                <div class="layout-grid__card">
                  <div class="layout-grid__card-visual">
                    <img
                      src="https://images.unsplash.com/photo-1433086966358-54859d0ed716?auto=format&fit=crop&w=900&q=82"
                      alt="Cascade Falls"
                      class="layout-grid__card-img"
                      loading="lazy"
                      draggable="false"
                    />
                  </div>
                  <div class="layout-grid__card-details">
                    <h2 data-layout-grid-item-title class="layout-grid__card-title">
                      Cascade Falls
                    </h2>
                  </div>
                </div>
              </div>

              <div data-layout-grid-item class="layout-grid__item">
                <div class="layout-grid__card">
                  <div class="layout-grid__card-visual">
                    <img
                      src="https://images.unsplash.com/photo-1475924156734-496f6cac6ec1?auto=format&fit=crop&w=900&q=82"
                      alt="Coastal Rocks"
                      class="layout-grid__card-img"
                      loading="lazy"
                      draggable="false"
                    />
                  </div>
                  <div class="layout-grid__card-details">
                    <h2 data-layout-grid-item-title class="layout-grid__card-title">
                      Coastal Rocks
                    </h2>
                  </div>
                </div>
              </div>

              <div data-layout-grid-item class="layout-grid__item">
                <div class="layout-grid__card">
                  <div class="layout-grid__card-visual">
                    <img
                      src="https://images.unsplash.com/photo-1518173946687-a4c8892bbd9f?auto=format&fit=crop&w=900&q=82"
                      alt="Pine Grove"
                      class="layout-grid__card-img"
                      loading="lazy"
                      draggable="false"
                    />
                  </div>
                  <div class="layout-grid__card-details">
                    <h2 data-layout-grid-item-title class="layout-grid__card-title">
                      Pine Grove
                    </h2>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </main>

    <script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/Flip.min.js"></script>
    <script src="script.js"></script>
  </body>
</html>
````

## Source — styles.css
````css
/* --------------------------------------------------------------------------
   Layout Grid Flip
   Premium nature gallery — GSAP Flip Large (3-col) ↔ Small (5-col)
   -------------------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
    sans-serif;
  color: #f3efe8;
  background-color: #0c0b0a;
  background-image:
    radial-gradient(ellipse 90% 55% at 50% -10%, rgba(90, 78, 62, 0.28), transparent 55%),
    radial-gradient(ellipse 50% 40% at 100% 100%, rgba(45, 52, 48, 0.2), transparent 50%);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  min-height: 100svh;
}

button {
  font: inherit;
  color: inherit;
  border: 0;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

img {
  display: block;
  max-width: 100%;
  user-select: none;
  -webkit-user-drag: none;
}

/* --------------------------------------------------------------------------
   Page shell
   -------------------------------------------------------------------------- */

.page {
  width: 100%;
  min-height: 100svh;
  font-size: clamp(10px, 1.05vw, 16px);
}

.layout-group {
  width: 100%;
  max-width: 90em;
  margin: 0 auto;
}

/* --------------------------------------------------------------------------
   Layout toggle buttons
   -------------------------------------------------------------------------- */

.layout-buttons {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  gap: 0.5em;
  padding: 1.25em 1em 2.5em;
}

.layout-btn {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  gap: 0.5em;
  padding: 0.75em 1.25em;
  border-radius: 100em;
  background-color: rgba(255, 255, 255, 0.06);
  color: rgba(243, 239, 232, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.08);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  transition:
    color 0.25s ease,
    background-color 0.25s ease,
    border-color 0.25s ease,
    transform 0.2s ease,
    box-shadow 0.25s ease;
}

.layout-btn:hover {
  transform: translateY(-1px);
  color: #f3efe8;
  background-color: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.14);
}

.layout-btn:active {
  transform: translateY(0);
}

.layout-btn.is--active {
  color: #0c0b0a;
  background-color: #e8e0d4;
  border-color: #e8e0d4;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
}

.layout-btn:focus-visible {
  outline: 2px solid #e8e0d4;
  outline-offset: 3px;
}

.layout-btn__label {
  font-size: 1.5em;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.01em;
  font-variation-settings: "wght" 500;
}

.layout-btn__icon {
  width: 0.75em;
  height: 0.75em;
  flex-shrink: 0;
}

/* --------------------------------------------------------------------------
   Nature grid
   -------------------------------------------------------------------------- */

.layout-grid {
  padding: 0 1em 8em;
}

.layout-grid__collection {
  position: relative;
  width: 100%;
}

.layout-grid__list {
  display: flex;
  flex-wrap: wrap;
  position: relative;
  row-gap: 3.5em;
  column-gap: var(--column-gap);
}

.layout-grid__item {
  position: relative;
  will-change: transform;
}

.layout-grid__card {
  display: flex;
  flex-direction: column;
  position: relative;
  width: 100%;
}

.layout-grid__card-visual {
  aspect-ratio: 1 / 1.25;
  border-radius: 0.4em;
  overflow: hidden;
  background-color: #1a1816;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.04) inset,
    0 18px 40px rgba(0, 0, 0, 0.35);
}

.layout-grid__card-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.7s cubic-bezier(0.65, 0, 0.1, 1);
}

.layout-grid__card:hover .layout-grid__card-img {
  transform: scale(1.04);
}

.layout-grid__card-details {
  height: 2.5em;
  margin-top: 0.85em;
}

.layout-grid__card-title {
  margin: 0;
  font-size: 1.5em;
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: #f3efe8;
  font-variation-settings: "wght" 500;
}

/* --------------------------------------------------------------------------
   Layout modes (column count + gaps)
   -------------------------------------------------------------------------- */

[data-layout-status="large"] {
  --columns: 3;
  --column-gap: 1.5em;
}

[data-layout-status="small"] {
  --columns: 5;
  --column-gap: 1em;
}

[data-layout-grid-item] {
  width: calc(
    (100% - (var(--columns) - 1) * var(--column-gap)) / var(--columns)
  );
}

[data-layout-grid-item-title] {
  transition: all 0.8s cubic-bezier(0.65, 0, 0.1, 1);
}

/* Small: tighter title */
[data-layout-status="small"] [data-layout-grid-item] .layout-grid__card-title {
  font-size: 1em;
  opacity: 0.88;
}

/* During Flip absolute phase */
[data-transitioning="true"] .layout-grid__item {
  z-index: 1;
}

[data-transitioning="true"] .layout-grid__card:hover .layout-grid__card-img {
  transform: none;
}

/* --------------------------------------------------------------------------
   Responsive breakpoints
   -------------------------------------------------------------------------- */

@media screen and (max-width: 767px) {
  .page {
    font-size: clamp(12px, 3.4vw, 16px);
  }

  .layout-buttons {
    padding: 1em 1em 2em;
  }

  [data-layout-status="large"] {
    --columns: 1;
    --column-gap: 0em;
  }

  [data-layout-status="small"] {
    --columns: 2;
    --column-gap: 1em;
  }

  .layout-grid__list {
    row-gap: 2.5em;
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-layout-grid-item-title],
  .layout-btn,
  .layout-grid__card-img {
    transition: none !important;
  }

  .layout-grid__card:hover .layout-grid__card-img {
    transform: none;
  }
}
````

## Source — script.js
````javascript
/**
 * Layout Grid Flip
 * Smooth Large ↔ Small grid reflow with GSAP Flip + height morph.
 */
gsap.registerPlugin(Flip);

function initGridLayoutFlip() {
  const groups = document.querySelectorAll("[data-layout-group]");
  const ACTIVE_CLASS = "is--active";

  groups.forEach((group) => {
    let activeTween = null;

    const buttons = group.querySelectorAll("[data-layout-button]");
    const grid = group.querySelector("[data-layout-grid]");
    const collection = group.querySelector("[data-layout-grid-collection]");

    if (!buttons.length || !grid || !collection) {
      console.warn(
        "Layout Grid Flip: missing required elements. Check data attributes."
      );
      return;
    }

    // a11y initial state
    buttons.forEach((b) => {
      b.setAttribute(
        "aria-pressed",
        String(b.classList.contains(ACTIVE_CLASS))
      );
    });

    buttons.forEach((btn) => {
      btn.addEventListener("click", () => {
        const targetLayout = btn.getAttribute("data-layout-button"); // large | small
        const currentLayout = group.getAttribute("data-layout-status");

        if (currentLayout === targetLayout) return;

        // Kill any in-flight animation so rapid clicks stay smooth
        if (activeTween) {
          activeTween.kill();
          activeTween = null;
          group.removeAttribute("data-transitioning");
          gsap.set(collection, { clearProps: "height" });
        }

        // Reduced motion: instant switch
        if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
          group.setAttribute("data-layout-status", targetLayout);
          buttons.forEach((b) => {
            const isActive = b === btn;
            b.classList.toggle(ACTIVE_CLASS, isActive);
            b.setAttribute("aria-pressed", String(isActive));
          });
          window.ScrollTrigger?.refresh?.();
          if (window.lenis?.resize) window.lenis.resize();
          return;
        }

        // 1) Snapshot current item positions
        const items = grid.querySelectorAll("[data-layout-grid-item]");
        const state = Flip.getState(items, { simple: true });

        // 2) Measure current collection height
        collection.getBoundingClientRect();
        const prevH = collection.offsetHeight;

        // 3) Apply target layout (CSS columns / gaps change)
        group.setAttribute("data-layout-status", targetLayout);
        buttons.forEach((b) => {
          const isActive = b === btn;
          b.classList.toggle(ACTIVE_CLASS, isActive);
          b.setAttribute("aria-pressed", String(isActive));
        });

        // 4) Measure next height after reflow
        collection.getBoundingClientRect();
        const nextH = collection.offsetHeight;

        // Pin height so absolute Flip items don't collapse the flow
        gsap.set(collection, { height: prevH });

        // 5) Flip items + morph container height in parallel
        const tl = gsap.timeline({
          onStart: () => {
            group.setAttribute("data-transitioning", "true");
          },
          onInterrupt: () => {
            group.removeAttribute("data-transitioning");
            gsap.set(collection, { clearProps: "height" });
          },
          onComplete: () => {
            group.removeAttribute("data-transitioning");
            gsap.set(collection, { clearProps: "height" });
            window.ScrollTrigger?.refresh?.();
            if (window.lenis?.resize) window.lenis.resize();
            activeTween = null;
          },
        });

        tl.add(
          Flip.from(state, {
            duration: 0.65,
            ease: "power4.inOut",
            absolute: true,
            nested: true,
            prune: true,
            // Stagger direction follows layout density change
            stagger:
              targetLayout === "large"
                ? { each: 0.03, from: "end" }
                : { each: 0.03, from: "start" },
          }),
          0
        ).to(
          collection,
          {
            height: nextH,
            duration: 0.65,
            ease: "power4.inOut",
          },
          0
        );

        activeTween = tl;
      });
    });
  });
}

document.addEventListener("DOMContentLoaded", () => {
  initGridLayoutFlip();
});
````
