Skip to main content

Glaze for WP (and for BricksBuilder)

HereUpdate is1.2.0: comprehensivePreview documentation forof the Presets directly in the WP backend now possible.

What It Is

Glaze for WP / Bricks plugin (v 1.1.1).

Overview

Glaze for WP / Bricks is a WordPress plugin that brings Tailwind-style, declarative GSAPattribute-driven animations to any WordPress site,site (with first-classspecial supportaffinity for Bricks Builder) using GSAP under the Bricks page builder.hood. Instead of writing JavaScript animationfor code,every animated element, you describesimply animationsadd directly in HTML usinga data-animate attributesattribute (or a CSS classes),class, if you prefer class-based syntax) containing a compact animation string, and the plugin's runtime translatesscript thoseparses stringsit intoand drives GSAP callsautomatically.

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 theits lightweightScrollTrigger ~3kb GlazeJS library.

Everything the plugin needs — settings, presets, breakpoints, and downloaded libraries — is stored in flat files inside the plugin directory (/config and /lib). No custom database tables, options, transients, or custom post types are created, and every trace is removed cleanly on uninstall.

The plugin is authored by art10m (with Claude Opus 4.8) and licensed MIT. Note thatplugin. GSAP itself carriesknows itsnothing ownabout license,your whichmarkup; youit's shouldjust reviewinvoked with the right parameters.

GlazeJS is a small ES module that sits between your HTML and GSAP. It scans the DOM for commercialelements use.

carrying
the

Coreconfigured Concept

attribute

A(default Glazedata-animate) animationor isclass expressedprefix as(default aglaze-), parses the pipe-separated animation string inon aneach HTMLone attribute:

(e.g.
<div data-animate="from:opacity-0|y-50|30|duration-1"></div>0.6), 
and

Thistranslates is parsedthat into the equivalent GSAP call:

.from()/.to()/timeline
gsap.from(element,calls { opacity:including 0,support y:for 50,staggered duration: 1 });

