Documentation menuRecipes
Recipes
Counters, reading progress, headers, carousels, text and image sequences.
Short, copyable answers to common scroll effects. All of them respect reduced motion where it makes sense.
Counter that counts up
Without JavaScript, whole numbers:
<span data-sigmoid="count" style="--sigmoid-count: 1200" role="img" aria-label="1200"></span>
With any format:
track(".stat", (p, el) => {
el.textContent = `${(98.6 * p).toFixed(1)} %`;
}, { range: "entry 0% cover 50%" });
Reading progress bar
<div data-sigmoid="progress" class="reading-bar"></div>
.reading-bar { position: fixed; inset: 0 0 auto; height: 3px; background: currentColor; }
Header that shrinks on the first screens
scrub("header", [{ paddingBlock: "2rem" }, { paddingBlock: "0.75rem" }], {
range: [0, 10], // done after the first 10% of the page
});
Words that arrive one by one
const { elements, parent } = splitText("h1");
reveal(elements, { subject: parent, keyframes: "fade-up", stagger: 6 });
Horizontal gallery
reveal(".slide", { axis: "inline", keyframes: "scale-in", stagger: 10 });
The slides must sit in a container with overflow-x: auto. Sigmoid measures against it, in the browser's native timeline and in the fallback.
Scroll story with a pinned image
<section id="how" style="height: 300vh">
<div style="position: sticky; top: 0; height: 100vh"> … </div>
</section>
story("#how", { steps: 3, onStep: (i) => showStep(i) });
Image sequence on a canvas
const frames = 120;
track("#sequence", (p) => {
draw(images[Math.min(Math.floor(p * frames), frames - 1)]);
}, { range: "contain" });
One easing everywhere
@import "tailwindcss";
@import "@sweberdev/sigmoid/tailwind.css";
<button class="transition-transform duration-500 ease-bouncy hover:scale-105">Buy</button>