Scroll-scrub scale
Tie a visual scale and opacity shift to scroll position with a bounded, progressive enhancement.
[data-sc-effect="scroll-scrub-scale"] {
--sc-progress: 0;
opacity: calc(1 - (var(--sc-progress) * .35));
transform: scale(calc(1 + (var(--sc-progress) * .12)));
transform-origin: center;
will-change: transform, opacity;
}
@media (prefers-reduced-motion: reduce) {
[data-sc-effect="scroll-scrub-scale"] { opacity: 1; transform: none; }
}
const scrubTarget = document.querySelector('[data-sc-effect="scroll-scrub-scale"]');
let scrubFrame = 0;
function updateScrub() {
scrubFrame = 0;
const box = scrubTarget.getBoundingClientRect();
const progress = Math.min(1, Math.max(0, (window.innerHeight - box.top) / (window.innerHeight + box.height)));
scrubTarget.style.setProperty('--sc-progress', progress.toFixed(3));
}
window.addEventListener('scroll', () => {
if (!scrubFrame) scrubFrame = requestAnimationFrame(updateScrub);
}, { passive: true });
updateScrub();