Cover slides

Each full-screen slide slides up over the last, which sinks back, dims and rounds its corners.

How it works

Slides are position: sticky; top: 0 at full height, so each new one covers the previous one for free. A script measures how far the next slide has come up and uses it to scale, dim and round the slide underneath.

Full file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Cover slides</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; }
body { font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; -webkit-font-smoothing: antialiased; }

body { background: #000; }
.slide {
  position: sticky; top: 0; height: 100vh; background: var(--bg); color: #fff;
  display: grid; place-content: center; text-align: center; transform-origin: 50% 0; will-change: transform;
}
.slide h2 { font: 900 clamp(2.6rem, 9vw, 6rem)/1 system-ui, sans-serif; letter-spacing: -.04em; margin: 0 0 .3em; }
.slide p { font-size: 1.3rem; margin: 0; opacity: .8; }
</style>
</head>
<body>
<section class="slide" style="--bg:#0f4c5c"><h2>Chapter one</h2><p>Scroll to turn the page.</p></section>
<section class="slide" style="--bg:#e36414"><h2>Chapter two</h2><p>The last slide sinks back.</p></section>
<section class="slide" style="--bg:#5f0f40"><h2>Chapter three</h2><p>And the next one covers it.</p></section>
<section class="slide" style="--bg:#9a031e"><h2>Chapter four</h2><p>Like a stack of paper.</p></section>
<section class="slide" style="--bg:#fb8b24"><h2>The end</h2><p>Scroll back up to unstack.</p></section>
<script>
const slides = [...document.querySelectorAll('.slide')];
function update() {
  const vh = innerHeight;
  slides.forEach((s, i) => {
    const next = slides[i + 1];
    if (!next) return;
    const t = Math.min(1, Math.max(0, 1 - next.getBoundingClientRect().top / vh));
    s.style.transform = 'scale(' + (1 - t * 0.12).toFixed(4) + ') translateY(' + (t * 4) + 'vh)';
    s.style.filter = 'brightness(' + (1 - t * 0.6).toFixed(3) + ')';
    s.style.borderRadius = (t * 28).toFixed(1) + 'px';
  });
}
addEventListener('scroll', update, { passive: true });
update();
</script>
</body>
</html>

More page turn effects