Motion · GSAP-style

Scroll-linked animation

Add scrollTrigger: { … } to any tween and the scroll position drives it. The same option names as GSAP's ScrollTrigger: start, end, scrub, pin, toggleClass.

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.

Live · Scroll the page — the square follows

Progress: 0% · waiting

View the source for this demo
HTML
<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>
JavaScript
$.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

JavaScript
$('.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

HTML
<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: { trigger, start, end, scrub, pin, snap, toggleActions, toggleClass, markers, once, onEnter… } · $.scrollTrigger(vars) · $.scrollTo(target, { duration, offset })

ScrollTrigger-style scroll-linked animation and smooth scrolling.

Reference: jskjs.scroll.js →
$.timeline({ defaults, paused, repeat, yoyo, onComplete… }) → .to .from .fromTo .set .add .call .addLabel .addPause .tweenTo

Sequence with positions: number, "label", "<", ">", "+=0.2", "-=0.2", "label+=1"; nest timelines.

Reference: $.timeline() →

Migrating

Coming from GSAPgsap.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