The tween engine
Every frame runs on requestAnimationFrame. Transform shorthands β x, y, rotate, scale, scaleX, scaleY, skewX, skewY β are tracked per element and composed into a single transform write per frame, so animating x never clobbers a rotate set earlier.
Any other numeric CSS property (opacity, width, margin-left, stroke-dashoffset) tweens from its computed value. Options: duration (seconds, default 0.4), delay, ease, stagger and onComplete.
Respect prefers-reduced-motion: check matchMedia('(prefers-reduced-motion: reduce)') and skip or shorten decorative tweens.
View the source for this demo
<div class="row">
<div class="field" style="min-width:180px"><label for="tw-ease">Ease</label><select id="tw-ease"></select></div>
<div class="field" style="min-width:200px"><label for="tw-dur">Duration: <span id="tw-dur-v">0.7</span>s</label><input id="tw-dur" type="range" min="0.2" max="2" step="0.1" value="0.7"></div>
</div>
<div id="tw-arena" class="arena" aria-label="Animation area. Click to move the ball, or use the corner buttons."><div id="tw-ball" class="ball"></div></div>
<div class="row" style="margin-top:10px" aria-label="Move to a corner">
<button type="button" data-corner="tl">β Top left</button><button type="button" data-corner="tr">β Top right</button>
<button type="button" data-corner="bl">β Bottom left</button><button type="button" data-corner="br">β Bottom right</button>
</div>
<pre class="out" id="tw-out"></pre>const SIZE = 44;
$.each($.easings, name => $('<option>').text(name).appendTo('#tw-ease')); // every built-in easing
$('#tw-ease').val('back.out');
$('#tw-dur').on('input', function () { $('#tw-dur-v').text(this.value); });
async function moveTo(x, y) {
const ease = $('#tw-ease').val(), duration = +$('#tw-dur').val();
$('#tw-out').text("await $.to('#tw-ball', { x: " + Math.round(x) + ', y: ' + Math.round(y) +
', duration: ' + duration + ", ease: '" + ease + "' })");
await $.to('#tw-ball', { x, y, duration, ease });
$.fromTo('#tw-ball', { scale: 1.3 }, { scale: 1, duration: .3, ease: 'elastic.out' }); // land with a wobble
}
$('#tw-arena').on('click', function (e) {
const r = this.getBoundingClientRect();
moveTo(Math.min(Math.max(e.clientX - r.left - SIZE / 2, 0), r.width - SIZE),
Math.min(Math.max(e.clientY - r.top - SIZE / 2, 0), r.height - SIZE));
});
$('[data-corner]').on('click', function () {
const r = $('#tw-arena')[0].getBoundingClientRect(), c = this.dataset.corner;
moveTo(c.includes('r') ? r.width - SIZE : 0, c.includes('b') ? r.height - SIZE : 0);
});More examples
Everyday tweens
$.to('.card', { y: -6, scale: 1.02, duration: .2 });
await $.to('#modal', { opacity: 0, y: 20, duration: .25 });
$('#modal').hide();
$('.badge').to({ rotate: 360, duration: 1, ease: 'elastic.out' }); // chainable formAPI
Tween to a state. stagger offsets each elementβs start; onComplete fires after the last finishes. Also chainable on sets: $(sel).to(props).
Built in: linear, ease-in, ease-out, ease-in-out, power2.in, power2.out, power2.inOut, back.out, elastic.out, bounce.out β exposed as $.easings β or pass any function mapping 0β1 progress.
Migrating
gsap.to() β $.to(), same property names and seconds. Not included: repeat/yoyo, playback control on single tweens, colour and SVG-attribute tweening, onUpdate, and automatic overwriting of competing tweens.Related features
From & fromTo
Animate elements in from a starting state with $.from(), or define both ends with $.fromTo().
Open βMotionTransforms
Animate x, y, rotate, scale, scaleX, scaleY, skewX and skewY independently β jsKjs composes them into one transform per frame.
Open βMotionEasings
Ten built-in easings β linear, ease-in/out, power2, back.out, elastic.out, bounce.out β plotted as curves and playable live.
Open β