Init options
AlrdyAnimate.init(options) accepts a single options object. Every field is optional — anything you don't pass falls back to the defaults below.
The values listed under Default are the single source of truth for the whole library: aa-duration, aa-ease, aa-delay, aa-scroll-start, etc. on any element fall back to these unless the per-element attribute is set. Override here once and every animation on the page picks it up.
All options
Section titled “All options”| Option | Default | Notes |
|---|---|---|
duration | 0.6 | Seconds. Per-element override: aa-duration. |
ease | 'power4.out' | Any GSAP ease string ('power2.out', 'expo.inOut', 'elastic.out(1, 0.3)') or one of the lib's named eases registered via CustomEase: osmo, energy, smooth, punch, relaxed, jump, pop, elastic, anticipate, bounce, fade. Named eases require CustomEase to be loaded. Per-element override: aa-ease. |
delay | not an init option | Per-element only via aa-delay (default 0). |
loadDelay | 0 | Seconds added to every aa-trigger="load" and aa-trigger="load-once" entrance's delay. Load entrances are paint-gated — built paused and released one frame after the reveal so a wall-clock tween can't advance during the heavy post-init layout/paint block (which made the entrance appear already mid-fade on content-heavy pages). At the default 0 the entrance starts the moment it's painted; a positive value adds an intentional beat on top, measured from that paint. Composes additively with per-element aa-delay — aa-delay="0.3" + loadDelay: 0.1 fires 0.4s after paint. Skipped on slow-network revisits (html[aa-fallback]) where the entrance is already replaced by the inline CSS fallback. Scroll / event / click / scrub triggers are unaffected. |
intensity | 1 | Global multiplier for every feature that reads aa-intensity: fade/rotate/slide translate, parallax depth, stack-card transforms, text-fade-* / text-blur-* offsets, hover-icon trail timing, marquee scrub sweep, nav hide-clearance, tabs scroll-pin range. 1 reproduces each feature's design baseline; 0.5 halves the effect; 2 doubles it. Per-element override: aa-intensity. |
scrollStart | 'top 85%' | Default ScrollTrigger start for every scroll-triggered animation. Standard GSAP syntax ('top 80%', 'center 50%'). Per-element override: aa-scroll-start. |
scrollEnd | 'bottom 60%' | Default ScrollTrigger end. Only used when aa-scrub is set — scrubbed animations need a start AND end to map progress onto. Non-scrubbed animations ignore this: they fire on enter and (with again: true, default) reset once the element fully leaves the viewport — that reset point is computed dynamically, not from scrollEnd. Per-element override: aa-scroll-end. |
scrubStart | unset | Optional start override that applies only when aa-scrub is set on the element. Use it to fire scrubbed animations earlier than the snappier non-scrubbed scrollStart — e.g. scrollStart: 'top 85%' (non-scrub fires close to viewport bottom) and scrubStart: 'top 100%' (scrub gets the full viewport pass). Per-element aa-scroll-start still wins over this. Same fallback order in all features that read scroll positions (scroll / text / reveal / reduced-motion). |
again | true | When true, scroll-triggered animations replay every time their trigger re-enters the viewport. When false, they play once and stay finished. Per-element override: aa-again="false" (play once) / aa-again="true" (force replay) — handy for animated content inside a slider/carousel that shouldn't re-fire as the section scrolls past. |
stagger | { chars: 0.02, words: 0.05, lines: 0.1, default: 0.1 } | Per-split-mode stagger defaults (seconds). The lib picks the value matching the resolved aa-split; aa-children without a split falls back to default. Per-element override: aa-stagger. |
autoplay | { interval: 4, hoverPause: false } | Slider/tabs autoplay defaults. Per-element override: aa-autoplay="<seconds> [hover-pause]". |
breakpoints | { sm: 480, md: 768, lg: 992, xl: 1280 } | Pixel widths for the aa-foo-md/aa-foo-lg suffixes and the | shorthand (which splits at md). Pass a partial object to override one breakpoint: { md: 900 }. |
reducedMotion | true | Collapse appear / text / reveal animations to a simple opacity fade under (prefers-reduced-motion: reduce); skip hover + parallax. Pass false to ignore the OS preference, or an object { duration, ease } to customize the fade timing. See Reduced motion for the full feature-by-feature breakdown. |
optimizeMobile | false | Drop the heaviest decorative features (text-*, parallax, standalone aa-split) when the viewport is below breakpoints.md. true makes text simply visible; 'fade' soft-fades it. Appear / reveal / components run unchanged. See Mobile optimization for what changes and why. |
smoothScroll | true | Lenis-driven smooth scroll. true creates a Lenis instance with library defaults; an object forwards any Lenis option; false disables. Silently skipped (dev-mode warning) when Lenis isn't loaded. See Smooth scroll for forwarded options, custom-script access (window.lenis), and page-transition behaviour. |
scrollState | true | Body scroll-state tracking: writes aa-scroll-direction="up|down" and aa-scroll-started="true|false" on <body>, and runs the [aa-toggle-playstate] IntersectionObserver. Pass false to opt out. |
root | document | Subtree to scan for aa-* elements. Pass a specific element to scope a re-init — useful for page-transition libs (Barba, View Transitions) that swap a container in while leaving the rest of the page intact. Element-scoped inits skip the global once-per-app setup (smoothScroll, scrollState, scroll-target). |
presets | unset | Class → animation map. Each entry maps a CSS class to one or more aa-* attributes that get virtually attached to matching elements — no DOM mutation, no FOUC interaction. Per-element aa-* always wins over the preset. See Class presets for the full reference + live demos. |
debug | false | Verbose dev-mode console logging: active feature set, detected GSAP plugins, missing-plugin warnings, Lenis status. |
Related pages
Section titled “Related pages”- Class presets — map CSS classes to
aa-*animations so you don't have to add attributes to every element. - Reduced motion — what
reducedMotion: truedoes to each feature, custom fade timing, opting out. - Mobile optimization — what
optimizeMobile: truedrops on small viewports and why. - Smooth scroll — Lenis configuration,
window.lenisaccess, page-transition behaviour.
How attribute fallbacks work
Section titled “How attribute fallbacks work”Per-element attributes always win over the init default. The pattern in every feature module is:
const duration = parseFloat(config['aa-duration']) || opts.durationconst ease = config['aa-ease'] ?? opts.easeThat's why all the per-animation reference tables list the defaults as (init) — the value really comes from init({ duration, ease, … }), not from the feature.
Example — global tuning
Section titled “Example — global tuning”AlrdyAnimate.init({ duration: 0.8, // every animation 33% slower ease: 'smooth', // named ease (needs CustomEase loaded) scrollStart: 'top 80%', // animations fire a bit earlier on scroll again: false, // play once, never replay stagger: { chars: 0.03 }, // slightly slower char cascade; words/lines unchanged})stagger, autoplay, and breakpoints are merged into their defaults — pass any subset.
Example — scoped re-init for page transitions
Section titled “Example — scoped re-init for page transitions”// Inside Barba's afterEnter / View Transitions update callback:await AlrdyAnimate.init({ root: container, debug: false })root scopes the DOM scan and skips the global one-shot setup (smoothScroll, scrollState, scroll-target). See Webflow + Barba recipe for the full destroy/init lifecycle.
TypeScript
Section titled “TypeScript”InitOptions is exported from the package — import it if you're wrapping init() in a typed helper:
import type { InitOptions } from 'alrdy-animate'
const config: InitOptions = { duration: 0.8, ease: 'smooth',}