Animated Grid Overlay (Columns)

Documentation
Webflow
Code
Setup: External Scripts
External Scripts in Webflow
Make sure to always put the External Scripts before the JavasScript step of the resource. In this video you learn where to put these in your Webflow project:
HTML
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/gsap.min.js"></script>Step 1: Copy structure to Webflow
Copy structure to Webflow
In the video below we described how you can copy + paste the structure of this resource to your Webflow project:
Copy to Webflow
Webflow structure is not required for this resource.
Step 1: Add HTML
HTML
<div data-animated-grid class="animated-grid">
<div class="container is--full-height">
<div class="animated-grid__row">
<div data-animated-grid-col class="animated-grid__col"></div>
<div data-animated-grid-col class="animated-grid__col"></div>
<div data-animated-grid-col class="animated-grid__col"></div>
<div data-animated-grid-col class="animated-grid__col"></div>
<div data-animated-grid-col class="animated-grid__col"></div>
<div data-animated-grid-col class="animated-grid__col"></div>
<div data-animated-grid-col class="animated-grid__col"></div>
<div data-animated-grid-col class="animated-grid__col"></div>
<div data-animated-grid-col class="animated-grid__col"></div>
<div data-animated-grid-col class="animated-grid__col"></div>
<div data-animated-grid-col class="animated-grid__col"></div>
<div data-animated-grid-col class="animated-grid__col"></div>
</div>
</div>
</div>HTML structure is not required for this resource.
Step 2: Add CSS
CSS
.animated-grid {
position: fixed;
inset: 0;
z-index: 200;
pointer-events: none;
display: block;
}
.container {
width: 100%;
max-width: var(--size-container);
margin-inline: auto;
padding-inline: 1.5em;
}
.container.is--full-height {
height: 100%;
}
.animated-grid__row {
display: grid;
grid-template-columns: repeat(12, minmax(0, 1fr));
gap: 1.5em;
width: 100%;
height: 100%;
overflow: clip;
}
.animated-grid__col {
width: 100%;
height: 100%;
min-height: 100%;
opacity: 0.2;
background-color: #f4f4f4;
}
@media screen and (max-width: 991px) {
.animated-grid__row {
grid-template-columns: repeat(6, minmax(0, 1fr));
}
}
@media screen and (max-width: 767px) {
.animated-grid__row {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
}Step 2: Add custom Javascript
Custom Javascript in Webflow
In this video, Ilja gives you some guidance about using JavaScript in Webflow:
Step 2: Add Javascript
Step 3: Add Javascript
Javascript
function initAnimatedGrid() {
const grid = document.querySelector("[data-animated-grid]");
const cols = document.querySelectorAll("[data-animated-grid-col]");
const toggles = document.querySelectorAll("[data-animated-grid-toggle]");
if (!grid || !cols.length) return;
const storageKey = "animatedGridState";
let isOpen = localStorage.getItem(storageKey) === "open";
gsap.set(grid, { display: "block" });
if (isOpen) {
gsap.set(cols, { yPercent: 0 });
} else {
gsap.set(cols, { yPercent: 100 });
}
function openGrid() {
isOpen = true;
localStorage.setItem(storageKey, "open");
gsap.fromTo(cols, {
yPercent: 100,
}, {
yPercent: 0,
duration: 1,
ease: "expo.inOut",
stagger: { each: 0.03, from: "start" },
overwrite: true
});
}
function closeGrid() {
isOpen = false;
localStorage.setItem(storageKey, "closed");
gsap.fromTo(cols, {
yPercent: 0,
}, {
yPercent: -100,
duration: 1,
ease: "expo.inOut",
stagger: { each: 0.03, from: "start" },
overwrite: true
});
}
function toggleGrid() {
if (isOpen) closeGrid();
else openGrid();
}
function isTypingContext(e) {
const el = e.target;
if (!el) return false;
const tag = (el.tagName || "").toLowerCase();
return tag === "input" || tag === "textarea" || tag === "select" || el.isContentEditable;
}
toggles.forEach((btn) => {
btn.addEventListener("click", (e) => {
e.preventDefault();
toggleGrid();
});
});
window.addEventListener("keydown", (e) => {
if (isTypingContext(e)) return;
if (!(e.shiftKey && (e.key || "").toLowerCase() === "g")) return;
e.preventDefault();
toggleGrid();
});
}
// Initialize Animated Grid Overlay (Columns)
document.addEventListener("DOMContentLoaded", () => {
initAnimatedGrid();
});Step 3: Add custom CSS
Step 2: Add custom CSS
Custom CSS in Webflow
Curious about where to put custom CSS in Webflow? Ilja explains it in the below video:
CSS
Implementation
This script creates a visual overlay and is just meant to be a gimmick to check if the grid is correctly implemented from the design. It is not a functional CSS grid system.
Container
Place this element as a direct child of the <body>. Make sure to not add postion: relative; to the body.
Use [data-animated-grid] to mark the grid wrapper that gets revealed on load and acts as the animation scope. You can add display: none; to it to hide it. The JavaScript will put display: block; on it on load.
Column
Use [data-animated-grid-col] on each column element that slides in and out using yPercent transforms controlled by GSAP. In this example we have 12.
Toggle
Use [data-animated-grid-toggle] on any button or link that should toggle the grid open and closed on click.
Keyboard Shortcut
Use Shift + G to toggle the grid open and closed anywhere on the page, except when typing inside an input, textarea, select, or any contenteditable element.
Osmo Scaling System
In the demo we used the Osmo Scaling System, which works great to adapt layouts and let them scale smoothly across different breakpoints, and this grid overlay makes it easy to visually verify that everything stays aligned. Using it with the Osmo Scaling System is completely optional.
Resource details
Last updated
February 16, 2026
Category
Gimmicks
Need help?
Join Slack







