Scroll Book Shelf Slide — Free HTML CSS JS Snippet

Scroll Book Shelf Slide · Scroll · Plain HTML, CSS & JS · Live preview

What's included

Features

Single GSAP scrub timeline and single ScrollTrigger shared by every book, sliced into equal numeric segments
zIndex tween raises whichever book is active above its neighbors, so its opened panel is never hidden behind later spines
Book spines pivot with transform-origin: bottom center for a natural pull-forward motion
Pages panel scales open from scaleX(0.2) to scaleX(1) like a hinged cover
Every book resets cleanly at the end of its own segment — none stay permanently slid out
Fully reversible — scrubbed timeline plays backward cleanly on scroll-up
Warm wood-and-leather color palette via CSS custom property --hue per book
No pinning required — content scrolls through a tall section for a natural reading rhythm
Responsive book and panel sizing at the 640px breakpoint
Vertical writing-mode spine labels for an authentic bookshelf look

About this UI Snippet

Scroll Book Shelf Slide — GSAP Timeline Segments, Shelf Illustration & Content Panel Reveal

Screenshot of the Scroll Book Shelf Slide snippet rendered live

This snippet turns a row of styled div "book spines" into a scroll-driven storytelling shelf: as the user scrolls through a tall pinned-feeling section, each book in turn slides outward and tilts off the shelf while a hinged "pages" panel unfolds beside it to reveal a title and description, then both settle back before the next book takes its turn.

One shared scrub timeline, sliced into segments

A single GSAP timeline is attached to .shelf-wrap with scrollTrigger: { start: 'top top', end: 'bottom bottom', scrub: true } — genuinely one timeline and one ScrollTrigger for every book, not one per book. Each book gets exactly one whole numeric unit of that timeline to itself (t0 = i), and its slide/tilt and pages-panel open/close tweens are placed at explicit fractional offsets within that unit using GSAP's position parameter and explicit duration values, so the total timeline length scales predictably with the book count and every book's turn takes the same, correctly-proportioned slice of the scroll distance.

The slide-and-tilt

Each .book is a narrow div styled as a spine with transform-origin: bottom center so it pivots naturally like a book being pulled forward. gsap.fromTo animates x, y and rotate from resting values to x: 34, y: -10, rotate: -7 — enough to read as "sliding outward and tipping" without leaving the shelf entirely.

Raising the active book above its neighbors

The .pages panel is absolutely positioned to the right of its spine, wide enough to visually overlap several of the books sitting next to it in the row. Left alone, that overlap is a real problem: with no explicit z-index, later book spines in DOM order paint on top of an earlier book's opened panel, hiding almost all of it behind the very spines it's supposed to float above. A zIndex tween lifts each book to the front for exactly the duration of its own segment and drops it back afterward, so whichever book is currently active is always the one on top, regardless of where it sits in the row.

The pages panel

The .pages div starts at opacity: 0, scaleX: 0.2, translated slightly left, with transform-origin: left center, then scales up to scaleX: 1 with full opacity — mimicking a book cover swinging open — timed to appear once the spine has slid far enough to have "room," and closing again before the segment ends so both the spine and the panel are back at rest by the time the next book's turn begins.

Fully reversible, no pinning required

Because everything lives on one scrubbed timeline keyed to scroll progress (not pin: true), scrolling back up smoothly reverses every book in sequence — GSAP scrub timelines are inherently bidirectional, so no manual reset logic is needed.

Pair this with Scroll Card Deck Shuffle for another sequential reveal pattern, or Scroll Polaroid Stack Flip for a similarly staggered "stack" story.

Step by step

How to Use

  1. 1
    Scroll through the previewScroll down slowly — each book spine slides forward and tilts while its content panel unfolds beside it, then both reset as the next book begins.
  2. 2
    Add or remove booksDuplicate a .book element inside .books with a unique --hue custom property for its spine color, a spine-label span, and a .pages panel with your own title/description.
  3. 3
    Tune the segment timingIn the JS panel, adjust the fractional offsets and durations inside each book's tl.fromTo/.to calls (relative to its own t0 = i) to control the pacing of its slide, open, and close.
  4. 4
    Adjust the slide distance and tiltChange the x, y and rotate values inside the fromTo call to make the slide-off more or less dramatic.
  5. 5
    Restyle the shelfThe .shelf-board and .shelf-stage background gradients set the warm wood tone — swap the hsl() values or background gradient for a different library aesthetic.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component, or "Tailwind" for a React + Tailwind version.

Real-world uses

Common Use Cases

Book or product catalog storytelling
Use each "book" as a product or publication, revealing a description panel as users scroll through a catalog page.
Sequential feature reveal
Repurpose each book as a feature card in a numbered story, sliding out and opening to reveal a description one at a time.
Portfolio or case-study timeline
Each book becomes a project; the pages panel reveals project details as the visitor scrolls through your body of work.
Library or bookstore landing page
A literal bookshelf hero section for a reading app, library, or bookstore, introducing featured titles one by one.
Editorial long-form storytelling
Break a long article into "chapters" represented as books that open to reveal a summary as the reader scrolls.
Learn multi-segment scrub timelines
Study how one numeric unit per book divides a single ScrollTrigger across many sequential animations without extra triggers, and how a zIndex tween keeps each one visible in turn.

Got questions?

Frequently Asked Questions

