GSAP + Glaze + BricksBuilder
You’ll first build a solid mental model of how animations work, then learn GSAP properly , and finally learn how to use Glaze efficiently for everyday work—without losing the ability to create advanced custom animations later.
Glaze for WP (and for BricksBuilder)
Update 1.2.0: Preview of the Presets directly in the WP backend now possible.
Update 1.3.0: Preview improved (more reliable + scroll preview)
What It Is
Glaze for WP / Bricks brings Tailwind-style, attribute-driven animations to any WordPress site (with special affinity for Bricks Builder) using GSAP under the hood. Instead of writing JavaScript for every animated element, you simply add a data-animate attribute (or a CSS class, if you prefer class-based syntax) containing a compact animation string, and the plugin's runtime script parses it and drives GSAP automatically.
The Technology Behind It
GSAP (GreenSock Animation Platform) is the actual animation engine — it handles all the tweening, easing, timelines, and (optionally) scroll-triggered behavior via its ScrollTrigger plugin. GSAP itself knows nothing about your markup; it's just invoked with the right parameters.
GlazeJS is a small ES module that sits between your HTML and GSAP. It scans the DOM for elements carrying the configured attribute (default data-animate) or class prefix (default glaze-), parses the pipe-separated animation string on each one (e.g. from:opacity-0|y-30|duration-0.6), and translates that into the equivalent GSAP .from()/.to()/timeline calls — including support for staggered children ([&>*]:...), nested selectors ([&_path]:...), transform origins, easing functions, and scroll-trigger properties.
This plugin is the WordPress "glue" layer: it loads GSAP and Glaze (from CDN or a locally hosted copy), lets you configure breakpoints, global defaults, reusable presets, and automatic class-to-animation mappings through an admin UI, and injects the resulting configuration into the front end via a small runtime script (runtime.js). Everything is stored in flat JSON/files (/config/settings.json, /lib/*.js) rather than the options table, and is fully removed on uninstall.
Getting Started
- After activation, go to the Glaze menu item in the WordPress admin sidebar (superhero icon).
- The admin screen has five tabs: Libraries, General, Breakpoints & Defaults, Presets, and Mappings.
- Make your changes and click Save changes in the header. Reset restores all settings to plugin defaults (with a confirmation prompt).
Tab-by-Tab Guide
Libraries
Controls how GSAP, ScrollTrigger, and GlazeJS are loaded on the front end.
- Library mode:
CDN(jsDelivr/esm.sh — fastest to set up, but relies on external requests) orLocal(serves self-hosted copies from the plugin's/libfolder — no third-party requests, but you must download each library first). - Use existing global GSAP: Enable if another plugin or your theme already loads GSAP globally, so Glaze reuses
window.gsapinstead of loading a duplicate copy. - Local libraries section: For each library (GSAP core, ScrollTrigger, GlazeJS), you can Download (fetch a fresh local copy), Refresh (re-download an existing one, e.g. after an update), or Remove (delete the local copy, falling back to CDN until re-downloaded).
General
- Data attribute: The HTML attribute Glaze scans for animation strings (default
data-animate). Only change this if it conflicts with another plugin/theme. - Class prefix: Prefix for the optional class-based syntax (default
glaze), e.g.class="glaze-from:opacity-0". - Enable ScrollTrigger: Registers GSAP's ScrollTrigger plugin so animations can react to scroll position (
scrollTrigger.*properties). - Force GPU (force3D): Forces animated elements onto GPU-accelerated layers for smoother motion (may occasionally blur very small text).
- Watch DOM & re-animate: Watches for elements added after page load (AJAX content, Bricks-injected components) and automatically animates them.
- Watch debounce (ms): Delay before re-scanning after a DOM change is detected (only relevant when Watch DOM is on).
- Run inside Bricks builder: Plays animations live while editing in the Bricks canvas (off by default, since constant replay can be distracting while building).
- Verbose console logging: Logs parsed animation strings and GSAP calls to the console — useful for debugging, should stay off in production.
Breakpoints & Defaults
- Breakpoints: Named media queries used for responsive prefixes like
@tablet:from:opacity-0. The name is what you reference in animation strings; the value is the actual CSS media query.defaultapplies when no@breakpoint:prefix is used. - Global defaults: Baseline settings applied automatically everywhere.
- Element defaults: Fallback properties for every animated element (e.g.
duration-0.6|ease-power2.out) — overridden by anything set directly in an element's own attribute. - Timeline defaults: Applied to every internal timeline Glaze creates (every element is wrapped in one), useful for a global easing or default
scrollTrigger.trigger.
- Element defaults: Fallback properties for every animated element (e.g.
Presets
Reusable animation strings referenced by name inside data-animate (e.g. fadeIn) or as a class (glaze-preset-fadeIn). Categories only organize the admin UI — they have no front-end effect, and preset names must be unique across all categories since they're flattened into one list at runtime.
- + Add category / + Preset: create new groups/rows.
- Preview button on each preset row: opens a modal that plays the animation live on a sample layout (single box, staggered row, grid, or SVG shape) using the same GSAP/Glaze pipeline as the front end — handy for tuning a string without leaving wp-admin.
- Advanced users can bypass the UI and hand-edit
/config/settings.jsondirectly to add many more presets at once; aglaze-opus-docs-2.0.mdfile in the plugin directory documents the full animation-string syntax for AI-assisted ("Vibe Coding") editing.
Mappings
Automatically attaches an animation to every element matching a CSS class or selector, without needing to add data-animate manually — useful for markup you don't control directly (e.g. icon wrappers Bricks generates).
- Left field: CSS class or selector to match (e.g.
.fv-a-iconorfv-a-icon). - Right field: raw animation string or
preset-nameto apply.
Writing Animation Strings
Animation strings are pipe-separated (|) key-value pairs, e.g.:
from:opacity-0|y-30|duration-0.6|ease-power2.out
Common patterns:
from:/to:define the animated state (properties before the tween vs. the target values).- Numeric values follow the property name with a hyphen:
y-30,scale-0.8,rotate-[-45](brackets allow negative/complex values). duration-,delay-,ease-,stagger-,repeat-,yoyo-control timing/behavior.[&>*]:prefix applies the animation with staggering to direct children (useful for lists/grids).[&_path]:/[&_line]:prefix targets nested SVG elements.scrollTrigger.trigger-[&],scrollTrigger.start-[top_85%],scrollTrigger.scrub-1, etc. wire the animation to scroll position (requires Enable ScrollTrigger).@breakpoint:prefix (e.g.@tablet:from:opacity-0) restricts a rule to a given breakpoint's media query.
Practical Notes
- Changing the library mode to Local without first downloading a library will simply cause the plugin to fall back to CDN for that library until you download it.
- Watch DOM uses a Firefox-safe, childList-only
MutationObserver— it intentionally never listens for attribute changes, avoiding an infinite re-trigger loop that can occur when GSAP rewrites inline styles. - If Run inside Bricks builder is left off, animations simply won't fire while editing in the canvas; they still work normally on the live front end.
- All plugin data lives in flat files (
/config/settings.json,/lib/*.js) — nothing is stored in the WordPress options table, and everything is deleted automatically on uninstall.
Glaze Cheat Sheet
Tailwind-style animations for HTML. Describe GSAP animations with data attributes—no JS animation code.
1. Core Concept
Glaze is a ~3kb syntax layer on top of GSAP. You write animation strings in HTML attributes; Glaze parses them into GSAP calls.
<div data-animate="from:opacity-0|y-50|duration-1"></div>
<!-- becomes -->
gsap.from(element, { opacity: 0, y: 50, duration: 1 })
Requirements: GSAP must be installed and passed to Glaze. (GSAP has its own license—check compliance for commercial use. Glaze itself is MIT.)
Features: responsive breakpoints (via GSAP matchMedia), timelines, dot notation for nested props, full GSAP access (ScrollTrigger, easing, stagger), library-agnostic design.
2. Install & Setup
npm i glazejs # or yarn add / pnpm add / bun add glazejs
import gsap from "gsap";
import glaze from "glazejs";
glaze({
lib: { gsap: { core: gsap } }, // ONLY required option
});
CDN:
import glaze from "https://esm.sh/glazejs";
import gsap from "https://esm.sh/gsap";
glaze({ lib: { gsap: { core: gsap } } });
Glaze auto-finds all data-animate elements and animates them.
3. Full Configuration
glaze({
lib: { gsap: { core: gsap } }, // required
element: document.querySelector("#app"), // search scope (default: document)
dataAttribute: "data-move", // custom attr (default: "data-animate")
className: "animate", // enable class-based syntax instead
breakpoints: { // responsive (GSAP matchMedia)
default: "(min-width: 1px)", // runs when no bp specified
sm: "(min-width: 640px)",
md: "(min-width: 768px)",
lg: "(min-width: 1024px)",
},
defaults: { // global default settings
tl: "ease-power2.inOut", // applies to every timeline
element: "duration-1", // applies to every element
},
presets: { // reusable animation shortcuts
fadeIn: "from:opacity-0|duration-1",
slideUp: "from:y-50|opacity-0",
},
watch: { debounceTime: 500 }, // watch DOM & re-animate (default: false)
});
4. Anatomy of an Animation String
[breakpoint][selector]:state:properties
Example: @lg:[&>div]:from:opacity-0|y-50|stagger-0.1|duration-0.5|ease-power2.out
5. States (every animation needs one)
| Syntax | GSAP equivalent | Meaning |
|---|---|---|
from:... |
gsap.from |
Start at these values → animate to natural state |
to:... |
gsap.to |
Animate from current state → these values |
from:... to:... |
gsap.fromTo |
Animate between two explicit states |
<div data-animate="from:opacity-0"></div>
<div data-animate="to:xPercent-50"></div>
<div data-animate="from:opacity-0.5 to:opacity-1"></div>
6. Properties
- List after state, separated by pipes
|. - Parsed by splitting at the dash
-: first part = property name, second = value. - Values auto-convert to number, boolean, or string.
<div data-animate="to:opacity-1|yPercent-10|duration-0.5"></div>
| Need | Syntax | Result |
|---|---|---|
| Nested props (dots) | to:scale.x-2|scale.y-2 |
{ scale: { x: 2, y: 2 } } |
| Negative values (brackets) | to:xPercent-[-50] |
{ xPercent: -50 } |
| Values with spaces (underscores) | to:boxShadow-[0_0_50px_20px_red] |
0 0 50px 20px red |
7. Breakpoints
Prefix with @breakpoint: — animation only runs at that screen size.
<div data-animate="@sm:from:opacity-0"></div> <!-- sm only -->
<div data-animate="@lg:from:opacity-0|rotate-180"></div>
Stack multiple with spaces; larger breakpoints add to/override smaller:
<div data-animate="@sm:from:opacity-0|y-50 @lg:from:scale-0.5"></div>
default breakpoint runs when none specified (defaults to (min-width: 1px)).
8. Selectors (target children)
Bracket notation [selector]:. The & = the parent element.
<div data-animate="[&>h1]:to:opacity-1|stagger-0.25">
<h1>One</h1><h1>Two</h1><h1>Three</h1>
</div>
Combine with breakpoints: @sm:[&>h1]:to:opacity-1|stagger-0.25
9. Alternative Input Modes
Custom attribute: set dataAttribute: "data-move" → use <div data-move="from:opacity-0">.
Class-based: set className: "animate" → write:
<div class="animate-from:opacity-0|duration-1"></div>
10. Timelines (tl)
Add tl keyword to make an element a timeline container. All child elements are automatically included in its scope.
<div data-animate="tl defaults:ease-elastic|duration-1">
<div data-animate="to:rotate-360"></div>
<div data-animate="to:rotate-360"></div>
</div>
Timeline defaults: tl defaults:ease-elastic|duration-4 yoyo-true
Timing control with tl:[...] on children:
| Value | Meaning |
|---|---|
tl:[+=1] |
Start 1s after previous ends |
tl:[-=1] |
Start 1s before previous ends (overlap) |
tl:[<] |
Start at same time as previous |
Responsive timelines: mix breakpoints inside children:
<div data-animate="tl defaults:power2.inOut|duration-2">
<div data-animate="to:rotate-360 @lg:to:xPercent-[50]"></div>
<div data-animate="tl:[-=1] to:rotate-360 @lg:to:xPercent-[-50]"></div>
</div>
Named timelines — reference from anywhere in the DOM:
<div data-animate="tl/main defaults:power2.inOut|duration-2">
<div data-animate="to:rotate-360"></div>
</div>
<div data-animate="tl:main-[-=1] to:scale-1.5"></div>
tl/name = create named timeline · tl:name = join it.
Internally, Glaze creates a timeline for every element even without
tl, sotldefaults apply globally.
11. ScrollTrigger
No special syntax—it's just the GSAP scrollTrigger property via dot notation.
Setup:
import ScrollTrigger from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
<div data-animate="from:opacity-0|y-50|scrollTrigger.trigger-[&]"></div>
| Option | What it does |
|---|---|
scrollTrigger.trigger-[&] |
Element that triggers animation ([&] = this element) |
scrollTrigger.start-[top_center] |
When to start (element pos + viewport pos) |
scrollTrigger.end-[bottom_top] |
When to end |
scrollTrigger.scrub=true |
Link progress to scroll position |
scrollTrigger.markers=true |
Show debug markers |
Use underscores for spaces:
[top_center]not[top center].
12. Defaults (behavior)
defaults: {
tl: "defaults:ease-power2.inOut scrollTrigger.trigger-[&]", // every timeline
element: "duration-1", // every element
}
Because every element gets an internal timeline, tl defaults effectively apply everywhere (great for global ScrollTrigger/easing).
Override per element:
<div data-animate="from:opacity-0"></div> <!-- default 1s -->
<div data-animate="from:opacity-0|duration-0.5"></div> <!-- overrides -->
13. Presets
Define reusable strings in config; reference with preset-.
presets: {
fadeIn: "from:opacity-0|duration-1",
slideUp: "from:y-50|opacity-0|duration-0.5",
helicopter: "from:rotate-2160|duration-5",
}
<div data-animate="preset-fadeIn"></div>
<div class="animate-preset-helicopter"></div> <!-- class mode -->
<div data-animate="preset-fadeIn scrollTrigger.trigger-[&]"></div> <!-- combine -->
Presets simply expand into the full string before processing.
14. Quick Syntax Reference
| Token | Purpose |
|---|---|
from: to: |
states (fromTo = use both) |
| |
separates properties |
- |
splits property name / value |
. |
nested property (scale.x-2) |
[-50] |
negative / literal value |
[0_0_50px_red] |
value with spaces (underscores) |
@bp: |
breakpoint prefix |
[&>sel]: |
child selector (& = parent) |
tl |
timeline container |
tl/name |
named timeline |
tl:name / tl:[+=1] |
join timeline / timing offset |
preset-name |
apply preset |
defaults: |
timeline-scoped defaults |
scrollTrigger.* |
ScrollTrigger options |
[&] |
"this element" (trigger/self) |
Full complex example:
<div data-animate="@lg:[&>div]:from:opacity-0|y-50|stagger-0.1|duration-0.5|ease-power2.out">
<div>Card 1</div><div>Card 2</div><div>Card 3</div>
</div>
On large screens, each child div fades in from 50px below, staggered by 0.1s.