The animation string follows the anatomy [breakpoint][selector]:state:properties, where:

    State is from:, to:, or bothchildren (mapping to gsap.from, gsap.to, and gsap.fromTo). Properties are separated by pipes |, split on the dash - into name/value pairs. Breakpoints are prefixed with @name: (e.g. @tablet:from:opacity-0). Child selectors use bracket notation [&>div]*]:...), wherenested selectors ([&_path]:...), transform origins, easing functions, and scroll-trigger properties.

    This plugin is the elementWordPress itself.

    "glue" Presetslayer: areit referencedloads with preset-nameGSAP and expandGlaze (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 theirthe fullfront string.end via

    Thea fullsmall syntaxruntime script (runtime.js). Everything is documentedstored in theflat bundled glaze-opus-docs-2.0.md "skill" file, which also serves as an AI-readable reference for generating presets via "Vibe Coding."


    Installation & Activation

      Upload the glaze-wp-bricks folder to /wp-content/plugins/.JSON/files (Or install the ZIP) Activate the plugin from the WordPress Plugins screen.

      On activation (glaze_wpb_activate in glaze-wp-bricks.php), the plugin:

        Creates the /config and /lib directories if missing. Drops a silent index.php (<?php // Silence is golden.) into each to prevent directory listing. Writes a .htaccess (Deny from all) into /config so the settings JSON is not publicly served. Seeds /config/settings.json, with/lib/*.js) rather than the defaultsoptions fromtable, Glaze_WPB_Settings::defaults()and ifis itfully doesn'tremoved alreadyon exist.uninstall.

        Getting

        AStarted new

        top-levelAfter activation, go to the Glaze menu item (superhero dashicon) appears in the WordPress admin.admin
        sidebar

        (superhero icon).

        The Admin Interface

        The settingsadmin screen ishas afive self-contained single-page app rendered by Glaze_WPB_Admin::render(). The PHP outputs only a skeleton — a header withtabs: ResetLibraries, General, Breakpoints & Defaults, Presets, and Mappings.

        Make your changes and click Save changes buttons,in the header. Reset restores all settings to plugin defaults (with a tabconfirmation bar, five empty <section> panels, and a toast container. All panel content is generated client-side by admin.js, which reads two localized globals:
          window.GlazeWPBAdmin — AJAX URL, nonce, current config, and library states.prompt). window.GlazeWPBStrings

          Tab-by-Tab all UI labels and hint text (from admin-strings.js), keeping copy separate from logic.

          The interface is styled by admin.css in a dark theme scoped under .glaze-wpb, using CSS custom properties for colors, radius, and accents. It also darkens the surrounding WordPress chrome (#wpwrap, #wpbody-content).

          The five tabs are:

          Guide

          1. Libraries

          Controls how GSAPGSAP, ScrollTrigger, and GlazeJS are loaded:loaded on the front end.

          • Library mode —: CDN (loadsjsDelivr/esm.sh from jsDelivrfastest /to esm.sh,set zeroup, setup)but relies on external requests) or Local (serves self-hosted copies from the plugin's /lib folder)folder — no third-party requests, but you must download each library first).
          • Use existing global GSAP: Enable whenif enabled, theanother plugin doesor notyour loadtheme itsalready ownloads GSAP andglobally, insteadso Glaze reuses an existing window.gsap (e.g.instead fromof loading a dedicated GSAP WordPress plugin), avoiding duplicate scripts and version conflicts.copy.
          • A Local libraries cardsection: listsFor each registered library (gsapGSAP core, ScrollTrigger, GlazeJS), scrolltrigger,you glaze)can withDownload (fetch a badge showing whether afresh local copy exists, pluscopy), Download/Refresh and(re-download an existing one, e.g. after an update), or Remove buttons.(delete the local copy, falling back to CDN until re-downloaded).

          Library operations are handled by AJAX (glaze_wpb_lib) and delegated to Glaze_WPB_Libs (see Technical Processes below).

          2. General

          • AttributesData attribute: The the dataHTML attribute nameGlaze scans for animation strings (default data-animate). GlazeOnly scans,change andthis theif classit conflicts with another plugin/theme.
          Class prefix: (glaze)Prefix for the optional class-based syntax.syntax Change(default theseglaze), onlye.g. to avoid conflicts.class="glaze-from:opacity-0". Behavior toggles:
            Enable ScrollTrigger: — registersRegisters GSAP's ScrollTrigger plugin forso scroll-basedanimations animations.can react to scroll position (scrollTrigger.* properties). Force GPU (force3D): Forces forcesanimated hardware-elements onto GPU-accelerated transforms.layers for smoother motion (may occasionally blur very small text). Watch DOM & re-animate: — enables a Firefox-safe MutationObserverWatches for dynamicallyelements added contentafter page load (seeAJAX below),content, withBricks-injected acomponents) configurableand 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: — allowsPlays animations to run live insidewhile editing in the Bricks editingcanvas canvas.(off by default, since constant replay can be distracting while building). Verbose console logging: Logs logsparsed parsinganimation strings and GSAP calls to the console — useful for debugging.debugging, should stay off in production.

            3. Breakpoints & Defaults

            • Breakpoints: Named name/media-querymedia pairsqueries thatused powerfor responsive prefixes like @tablet:from:opacity-0. The specialname is what you reference in animation strings; the value is the actual CSS media query. default name is usedapplies when no breakpoint@breakpoint: prefix is given.used.
            • Global defaults: Baseline elementsettings applied automatically everywhere.
              • Element defaults: (appliedFallback asproperties a fallback tofor every animated element,element (e.g. duration-0.6|ease-power2.out) and tloverridden timelineby anything set directly in an element's own attribute.
              Timeline defaults: (appliedApplied to every internal timeline,timeline e.g.Glaze creates (every element is wrapped in one), useful for a global easing or default defaults:ease-power2.outscrollTrigger.trigger).

              4. Presets

              Reusable animation strings organizedreferenced intoby namedname categoriesinside data-animate (Fades,e.g. Scale,fadeIn) Slide,or Zoom,as Bounce,a SVGclass Draw, Stagger, etc.(glaze-preset-fadeIn). Categories exist only to organize the admin UI — they have no front-end effecteffect, and are flattened into a single map before delivery. Presetpreset names must be unique across all categories.categories Yousince referencethey're flattened into one list at runtime.

                + Add category / + Preset: create new groups/rows. Preview button on each preset row: opens a presetmodal withthat 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 preset-name/config/settings.json (ordirectly to add many more presets at once; a glaze-preset-nameopus-docs-2.0.md file in classthe mode).plugin directory documents the full animation-string syntax for AI-assisted ("Vibe Coding") editing.

                5. Mappings

                AutomaticAutomatically class mappings attachattaches an animation to every element matching a CSS class/selectorclass or selector, without editingneeding eachto element'sadd markupdata-animate manually — useful for markup you don't control directly (e.g. Bricks-generated icon wrappers)wrappers Bricks generates).

                Each
                rowLeft pairsfield: aCSS class or selector to match (e.g. .fv-a-icon or fv-a-icon). withRight anfield: raw animation string or preset-name.
                to apply.

                Saving,Writing Resetting,Animation and Data FlowStrings

                WhenAnimation youstrings clickare Savepipe-separated changes,(|) key-value pairs, e.g.:

                from:opacity-0|y-30|duration-0.6|ease-power2.out
                

                Common patterns:

                  from: / admin.js's collect()to: walksdefine the renderedanimated DOM, rebuilds a config objectstate (validatingproperties and defaulting empty fields), and POSTs it as JSON tobefore the glaze_wpb_savetween AJAX action. Onvs. the server,target Glaze_WPB_Admin::ajax_save():
                    Runs the guard() check (capability + nonce)values). DecodesNumeric values follow the JSONproperty payload.name with a hyphen: y-30, scale-0.8, rotate-[-45] (brackets allow negative/complex values). Mergesduration-, itdelay-, ontoease-, stagger-, repeat-, yoyo- control timing/behavior. [&>*]: prefix applies the defaultsanimation with staggering to direct children (useful for lists/grids). array_replace_recursive()[&_path]: so/ [&_line]: prefix targets nested SVG elements. scrollTrigger.trigger-[&], scrollTrigger.start-[top_85%], scrollTrigger.scrub-1, etc. wire the structureanimation alwaysto staysscroll intactposition and(requires newEnable keys survive.ScrollTrigger). Persists@breakpoint: itprefix via(e.g. Glaze_WPB_Settings::save(@tablet:from:opacity-0), whichrestricts writesa pretty-printed JSONrule to /config/settings.json.a given breakpoint's media query.

                    Reset

                    Practical (glaze_wpb_reset)Notes

                    rewrites
                      Changing the filelibrary withmode defaults()to andLocal re-renderswithout first downloading a library will simply cause the UI.plugin

                      Glaze_WPB_Settings::get()to always reads the file and merges it onto the defaults, so a corrupt or partial file safely fallsfall back to defaults.

                      CDN
                      for

                      Thethat Front-Endlibrary Runtime

                      until

                      Glaze_WPB_Frontend::enqueue()you runsdownload on wp_enqueue_scripts (priority 20) and orchestrates loading:

                        It reads the merged config. If loadInBuilder is off and the code is running inside the Bricks builder (bricks_is_builder()), it bails out entirely.it. UnlessWatch useExternalGsapDOM is set, it enqueues GSAP (and ScrollTrigger, if enabled) from the URL resolved by Glaze_WPB_Libs::url() for the active mode. It enqueues runtime.js, depending on the GSAP scripts. It injectsuses a window.GlazeWPBricksFirefox-safe, payload (viachildList-only wp_add_inline_script(..., 'before')) containing the Glaze module URL, settings, breakpoints, defaults, flattened presets, and animation mappings.

                        runtime.js then executes this flow:

                          Waits for DOMContentLoaded, then polls for gsap (up to a 5s timeout). Optionally applies force3D config and registers ScrollTrigger. Runs applyAnimationMappings()MutationObserverfor each mapping, it queriesintentionally matchingnever elements and appends the animation class(es). Runs prepareSVGs() —listens for SVGsattribute flaggedchanges, asavoiding "draw"an animations,infinite itre-trigger measuresloop each strokeable child's total length via getTotalLength() and sets strokeDasharray/strokeDashoffset so line-drawing effects work. Dynamically imports the Glaze ESM module from glazeUrl and calls glaze(glazeConfig), passing GSAP core, the data attribute, class name, breakpoints, defaults, and presets. Fires a glazeReady window event exposing glaze, gsap, the config, and a reinit function so other integrationsthat can re-runoccur Glaze after their own AJAX loads.

                          The Firefox "looping" safeguard

                          A key technical detail: Glaze's own native watch mode is deliberately never enabled. Its internal observer reacts to attribute mutations, and sincewhen GSAP rewrites inline styles on every tick, native watch would re-trigger Glaze on its own output — a mutate → re-init → mutate loop that Firefox renders as endlessly restarting animations.

                          Instead, the Watch DOM & re-animate toggle drives a custom, Firefox-safe MutationObserver that listens for childList changes only (never attributes). When new nodes appear, it checks whether they are SVGs or match any mapping, and if so schedules a debounced re-init (re-preparing SVGs, re-running Glaze, and refreshing ScrollTrigger). When the toggle is off, no observer is attached at all. Either way, scheduleReinit remains exposed through the glazeReady event for manual re-runs.


                          Technical Processes in Detail

                          Library management (Glaze_WPB_Libs)

                          A static registry() defines each library's runtime CDN URL, download URL, local filename, and type (script vs module):

                            gsap → gsap.min.js from jsDelivr.styles. scrolltrigger → ScrollTrigger.min.js from jsDelivr. glaze → glaze.module.js, downloaded from esm.sh/glazejs?bundle&target=es2020.

                            url($key, $mode) returns the local /lib URL when mode is local and a local copy exists, otherwise the CDN URL. is_local() simply checks whether the local file exists.

                            download($key) fetches the source via wp_remote_get() (30s timeout, following redirects), validates the HTTP status and non-empty body, and writes it into /lib.

                            ESM import rewriting — a notable subtlety: esm.sh often returns a thin ESM shim whose specifiers are root-relative (e.g. export * from "/glazejs@2.0.1/es2020/glazejs.bundle.mjs";). Those only resolve against the CDN's origin. Since the plugin serves the file from your own WordPress domain, absolutize_root_relative_imports() uses a regex to rewrite from/import specifiers that begin with / into fully-qualified URLs pointing back at the CDN origin, so the locally-served module still resolves its dependencies correctly.

                            Preset flattening

                            Glaze_WPB_Settings::flatten_presets() collapses the categorized preset structure (category → { name → string }) into a single flat name → string map, which is what Glaze actually consumes at runtime. This is why preset names must be globally unique.

                            Security

                              All AJAX handlers call guard(), which requires the manage_options capability and a valid glaze_wpb_nonce, returning a 403 JSON error otherwise. The /config folder is protected with .htaccess and an index.php silence file. In admin.js, all stored, user-editable values (breakpoint media queries, preset strings, selectors, names) are passed through escHtml() / escAttr() helpers before being injected via innerHTML, preventing broken markup and stored XSS. Toggle labels, hints, and attribute values are all escaped at their injection points.

                              Uninstall

                              uninstall.php runs glaze_wpb_rrmdir() to recursively delete the /config and /lib directories and everything inside them. Because the plugin never touches the options table, transients, or custom post types, nothing else needs cleanup — the removal is complete.


                              Writing Animations: Quick Reference

                              Once configured, add animations directly in your markup or Bricks elements:

                              <!-- Simple fade up -->
                              <div data-animate="from:opacity-0|y-30|duration-0.6"></div>
                              
                              <!-- Using a preset -->
                              <div data-animate="preset-fadeInUp"></div>
                              
                              <!-- Responsive: only on tablet and up -->
                              <div data-animate="@tablet:from:opacity-0|scale-0.9"></div>
                              
                              <!-- Staggered children -->
                              <div data-animate="[&>*]:from:opacity-0|y-20|stagger-0.1|duration-0.5">
                                <div>One</div><div>Two</div><div>Three</div>
                              </div>
                              
                              <!-- Scroll-triggered -->
                              <div data-animate="from:opacity-0|y-40|scrollTrigger.trigger-[&]|scrollTrigger.start-[top_85%]"></div>
                              
                              <!-- SVG line-drawing -->
                              <svg class="glaze-preset-svgDrawIn"> ... </svg>
                              

                              Syntax notes: use [-50] for negative/literal values, underscores for values with spaces ([top_center]), dots for nested props (scale.x-2), and tl to make an element a timeline container. Consult the bundled glaze-opus-docs-2.0.md for the exhaustive syntax reference.


                              Bricks-Specific Notes

                                Bricks-generated markup (like icon wrappers) can be animated globally via the Mappings tab without editing individual elements. EnableIf Run inside Bricks builder onlyis ifleft you want to previewoff, animations livesimply won't fire while editing in the canvas; leaving it off avoids distracting replays on every edit. The runtime's childList observer specifically watches for components Bricks injects dynamically, applying mappings and re-initializing Glaze as they appearstill (whenwork Watch DOM is enabled).

                                Troubleshooting

                                  Animations don't run: confirm GSAP is loading (check the console for [Glaze] GSAP detected), or that useExternalGsap matches your actual setup. Enable Verbose console logging to see parsed strings and GSAP calls. Local mode not working: ensure you clicked Download for each library first; url() falls back to CDN until a local copy exists. Settings won't save: the error toast "Could not write /config/settings.json" indicates a file-permission problemnormally on the /configlive folder.front end. ScrollAll animationsplugin inert:data verifylives Enablein ScrollTriggerflat files (/config/settings.json, /lib/*.js) — nothing is onstored in the WordPress options table, and youreverything presetis includesdeleted scrollTrigger.trigger-[&].automatically Dynamic/AJAXon content not animating: enable Watch DOM & re-animate, or listen for the glazeReady event and call its reinit after your own content loads.uninstall.

                                  Screenshots