A single timeline scrubbed against one long .shelf-wrap section is more performant and keeps every book perfectly synchronized to scroll position. Creating a separate timeline per book (each with its own default tween durations, on an identical full-page ScrollTrigger) makes every book's effective timeline a different length, so they drift out of sync with each other — genuinely one shared timeline with explicit positions and durations is what keeps every book's turn the same size.

The panel is positioned to the right of its spine and is wide enough to visually overlap several of the following books in the row. Without an explicit z-index, later siblings in DOM order paint on top of it by default, so most of an opened panel would render hidden behind the very spines it should float above. Raising the active book's z-index for the duration of its own segment (and lowering it again afterward) guarantees whichever book is currently open is always the one on top.

Remove that book's .to(pages, { opacity: 0 ... }) and spine-reset tweens, or move them much closer to t0 + 1 so they only fire right at the very end of its segment.

Yes — add an <img> inside .pages alongside or instead of the <p> text; the panel container already scales and fades in as a unit.

Because scrub: true ties the timeline's playhead directly to scroll position rather than firing a one-shot animation, GSAP automatically plays every tween — including the zIndex sets — in reverse as the user scrolls upward.

Any number — each book simply claims the next whole integer unit of the timeline (t0 = i), so the total timeline length and the scroll distance it maps to both grow automatically with however many .book elements exist.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Paste this snippet's HTML, CSS and JS into an AI assistant and ask it to walk through why every book needs to share one single GSAP timeline and ScrollTrigger rather than each creating its own, and why the active book's z-index has to be raised above its neighbors while its pages panel is open. It's also a good candidate to extend: ask the assistant to make the pages panel display a real cover image with a CSS 3D flip instead of a flat scale-open, to add a subtle shelf-dust parallax layer behind the books, or to convert the shelf into a horizontal-scroll gallery using the same segment-timeline technique paired with scroll-horizontal-pin.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a scroll-driven "bookshelf" animation in HTML, CSS and JavaScript using GSAP and ScrollTrigger — no React, no canvas, no WebGL.

Requirements:
- Render a horizontal row of narrow div "book spine" elements sitting on a wooden shelf illustration built from CSS gradients, each spine a different flat color and each with a vertical text label (use CSS writing-mode).
- Give each book a hidden absolutely-positioned "pages" panel anchored to its right edge, wide enough to overlap several neighboring spines, starting scaled down and transparent with its transform-origin on the left edge so it can open like a hinged cover.
- Create exactly one GSAP timeline and attach exactly one ScrollTrigger to it (start 'top top', end 'bottom bottom', scrub: true) — never create a separate timeline or ScrollTrigger per book, since giving each book its own timeline (each ending up a different effective length from default tween durations) on an identical scroll range would make them drift out of sync with each other.
- Give every book exactly one whole integer unit of that single timeline as its own segment (book i's segment starts at time i), and within it: raise that book's z-index above its neighbors, slide and rotate the spine outward from the shelf using its own transform-origin at the bottom, fade/scale open its pages panel, then close the panel, return the spine to rest, and lower its z-index back down again — every book must reset this way, including the very first one, and every tween needs an explicit duration and position rather than relying on defaults.
- The entire effect must play forward and reverse cleanly as the user scrolls down and back up, since scrub ties it directly to scroll position with no manual state to reset.
- Use a warm library color palette: dark wood browns for the shelf and background, and a distinct accent hue per book spine.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Source Code

<div class="hint">Scroll ↓ to pull books off the shelf</div>
<div class="shelf-wrap">
  <div class="shelf-stage">
    <div class="shelf-board"></div>
    <div class="books">
      <div class="book" data-title="Deep Work" style="--hue:210;--i:0">
        <span class="spine-label">Deep Work</span>
        <div class="pages">
          <h3>Deep Work</h3>
          <p>Rules for focused success in a distracted world. Cultivate the ability to concentrate without distraction on cognitively demanding tasks.</p>
        </div>
      </div>
      <div class="book" data-title="Atomic Habits" style="--hue:0;--i:1">
        <span class="spine-label">Atomic Habits</span>
        <div class="pages">
          <h3>Atomic Habits</h3>
          <p>An easy and proven way to build good habits and break bad ones. Tiny changes, remarkable results.</p>
        </div>
      </div>
      <div class="book" data-title="Sapiens" style="--hue:35;--i:2">
        <span class="spine-label">Sapiens</span>
        <div class="pages">
          <h3>Sapiens</h3>
          <p>A brief history of humankind, from foraging bands to the cognitive, agricultural and scientific revolutions.</p>
        </div>
      </div>
      <div class="book" data-title="The Design of Everyday Things" style="--hue:150;--i:3">
        <span class="spine-label">The Design of Everyday Things</span>
        <div class="pages">
          <h3>The Design of Everyday Things</h3>
          <p>Why some products satisfy customers while others frustrate them — the psychology of good design.</p>
        </div>
      </div>
      <div class="book" data-title="Thinking, Fast and Slow" style="--hue:275;--i:4">
        <span class="spine-label">Thinking, Fast and Slow</span>
        <div class="pages">
          <h3>Thinking, Fast and Slow</h3>
          <p>Two systems drive the way we think — fast, intuitive and emotional, versus slower, deliberate and logical.</p>
        </div>
      </div>
    </div>
  </div>
</div>