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

  1. After activation, go to the Glaze menu item in the WordPress admin sidebar (superhero icon).
  2. The admin screen has five tabs: Libraries, General, Breakpoints & Defaults, Presets, and Mappings.
  3. 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.

General

Breakpoints & Defaults

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.

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).

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:

Practical Notes

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

<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, so tl defaults 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.