Featured recipe Library starters
AOS fade-up starter A minimal, version-pinned Animate On Scroll setup for teams that want a maintained preset library.
AOS CDN scroll
Copy recipe ↗ <link rel="stylesheet" href="https://unpkg.com/aos@2.3.4/dist/aos.css">
<script src="https://unpkg.com/aos@2.3.4/dist/aos.js"></script>
<script>
document.querySelectorAll('[data-sc-effect="aos-fade-up"]').forEach((node) => node.setAttribute('data-aos', 'fade-up'));
AOS.init({ once: true, duration: 650, offset: 80, disable: window.matchMedia('(prefers-reduced-motion: reduce)').matches });
</script>
<article data-aos="fade-up">Your content</article>
The foundation
Native recipes Small, composable patterns you can paste into a plain HTML site, a CMS, or a generated staging build.
AOS MIT
AOS fade-up starter A minimal, version-pinned Animate On Scroll setup for teams that want a maintained preset library.
<link rel="stylesheet" href="https://unpkg.com/aos@2.3.4/dist/aos.css">
<script src="https://unpkg.com/aos@2.3.4/dist/aos.js"></script>
<script>
document.querySelectorAll('[data-sc-effect="aos-fade-up"]').forEach((node) => node.setAttribute('data-aos', 'fade-up'));
AOS.init({ once: true, duration: 650, offset: 80, disable: window.matchMedia('(prefers-reduced-motion: reduce)').matches });
</script>
<article data-aos="fade-up">Your content</article>
Motion MIT
Motion spring entrance A small modern Motion starter for a springy entrance when CSS transitions need more control.
<div data-sc-effect="motion-spring">Your content</div>
<script type="module">
import { animate } from 'https://cdn.jsdelivr.net/npm/motion@12.23.24/+esm';
const node = document.querySelector('[data-sc-effect="motion-spring"]');
const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
animate(node, { opacity: [0, 1], y: [24, 0] }, reduceMotion ? { duration: 0 } : { type: 'spring', stiffness: 260, damping: 24 });
</script>
Lenis MIT
Lenis smooth scroll A smooth-scroll baseline for sites where scroll-linked motion is part of the interaction model.
<script type="module">
import Lenis from 'https://cdn.jsdelivr.net/npm/lenis@1.3.25/+esm';
const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const wrapper = document.querySelector('[data-sc-effect="lenis-smooth-scroll"]') || window;
const lenis = new Lenis({ wrapper, autoRaf: !reduceMotion, anchors: true });
window.siteCommanderLenis = lenis;
if (reduceMotion) lenis.stop();
window.matchMedia('(prefers-reduced-motion: reduce)').addEventListener('change', ({matches}) => {
if (matches) lenis.stop(); else lenis.start();
});
</script>
Embla Carousel MIT
Embla carousel starter A small, accessible carousel baseline with touch gestures and explicit previous/next controls.
<div class="embla"><div data-sc-effect="embla-carousel" class="embla__viewport"><div class="embla__container"><div class="embla__slide">Slide one</div><div class="embla__slide">Slide two</div></div></div><button type="button" data-embla-prev>Previous</button><button type="button" data-embla-next>Next</button></div>
<script type="module">
import EmblaCarousel from 'https://cdn.jsdelivr.net/npm/embla-carousel@8.5.2/+esm';
const viewport = document.querySelector('[data-sc-effect="embla-carousel"]');
const embla = EmblaCarousel(viewport, { loop: false });
document.querySelector('[data-embla-prev]').addEventListener('click', () => embla.scrollPrev());
document.querySelector('[data-embla-next]').addEventListener('click', () => embla.scrollNext());
</script>
Splitting.js MIT
Splitting.js text starter A character or word splitting starter for expressive headings that need precise sequencing.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/splitting@1.1.0/dist/splitting.css">
<script src="https://cdn.jsdelivr.net/npm/splitting@1.1.0/dist/splitting.min.js"></script>
<h2 data-sc-effect="splitting-text" data-splitting>Make it move</h2>
<style>[data-sc-effect="splitting-text"] .char { display: inline-block; opacity: 0; transform: translateY(.7em); animation: sc-split-in 650ms ease forwards; animation-delay: calc(var(--char-index, 0) * 60ms); } @keyframes sc-split-in { to { opacity: 1; transform: none; } } @media (prefers-reduced-motion: reduce) { [data-sc-effect="splitting-text"] .char { animation: none; opacity: 1; transform: none; } }</style>
<script>Splitting({ target: document.querySelector('[data-sc-effect="splitting-text"]'), by: 'chars' });</script>
TypewriterJS MIT
TypewriterJS starter A pinned typewriter starter for short rotating phrases, with an accessible static fallback.
<span id="typed" data-sc-effect="typed-text" aria-label="Build with clarity">Build with clarity</span>
<script src="https://unpkg.com/typewriter-effect@2.22.0/dist/core.js"></script>
<script>
const node = document.querySelector('[data-sc-effect="typed-text"]');
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) node.textContent = 'Build with clarity';
else {
const typewriter = new Typewriter(node, { loop: true, delay: 48 });
typewriter.typeString('Build with clarity').pauseFor(1200).deleteAll().typeString('Ship with confidence').start();
}
</script>
CountUp.js MIT
CountUp.js metric starter A lightweight number animation starter for metrics that enter the viewport.
<span id="metric" data-sc-effect="countup-metric" data-value="240">240</span>
<script type="module">
import { CountUp } from 'https://cdn.jsdelivr.net/npm/countup.js@2.8.0/+esm';
const node = document.querySelector('[data-sc-effect="countup-metric"]');
if (!matchMedia('(prefers-reduced-motion: reduce)').matches) new CountUp(node, Number(node.dataset.value)).start();
</script>
VanillaTilt MIT
VanillaTilt card A restrained 3D tilt starter for one featured card or product preview, with glare kept optional.
<script src="https://cdn.jsdelivr.net/npm/vanilla-tilt@1.8.1/dist/vanilla-tilt.min.js"></script>
<div data-sc-effect="vanilla-tilt">Featured visual</div>
<script>
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
VanillaTilt.init(document.querySelectorAll('[data-sc-effect="vanilla-tilt"]'), {
max: 7, speed: 500, scale: 1.015, glare: true, 'max-glare': .14
});
}
</script>