Animation and scroll effects
Scroll/resize coalesced to requestAnimationFrame: read --scroll-progress, data-scroll-progress, and body classes from wckd-ui.js. Idle pass toggles in-view on .animate; pair animate image-zoom on .background-image blocks for the built-in zoom.
Download & setup
Load the kit from Get Started; use the style guide for utilities and tokens while wiring this component.
Default implementation
Live body hooks on this page
WCKD_BODY_SCROLL coalesces scroll/resize work to requestAnimationFrame. Read --scroll-progress, data-scroll-progress, and classes like at-top / scrolling-down from document.body in CSS or light scripts. In-view behaviour on .animate is covered under configuration options below.
Body: progress, data attribute, direction
Scroll this page, values read from the live body node. Full walkthrough: style guide.
Document progress (0 = top, 1 = bottom):
Markup
/* body , always updated when wckd-ui.js runs */
/* --scroll-progress, data-scroll-progress, .at-top, .at-bottom, .scrolling-up, .scrolling-down */
header.hero {
transform: scaleX(var(--scroll-progress, 0));
transform-origin: left center;
}
Configuration options
Default block: body scroll vars. Optional blocks: add animate (and optional image-zoom on .background-image); demos use inline <style> for motion only.
In-view: .animate
Elements with class animate are observed by wckdToggleInViewClass; when enough of the element is visible, the script adds in-view (and removes it when leaving). You define resting and .in-view looks, this demo uses scoped inline CSS for lift, slide, fade, blur, and scale-on-box patterns.
Scroll until each tile crosses the viewport. Default visibility threshold is 0.4 unless you set data-threshold on the node.
Lift (translateY)
Slide (translateX)
Fade only
Blur in
Scale (whole box)
Pop easing
Earlier threshold
Markup
<style>/* scope under a wrapper id in your theme */</style>
<div class="animate my-reveal">…</div>
/* CSS */
.my-reveal { opacity: 0; transform: translateY(12px); transition: … }
.my-reveal.in-view { opacity: 1; transform: none; }
In-view: .animate.image-zoom (still)
Add image-zoom alongside animate on the same element. The kit scales .background-image img from transform: scale(1) to 1.1 when in-view is on, Ken Burns–style motion on a hero or card still, without a second JS selector.
Use animate image-zoom on a wrapper that contains .background-image with a cover img. Rules live in wckd-ui.css; the script only toggles in-view on .animate.
Markup
<div class="animate image-zoom relative height-30 hide-overflow round">
<div class="background-image" aria-hidden="true">
<img src="/media/hero.jpg" width="1600" height="900" alt="" />
</div>
<div class="overlay relative tint-dark pad">…</div>
</div>
When to use
- Reading progress, gradient read-lines, and chapter position indicators.
- Tightening sticky header shadow on
scrolling-downor showing a footer CTA atat-bottom. - Entrance motion without a framework, using only CSS and
in-viewon.animate.
Implementation notes
- Body scroll tracking is not a separate bootstrap step; it runs when
wckd-ui.jsloads (flushScrollDirectionon scroll/resize). .hide-and-seekinwckd-ui.cssusesbody.scrolling-down/scrolling-upfor the auto-hiding site header.- Threshold for in-view:
parseFloat(parentCarousel?.dataset.threshold || el.dataset.threshold || '0.4')inwckdToggleInViewClass. - On very short pages,
at-topandat-bottomcan both be true; preferat-topto mean “not really scrolled” for header chrome.
Developer checklist
- Confirm the idle bootstrap still calls
wckdToggleInViewClasswhen the page uses.animatenodes. - Do not re-bind
windowscrollfor the same progress math, readbodyin CSS or usedata-scroll-progressin targeted scripts. - iOS overscroll can momentarily change edge flags; do not use them as the sole trigger for one-shot modals without debounce.