Orravo FX v3.0.0
A vanilla-JS animation engine for WordPress. 22 modules across reveal, pointer, type, background, navigation, decoration, and utility packs. Around 8KB gzipped. IntersectionObserver, requestAnimationFrame, GPU transforms. prefers-reduced-motion aware.
What Orravo FX does
Drop a data-orv-fx="<module>" attribute on any element. The engine wires up the right behaviour. There are 22 built-in modules covering scroll-reveal, parallax, sticky-media scrollytelling, count-up, marquee, magnetic cursor, image compare, lazy Lottie, and 14 more. No jQuery. No GSAP. No build step.
prefers-reduced-motion is requested.Orv_FX_Modules::register(). The engine treats it like a core module.csp_strict is on. Everything goes through enqueued bundles.orravo_fx_settings option. Nothing else to clean up at uninstall.Get it on your site
Standard WordPress plugin install. PHP 8.0+, WordPress 6.0+. No external services, no API keys.
orravo-fx-3.0.0.zip from the Orravo plugins page.OrvFX namespace and listens for the orv-fx:* custom events.Your first three modules
Open any post or page in Gutenberg, switch a paragraph block to the Code Editor view, and paste this. Save, view the page, scroll.
html<h2 data-orv-fx="text-split" data-orv-ts-by="word" data-orv-ts-stagger="80">Each word lands in turn.</h2>
<p data-orv-fx="scroll-reveal">This paragraph fades and slides up as it enters the viewport.</p>
<div data-orv-fx="count-up">
We have shipped <span data-orv-cu-to="14820">0</span> events this season.
</div>
data-orv-*. There are no inline scripts, no shortcodes, and no Gutenberg block dependencies. Plain HTML, anywhere it can render.Scroll Reveal
Fades and slides children into view as the host enters the viewport. Optional per-child stagger.
| Attribute | Type | Default | Notes |
|---|---|---|---|
data-orv-fx="scroll-reveal" | trigger | required | opts the host element in |
data-orv-sr-stagger | number | 0 | per-child delay multiplier (0 = no stagger) |
data-orv-sr-distance | px | 32 | vertical slide distance |
data-orv-sr-duration | ms | 700 | animation duration |
html<div data-orv-fx="scroll-reveal" data-orv-sr-stagger="2">
<h2>Lead</h2>
<p>Each child fades in 120ms after the previous one.</p>
<a href="/cta">Read the case study</a>
</div>
Reveal Blur
Same trigger as Scroll Reveal, with a frosted-glass filter:blur drop. Use sparingly; blur is a compositing op.
html<h1 data-orv-fx="reveal-blur">Hero appears from a blur</h1>
Sticky Media
Apple-style scrollytelling. A pinned media slot crossfades as panels enter view.
| Attribute | Where | Notes |
|---|---|---|
data-orv-fx="sticky-media" | section root | opts the section in |
data-orv-stk-target | media child | the element that gets pinned and crossfaded |
data-orv-stk-img | panel children | image URL to swap into the target on entry |
SVG Line Draw
Animates SVG strokes from undrawn to drawn when the element scrolls into view. Uses stroke-dasharray + stroke-dashoffset.
html<div data-orv-fx="svg-line-draw" data-orv-sld-dur="1400">
<svg viewBox="0 0 100 100">
<path d="M10 50 Q50 10 90 50 T170 50" stroke="#000" fill="none" stroke-width="2"/>
</svg>
</div>
Parallax Layers
Multi-speed layered parallax inside a container. rAF-throttled. Speeds expressed in vh per scroll unit.
| Attribute | Where | Notes |
|---|---|---|
data-orv-fx="parallax-layers" | container | opts the container in |
data-orv-px-speed | each child | signed number; negative drifts up, positive drifts down |
Particles Background
Lightweight canvas particle field that fills the host. Pauses when off-screen.
| Attribute | Type | Notes |
|---|---|---|
data-orv-pb-count | number | particles per host |
data-orv-pb-color | color | RGBA preferred for low-opacity dust |
data-orv-pb-speed | number | drift speed multiplier |
Hover Glow
Cursor-following spotlight gradient inside the host. Updates two CSS variables on mousemove. No canvas, no rAF.
html<div data-orv-fx="hover-glow" data-orv-hg-color="rgba(255,106,43,.4)" data-orv-hg-radius="320">
Hover me
</div>
Count Up
Numeric counters animate from zero on first viewport entry. Suffixes preserved (%, $, K, M).
| Attribute | Type | Default | Notes |
|---|---|---|---|
data-orv-cu-to | string | required | final value, suffix and prefix preserved |
data-orv-cu-dur | ms | 1200 | animation duration |
data-orv-cu-easing | enum | out-cubic | linear / out-cubic / out-expo |
Text Split
Wraps text in per-word or per-letter spans and reveals them on scroll with a stagger.
html<h2 data-orv-fx="text-split" data-orv-ts-by="word" data-orv-ts-stagger="80">
Hello kinetic web
</h2>
Kinetic Typography
Headlines scale based on viewport position: largest at the centre, smallest at the edges.
| Attribute | Type | Notes |
|---|---|---|
data-orv-kt-min | number | minimum scale (e.g. 0.85) |
data-orv-kt-max | number | maximum scale (e.g. 1.15) |
Text Shimmer
A soft highlight loops across the text via background-clip:text. Pairs well with kinetic typography for hero blocks.
Text Cycle
Rotates through child elements at an interval, fading between them. Great for "We make X. We make Y." hero patterns.
html<span data-orv-fx="text-cycle" data-orv-tc-dur="2400">
<span>fast</span>
<span>simple</span>
<span>quiet</span>
</span>
Magnetic Cursor
Element drifts toward the cursor when nearby. Opt-in via dedicated attribute. No-op on touch devices.
| Attribute | Type | Default |
|---|---|---|
data-orv-mag | flag | opts in |
data-orv-mag-strength | number 0 to 1 | 0.3 |
Tilt
Pointer-tracked 3D card tilt. Configurable max rotation and perspective.
| Attribute | Type | Default |
|---|---|---|
data-orv-tilt-max | deg | 12 |
data-orv-tilt-persp | px | 800 |
Cursor Trail
A small eased dot follows the cursor inside the host element. Pointer-only; no-ops on touch.
Marquee + Rich Marquee
Infinitely scrolling text or logo strip. Pauses on hover and on focus. Speed is set via the --orv-fx-mq-speed custom property. Rich Marquee adds an edge-fade mask and auto-cloning.
html<div data-orv-fx="marquee" style="--orv-fx-mq-speed:30s">
<div class="orv-fx-mq__track">
<span>Free shipping</span>
<span>30-day returns</span>
<span>Made in Lagos</span>
</div>
</div>
Image Compare
Before/after slider with a keyboard-accessible drag handle. Arrow keys move the divider; Home and End jump to extremes.
| Class | Where |
|---|---|
.orv-fx-ic | root, also takes data-orv-fx="image-compare" |
.orv-fx-ic__before | before image wrapper |
.orv-fx-ic__after | after image wrapper |
.orv-fx-ic__handle | draggable divider |
Lazy Lottie
Lazy-loads lottie-web from a CDN only when the host scrolls into view. Zero cost on pages that do not use the module.
| Attribute | Type | Notes |
|---|---|---|
data-orv-lt-url | url | JSON animation file |
data-orv-lt-loop | 0/1 | looping playback |
data-orv-lt-autoplay | 0/1 | play on load |
data-orv-lt-onscroll | 0/1 | defer fetch until viewport entry |
data-orv-lt-static | 0/1 | render first frame only, no playback |
Confetti Burst
DOM-particle confetti on click, on scroll, or via programmatic trigger.
| Attribute | Type | Notes |
|---|---|---|
data-orv-cb-trigger | enum | click / scroll / manual |
data-orv-cb-count | number | particles per burst |
Section Anchors
Smooth-scrolls in-page anchor links inside the host with a configurable header offset, then writes the hash to the URL.
html<nav data-orv-fx="section-anchors" data-orv-sa-offset="-80">
<a href="#chapter-1">Chapter 1</a>
<a href="#chapter-2">Chapter 2</a>
</nav>
Page Transitions
Fades the page on first paint and on internal-link clicks. Uses the View Transitions API where supported, falls back to an opacity fade.
Focus Trail
A traveling outline that follows keyboard focus through descendants of the host. Helps keyboard users keep their place.
prefers-reduced-motion handling
The engine reads the OS-level prefers-reduced-motion setting on boot. Modules respond in one of two ways: full skip (parallax, marquee, particles, kinetic) or fade-only fallback (scroll-reveal, text-split, sticky-media).
You can override per site in Settings. Set reduced_motion_override to auto (respect OS), force-on (suppress all motion regardless of OS), or force-off (always animate, ignore OS). Default is auto.
force-off option exists for staging environments and demos only.Performance notes
Bundle size, GPU usage, and the rules the engine follows to stay invisible.
- Bundle size: lite build is ~8KB gzipped, full build is ~14KB. Conditional load (Settings) drops the engine entirely on pages that do not use it.
- GPU transforms only: all motion uses
transformandopacity. No animatingtop,left,width, orheight. - IntersectionObserver: no
scrolllisteners onwindow. Hosts that scroll off-screen pause their work. - requestAnimationFrame throttling: parallax, count-up, and tilt all batch updates to a single rAF tick per frame.
- Tab-hidden pause: the engine listens for
visibilitychangeand pauses canvas-based modules (particles, cursor trail) when the tab is backgrounded. - Loading strategy: Settings →
loading_strategy=monolithic(one engine.js) or per-module (each module is its own lazy chunk fetched on first match).
Custom events
The engine emits four custom events on window or on the element. Wire them to analytics, error reporting, or your test harness.
| Event | Target | Detail |
|---|---|---|
orv-fx:ready | window | fires after the engine completes its first DOM scan |
orv-fx:module-init | element | per-module init; detail contains module + el |
orv-fx:module-error | window | fires when a module throws during init |
orv-fx:module-load-failed | window | fires when a lazy-loaded module bundle 404s |
jswindow.addEventListener('orv-fx:ready', () => {
console.log('[orv-fx] booted, first scan complete');
});
document.addEventListener('orv-fx:module-init', (ev) => {
const { module, el } = ev.detail;
sendBeacon('/track/fx-init', { module, path: location.pathname });
}, true);
window.addEventListener('orv-fx:module-load-failed', (ev) => {
console.error('[orv-fx] module 404', ev.detail);
});
Settings reference
Every key in the orravo_fx_settings option, with its default and what it does.
| Key | Default | Notes |
|---|---|---|
modules_enabled | all true | per-module on/off map |
enabled_packs | all true | per-pack toggle (reveal, pointer, type, background, navigation, decoration, utility) |
defer_script | true | add defer attribute to engine bundle |
force_disable | false | kill switch; engine does not load anywhere |
debug | false | verbose engine logging to console |
reduced_motion_override | auto | auto / force-on / force-off |
delete_on_uninstall | false | remove the option row at uninstall |
conditional_load | false | only enqueue on pages that use a data-orv-fx attribute |
loading_strategy | monolithic | monolithic / per-module |
designer_mode | false | visual editor highlights for active modules |
csp_strict | false | refuse inline injection |
prefer_css_scroll | false | prefer CSS scroll-timeline where supported |
Frequently asked
lottie-web, lazy-loaded from a CDN only when the Lottie module finds an element to mount.conditional_load on (Settings tab), disabled modules are not even shipped in the engine bundle on pages that do not use them.Orv_FX_Modules::register('my-fx', [...]) with your meta. The engine treats third-party modules identically to core ones; they appear in the admin, they get the same lifecycle hooks, they emit the same custom events.delete_on_uninstall is true (Settings), the orravo_fx_settings option is removed. Otherwise the option stays in place so a reinstall picks up exactly where you left off. There are no custom database tables to clean up.data-orv-fx="..." to any element via the builder's custom attributes panel. No widget, no shortcode, no integration shim required.csp_strict = true in Settings. The engine then refuses to inject inline styles or scripts; everything goes through the enqueued bundle. Page Transitions module degrades gracefully on CSP-strict pages where the View Transitions API would otherwise need a small inline shim.Changelog
- Module API:
Orv_FX_Modules::register()for first-class third-party modules - Module aliases: rename modules without breaking existing markup
- Per-pack toggles in admin (reveal, pointer, type, background, navigation, decoration, utility)
- Loading strategy switch: monolithic engine.js or per-module lazy chunks
- CSP-strict mode
- Conditional load: skip the bundle entirely on pages with no
data-orv-fxattributes - Designer mode: visual highlights in the editor for active modules
- WP-CLI:
wp orv-fx audit,wp orv-fx modules - REST API for engine + module config
- Site Health integration: dependency graph, broken-requires detector
- Customizer integration for per-template overrides
- Page Transitions module (View Transitions API + fade fallback)
- Section Anchors module (smooth-scroll + URL hash)
- Focus Trail module
- Text Shimmer, Text Cycle, Reveal Blur, Rich Marquee modules
- Confetti Burst module
- Particles Background, Hover Glow, Cursor Trail modules
- Kinetic Typography module
- Engine events:
orv-fx:ready,orv-fx:module-init,orv-fx:module-error,orv-fx:module-load-failed
Got a question about Orravo FX?
Reach out directly. Kenneth replies within 24 hours.
