fancoolo-fx
v1.8.6
Published
A class-driven GSAP animation wrapper for WordPress and static sites.
Maintainers
Readme
fancoolo-fx — Fancoolo FX
A class-driven GSAP animation wrapper for WordPress and static sites. Add a CSS class to any element and it animates — no JavaScript needed per page.
Install
npm installUsage
Load GSAP + plugins + FX as separate script tags — no build step needed:
<!-- 1. GSAP core -->
<script src="node_modules/gsap/dist/gsap.min.js"></script>
<!-- 2. GSAP plugins -->
<script src="node_modules/gsap/dist/ScrollTrigger.min.js"></script>
<script src="node_modules/gsap/dist/SplitText.min.js"></script>
<!-- 3. Fancoolo FX -->
<script src="src/fx.js"></script>Then add classes in your HTML. Done. FX auto-initializes on DOMContentLoaded.
Quick Start
<h1 class="fx-text-reveal-pl">Hello World</h1>The heading animates with a masked line-reveal on page load.
Available Effects
| Effect | Class | Description |
|--------|-------|-------------|
| Text Reveal | fx-text-reveal | Split into lines, masked slide-up |
| Reveal | fx-reveal | Slide up from below + fade |
| Spin Reveal | fx-spin-reveal | Rotate + scale in + fade |
| BG Reveal | fx-bg-reveal | Slide up from y:100% + fade |
| Scale In | fx-scale-in | Scale from 0.92 + fade |
| Fade In | fx-fade-in | Opacity + subtle scale, no movement |
| Blur In | fx-blur-in | Fade + deblur (camera-focus effect) |
| Clip Up | fx-clip-up | Clip-path wipe from bottom |
| Clip Down | fx-clip-down | Clip-path wipe from top |
| Tilt In | fx-tilt-in | 3D perspective reveal (scrub-based) |
| Type Writer | fx-type-writer | Characters revealed one by one |
| Draw SVG | fx-draw-svg | Stroke draw-on for SVG paths (fx-draw-svg-scrub for scroll-scrubbed) |
| Parallax | fx-parallax | Scrub-based Y-shift on scroll |
| Split Words | fx-split-words | Words staggered fade + slide-up |
| Slide In | fx-slide-left / fx-slide-right | Horizontal slide in |
Three trigger modes (append to any class above):
-pl— Page load: animates when the DOM is ready (e.g.fx-reveal-pl)-st— Scroll trigger: animates when the element enters the viewport (e.g.fx-reveal-st)- No suffix — Section trigger: a bare
fx-revealinside a<section>is auto scroll-triggered, using the section to scope which elements are picked up
fx-tilt-in and fx-parallax are scrub-based — tied directly to scroll position rather than playing once on enter.
How Scroll Triggering Works
When FX sees a scroll-triggered element (-st suffix or bare class inside a section), it creates a GSAP ScrollTrigger with these defaults:
start: 'top 85%'— the animation fires when the top of the element (or its section) reaches 85% down from the top of the viewportonce: true— plays once, doesn't replay on re-scroll
For grouped siblings (same class, same parent), the parent is used as the shared trigger — so all items animate together with stagger, rather than each triggering independently.
Section Auto-Trigger
Elements with bare .fx-* classes (no -pl/-st suffix) inside a <section> are automatically scroll-triggered using the section as the trigger:
<section>
<h2 class="fx-text-reveal">This auto-triggers on scroll</h2>
<p class="fx-text-reveal">No suffix needed inside a section</p>
<img src="photo.jpg" class="fx-reveal" />
</section>Change the container selector via config:
FX.config.sectionSelector = '.animate-section'; // only sections with this class
FX.config.sectionSelector = 'section, .wp-block-group'; // multiple selectorsTag-Based Auto-Animation
For zero-class animation, configure tagMap to automatically animate elements by their tag name inside sections:
<!-- Set config BEFORE the FX script loads -->
<script>
window.__FX_CONFIG__ = {
tagMap: {
'h1,h2,h3,h4,h5,h6': 'textReveal',
'p,blockquote': 'textReveal',
'img,video': 'reveal',
}
};
</script>
<script src="dist/fx.min.js"></script>Or configure after load and re-init:
FX.config.tagMap = { 'h1,h2,h3': 'textReveal', 'img': 'reveal' };
FX.init();Elements already animated by explicit .fx-* classes are skipped — tagMap only picks up unhandled elements.
Auto-Stagger
Sibling elements with the same class are automatically staggered (0.15s between each):
<div>
<p class="fx-text-reveal-st">First paragraph</p>
<p class="fx-text-reveal-st">Second paragraph</p>
<p class="fx-text-reveal-st">Third paragraph</p>
</div>Modifier Classes
Override timing per-element using modifier classes (Gutenberg-friendly — no inline styles needed):
| Class | Default | Description |
|-------|---------|-------------|
| fx-duration-[n] | 1.2 (text) / 1 (others) | Animation duration in seconds |
| fx-delay-[n] | 0 | Start delay in seconds |
| fx-stagger-[n] | 0.1 | Delay between staggered items |
| fx-ease-[name] | power3.out | GSAP easing function |
| fx-start-[pos] | top 85% | ScrollTrigger start position |
| fx-scrub-[n] | 0.6 | Scrub amount for scrub effects (fx-draw-svg-scrub, fx-tilt-in, fx-parallax) |
| fx-y-[n] | 50 | Parallax shift distance in pixels |
<h2 class="fx-text-reveal-st fx-duration-[2] fx-stagger-[0.25]">
Slower and wider stagger
</h2>Add these in Gutenberg via the "Additional CSS class(es)" field alongside the effect class.
JavaScript API
For compound sequences or dynamic content, use the FX global:
FX.textReveal(document.querySelector('.hero-title'), {
trigger: 'scroll',
delay: 0.3,
scrollTrigger: { trigger: '.hero-section' }
});API Reference
All functions accept (element, options):
| Function | Options |
|----------|---------|
| textReveal(el, opts) | duration, ease, stagger, delay, trigger, scrollTrigger |
| reveal(el, opts) | y (default 80), duration, ease, delay, trigger, scrollTrigger |
| spinReveal(el, opts) | rotation (default -30), scale (default 0.9), duration, ease, delay, trigger, scrollTrigger |
| bgReveal(el, opts) | duration, ease, delay, trigger, scrollTrigger |
| scaleIn(el, opts) | scale (default 0.92), duration, ease, delay, trigger, scrollTrigger |
| fadeIn(el, opts) | duration, ease, delay, trigger, scrollTrigger |
| blurIn(el, opts) | duration, ease, delay, trigger, scrollTrigger |
| clipUp(el, opts) | duration, ease, delay, trigger, scrollTrigger |
| clipDown(el, opts) | duration, ease, delay, trigger, scrollTrigger |
| tiltIn(el, opts) | duration, ease, scrub, scrollTrigger (scrub-based) |
| typeWriter(el, opts) | duration, ease, stagger, delay, trigger, scrollTrigger |
| drawSVG(el, opts) | duration, ease, delay, scrub, end, trigger, scrollTrigger |
| parallax(el, opts) | y (default 50), scrub, end, scrollTrigger (scrub-based) |
| splitWords(el, opts) | y (default 30), duration, ease, stagger, delay, trigger, scrollTrigger |
| slideIn(el, opts) | x (default 100), direction ('left'/'right'), duration, ease, delay, trigger, scrollTrigger |
Set trigger: 'scroll' to enable ScrollTrigger. Pass scrollTrigger: { trigger: someEl } to use a different trigger element.
Utility Methods
| Method | Description |
|--------|-------------|
| FX.init() | Re-scan DOM and apply animations (for dynamic content) |
| FX.refresh() | Re-split text after layout change (sidebar toggle, font load) |
| FX.config | Global config object |
Resize handling: Text-based effects (textReveal, typeWriter, splitWords) automatically re-split when the browser width changes. After one-shot animations complete, the SplitText DOM is reverted so text reflows naturally.
Preventing Flash of Unstyled Content (FOUC)
FX uses GSAP's autoAlpha internally, so elements with visibility: hidden are revealed automatically when their animation starts. Add this CSS before any content renders to prevent the flash where elements appear briefly before JS loads:
.fx-text-reveal-pl,.fx-text-reveal-st,.fx-text-reveal,
.fx-reveal-pl,.fx-reveal-st,.fx-reveal,
.fx-spin-reveal-pl,.fx-spin-reveal-st,.fx-spin-reveal,
.fx-bg-reveal-pl,.fx-bg-reveal-st,.fx-bg-reveal,
.fx-scale-in-pl,.fx-scale-in-st,.fx-scale-in,
.fx-fade-in-pl,.fx-fade-in-st,.fx-fade-in,
.fx-blur-in-pl,.fx-blur-in-st,.fx-blur-in,
.fx-clip-up-pl,.fx-clip-up-st,.fx-clip-up,
.fx-clip-down-pl,.fx-clip-down-st,.fx-clip-down,
.fx-tilt-in-st,.fx-tilt-in,
.fx-type-writer-pl,.fx-type-writer-st,.fx-type-writer,
.fx-draw-svg-pl,.fx-draw-svg-st,.fx-draw-svg,.fx-draw-svg-scrub,
.fx-split-words-pl,.fx-split-words-st,.fx-split-words,
.fx-slide-left-pl,.fx-slide-left-st,.fx-slide-left,
.fx-slide-right-pl,.fx-slide-right-st,.fx-slide-right{visibility:hidden}Reduce Motion — required companion rule. With respectReducedMotion: true (the default), FX skips all animations when the OS "reduce motion" setting is on — which means the reveals never run and never lift the visibility:hidden above, leaving content invisible. Add this after the rule above so the hidden state is lifted when animations won't play (no !important — GSAP's inline styles must still win if you set respectReducedMotion: false):
@media (prefers-reduced-motion: reduce) {
.fx-text-reveal-pl,.fx-text-reveal-st,.fx-text-reveal,
.fx-reveal-pl,.fx-reveal-st,.fx-reveal,
.fx-spin-reveal-pl,.fx-spin-reveal-st,.fx-spin-reveal,
.fx-bg-reveal-pl,.fx-bg-reveal-st,.fx-bg-reveal,
.fx-scale-in-pl,.fx-scale-in-st,.fx-scale-in,
.fx-fade-in-pl,.fx-fade-in-st,.fx-fade-in,
.fx-blur-in-pl,.fx-blur-in-st,.fx-blur-in,
.fx-clip-up-pl,.fx-clip-up-st,.fx-clip-up,
.fx-clip-down-pl,.fx-clip-down-st,.fx-clip-down,
.fx-tilt-in-st,.fx-tilt-in,
.fx-type-writer-pl,.fx-type-writer-st,.fx-type-writer,
.fx-draw-svg-pl,.fx-draw-svg-st,.fx-draw-svg,.fx-draw-svg-scrub,
.fx-split-words-pl,.fx-split-words-st,.fx-split-words,
.fx-slide-left-pl,.fx-slide-left-st,.fx-slide-left,
.fx-slide-right-pl,.fx-slide-right-st,.fx-slide-right{visibility:visible}
}WordPress: The plugin injects both rules automatically in the <head> — no action needed.
Using in a New Project
- Copy this repo (or
npm install) - Add the 4 script tags (gsap, ScrollTrigger, SplitText, fx.js)
- Add the FOUC prevention CSS in your
<head>(see above) - Add
.fx-*classes in your HTML
For compound sequences, create a project-specific JS file loaded after fx.js:
// animations.js — loaded after fx.js
document.addEventListener('DOMContentLoaded', function () {
var hero = document.querySelector('.hero');
if (hero) {
FX.scaleIn(hero.querySelector('.card'), { trigger: 'scroll', scrollTrigger: { trigger: hero } });
FX.textReveal(hero.querySelector('h2'), { trigger: 'scroll', delay: 0.2, scrollTrigger: { trigger: hero } });
}
});File Structure
├── fancoolo-fx.php ← WordPress plugin
├── assets/ ← GSAP + fx.js copies for WP
├── src/fx.js ← Source of truth (npm package entry)
├── package.json ← npm deps (gsap)
├── docs/ ← GitHub Pages site
├── .distignore ← Files excluded from WP plugin zip
├── .npmignore ← Files excluded from npm package
├── CLAUDE.md ← Project context for Claude
└── README.mdWordPress / Gutenberg
Fancoolo FX uses CSS classes which you can add via the "Additional CSS class(es)" field in the block sidebar. No data attributes or inline styles needed.
Building the WordPress Plugin Zip
Use WP-CLI dist-archive to build a clean plugin zip. The .distignore file controls which files are excluded.
# Install the command (one-time)
wp package install wp-cli/dist-archive-command
# Build the zip from the project root
wp dist-archive .This produces fancoolo-fx.1.x.x.zip containing only the plugin files (fancoolo-fx.php, assets/, inc/, README.md). Upload it via Plugins → Add New → Upload in WordPress.
Releasing
Publishing is automated. Pushing a version tag triggers the GitHub Actions
workflow (.github/workflows/release.yml), which builds the WordPress plugin
zip and publishes to npm (npm publish --provenance, authed by the
NPM_TOKEN repo secret). Do not run npm publish manually.
Only src/fx.js, package.json, and README.md are published to npm
(controlled by .npmignore).
Release checklist
- Bump the version in
package.jsonandfancoolo-fx.php - Run
npm run syncto copysrc/fx.jstoassets/anddocs/vendor/ - Add a changelog entry to
CHANGELOG.md - Commit and push to
main - Tag and push:
git tag X.Y.Z && git push origin X.Y.Z
The tag push does the rest — GitHub Release zip + npm publish.
