How it works
Load jskjs.scroll.js after jsKjs. Any $.to(), $.from() or $.timeline() then accepts a scrollTrigger option. With scrub: true the tween's progress follows the scrollbar; without it, the tween plays when the trigger enters the viewport.
start and end read as "trigger edge viewport edge": 'top 80%' means "when the top of the trigger reaches 80% down the viewport". Use '+=600' for a distance in pixels.
The add-on uses one passive scroll listener and recalculates on resize. Pinning wraps the element in a spacer so the content below doesn't jump.
Progress: 0% · waiting
View the source for this demo
<div id="st-zone" class="st-zone" aria-label="Scroll-linked animation area"><div id="st-box" class="st-box"></div></div>
<div class="st-bar" aria-hidden="true"><span id="st-bar"></span></div>
<p class="muted" style="margin-top:10px">Progress: <b id="st-out">0%</b> · <span id="st-state">waiting</span></p>
<div class="row"><button type="button" id="st-jump">$.scrollTo() the next section</button></div>$.timeline({
scrollTrigger: {
trigger: '#st-zone', start: 'top bottom', end: 'bottom top', scrub: true,
toggleClass: 'is-active',
onUpdate: st => $('#st-out').text(Math.round(st.progress * 100) + '%'),
onEnter: () => $('#st-state').text('entered'),
onLeave: () => $('#st-state').text('left (scrolled past)'),
onEnterBack: () => $('#st-state').text('entered again'),
onLeaveBack: () => $('#st-state').text('left (scrolled above)')
}
})
.to('#st-box', { x: -140, rotate: -90, ease: 'none' })
.to('#st-box', { x: 140, rotate: 180, borderRadius: '50%', ease: 'none' })
.to('#st-bar', { scaleX: 1, ease: 'none' }, 0);
$('#st-jump').on('click', () => $.scrollTo('.pager', { duration: 0.8, offset: 80 }));More examples
Reveal on enter, pin a hero, snap to sections
$('.reveal').each(function () {
$.from(this, { y: 40, opacity: 0, duration: .6, scrollTrigger: { trigger: this, start: 'top 85%' } });
});
$.scrollTrigger({ trigger: '#hero', pin: true, start: 'top top', end: '+=600' });
$.to('.panels', { xPercent: -300, ease: 'none',
scrollTrigger: { trigger: '.panels', pin: true, scrub: 1, snap: 1 / 3, end: '+=2400' } });Load the add-on
<script src="https://jskjs.org/cdn/1.0.0/jskjs.min.js"></script>
<script src="https://jskjs.org/cdn/1.0.0/plugins/jskjs.scroll.js"></script>API
ScrollTrigger-style scroll-linked animation and smooth scrolling.
Reference: jskjs.scroll.js →Sequence with positions: number, "label", "<", ">", "+=0.2", "-=0.2", "label+=1"; nest timelines.
Migrating
gsap.registerPlugin(ScrollTrigger) is replaced by loading the add-on. ScrollTrigger.create() → $.scrollTrigger(), ScrollTrigger.refresh() → $.ScrollTrigger.refresh(); the options and callbacks keep their names.Related features
Timelines
Sequence animations with $.timeline(): steps run in order, "<" runs a step alongside the previous one, "+=0.3" adds a gap, and await tl.play() tells you when it's done..
Open →MotionPlayback control
Every jsKjs tween and timeline is a controllable object: play, pause, reverse, seek to a label, scrub progress, change speed, repeat and yoyo.
Open →MotionSplit text
Split headings into lines, words and characters for staggered text animation with the jskjs.split.js add-on.
Open →