Bookshop Template

£10

A complete one-page site for an independent bookshop, built around a spine wall: a shelf of art-directed CSS book spines where pulling one tips the book out in 3D and opens it on the table below, cover and staff blurb on facing pages.

ScrollTrigger Lenis intermediate
6 more details
3d-transformsclick-togglescroll-revealstaggerhover-effectkeyboard-navigation
Bookshop Template - website template preview

This template reads better at your own screen size than in the frame below:

About this template

A production-ready one-pager for a neighbourhood bookshop, art-directed like the shop itself: a warm kraft-paper wall, cream book pages on it, near-black ink doing the reading, and one rubber-stamp red that only ever behaves like a rubber stamp. Every shop object is a designed piece of CSS - the book spines, the covers, the club's date-due slip - and the people are real: four warm, colour-graded photographs of the shop in use, mounted like prints on cream card with stamped captions, showing the browsing, the book club mid-discussion and Saturday storytime.

Read the full template overview

The signature is the spine wall. The shelf is a row of eight books, each spine its own tiny piece of design - different widths, heights, bindings and type treatments, like real jackets from different publishers. Pull a spine and the book tips out of the shelf in 3D, then lands open on the table below: the front cover on the left leaf, a staff-written blurb with the price on the right. Pull it again, press Escape, or choose "Put it back" and it slides home.

Around the wall the page stays in the shop's voice: staff picks that take a red STAFF PICK stamp on hover, a book club section with a library date-due slip stamped with the year's meetings, an events list with chairs-out-kettle-on copy, and a visit section that tells you to push the sticking door harder. Swap the titles, blurbs, dates and prices for your own stock and deploy the folder as static files - there is no build step.

What's included

12 items
  • Complete deployable one-page site: nav, hero, spine wall, staff picks, book club, events, visit, footer
  • Signature spine wall: eight art-directed CSS book spines with varied widths, heights, bindings and type treatments - each one a designed object, no images anywhere
  • Pull a spine and the book tips out of the shelf in 3D, then opens on the table below with its designed cover and a staff blurb on facing pages
  • Fully keyboard accessible: every spine is a real button with aria-expanded and aria-controls, Escape puts the open book back and returns focus to its spine
  • Eight designed book covers built from the same binding tokens as the spines - reskin the cloth colours and both change together
  • Staff picks take a rubber STAFF PICK stamp that thunks in on hover and focus; on touch devices the stamp is simply there
  • A book club section with a library date-due slip: the year's meetings stamped in mono, the next one stamped in red
  • Four photographs of the shop in use - the front room, the browsing tables, the club, storytime - bundled as optimised, colour-graded WebP prints on cream mounts, swappable by dropping files into assets/img
  • Five-token palette plus four book-cloth colours, all with RGB triples and a measured contrast table in the stylesheet header
  • Degrades completely: with JavaScript off, all eight books read in full below the shelf like a plain catalogue
  • Reduced motion keeps the wall fully working - books appear open instantly instead of travelling, via both the CSS media query and the script's own motion branch
  • Lenis smooth scrolling wired in and fully optional

Perfect for

5 use cases
  • Independent bookshops, secondhand and antiquarian dealers
  • Record shops, game stores and anywhere else with shelves worth browsing
  • Publishers and small presses presenting a season's list
  • Authors showcasing a backlist with real blurbs
  • Learning 3D CSS transforms driven by GSAP: a real, content-driven example of preserve-3d, rotationY and staged timelines

How it works

5 sections

Structure

One script initialises each section with a single setup and teardown path and one motion branch, keyed only on reduced motion so exactly one branch runs on every device. Every querySelector is guarded, so any section - the picks, the club, the whole shelf - can be deleted and the rest keeps working. Reveal start states are double-gated behind a has-js class and the motion media query, so a blocked CDN or a reduced-motion preference both leave a complete static page.

The spine wall

Each book on the shelf is a button styled as a spine: a 3D object with preserve-3d, a front face carrying the jacket design and a page-block face hidden along its fore edge. Activating it builds one timeline: the spine tips forward with rotationY and a translateZ lift so the pages catch the light, the table card below grows open from height zero, and the cover leaf falls flat from an 84-degree rotationY like a book slapped open. A second activation, Escape, or the Put-it-back button runs the same journey home.

State and focus

One book is open at a time: opening a spine closes the current one first, aria-expanded tracks every button, and closing from the keyboard returns focus to the spine it came from. If the table sits below the fold when a book opens - common on phones - the page scrolls it into view through Lenis when present, native scrollIntoView otherwise.

Accessibility and reduced motion

Under reduced motion the wall keeps working - it is the shop's menu, not decoration - but books appear open instantly: the reduce branch never tweens, a CSS rule gives the pulled spine a static offset, and Lenis is never created. The staff-pick stamps switch from a hover animation to simply being present, both under reduced motion and on touch devices.

Without JavaScript

The shelf renders as a wall of designed spines and all eight books read in full below it, stacked in order like a printed catalogue - covers, blurbs and prices are plain markup throughout. The only thing that disappears is the Put-it-back button, which would have nothing to put back.

Plugins ScrollTrigger
Difficulty Intermediate
Smooth scroll Lenis integration
Includes HTML + JS + CSS source, documentation, AI setup prompt, lifetime updates

Questions about this template

Do I need photographs of book covers?

No. All eight spines and their covers are art-directed CSS built from shared binding tokens, so there are no cover images to source or license, and reskinning the cloth colours changes spine and cover together. Four photographs of the shop itself are bundled and swappable by dropping files into assets/img.

Can visitors buy books through it?

No, there is no basket or checkout. It is a browsing and staff-recommendation site, which is what most independent bookshops actually want online, with events, a book club and visit details. If you need commerce, point the picks at Bookshop.org or your existing shop.

Is the spine wall usable with a keyboard?

Yes. Every spine is a real button with aria-expanded and aria-controls, and Escape puts the open book back and returns focus to the spine you came from. With JavaScript off all eight books read in full below the shelf like a plain catalogue.

Can I show more than eight books?

You can add spines, but the wall is composed as a shelf and its rhythm of varied widths, heights and bindings is part of the design. Eight is the number it is tuned for. A large catalogue wants a grid, not a shelf; this one is for a curated selection.

Would it work for something other than books?

Yes, wherever shelves are worth browsing. Record shops and game stores use the same shape directly, and publishers or authors can use it for a season's list or a backlist. The 3D pull-and-open moment is what you are buying, so the objects need spines worth pulling.

Paid template

Purchase to unlock the code.

Buying Bookshop Template opens the HTML, CSS and JavaScript source, the full documentation, an AI setup prompt for your editor, and every update we ship to it. Standard license: unlimited personal and commercial projects.

£10 Standard license, unlimited projects

Browse free effects

Documentation

Quick Start

  1. Copy the whole folder to your web host (or open index.html locally).
  2. Replace the shop name, address and hours - search index.html for "Dog-Ear", "Bakehouse Yard" and the hours in #visit.
  3. Point the contact links at your own inbox: search for hello@dogearbooks.co.uk.
  4. Swap the eight books on the shelf for your own stock (details below).

The page keeps working as you cut it down: every section (#shelf, #picks, #club, #events, #visit) can be deleted wholesale and the script skips what it can't find.

Files

Code snippet omitted: it ships with the download.

The spine wall

Each book exists twice in index.html: a spine on the shelf (a <button class="spine"> inside .shelf) and a card on the table (an <article class="book-detail"> inside .stacks). The button's aria-controls must match the card's id - that is the whole wiring.

To change a book's details (title, author, blurb, price) edit its card - everything is ordinary markup. The staff sign-offs (.page-staff) are yours to rewrite; they sell more books than the blurbs do.

To add a book of your own:

  1. Copy an existing <li class="book"> and <article class="book-detail"> pair, and give them fresh matching aria-controls/id values.
  2. Pick the spine's shape and binding with classes: width spine--w1 (thinnest) to spine--w5 (widest), height spine--h1 to spine--h4, binding spine--olive, spine--navy, spine--tobacco, spine--oxblood, spine--red, spine--ink or spine--cream.
  3. Pick the spine's type treatment: st-serif (display serif), st-mono + st-caps (stamped capitals), st-mono + st-lower (lowercase, letterspaced), st-ital (italic), st-big (larger serif for wide spines). Optional ornaments: spine-rule (double rule), spine-orn (a line of mono characters), and the jacket variants spine--band and spine--frame.
  4. Give the card's cover the matching binding (cover--olive etc.) and one ornament (orn-rules, orn-waves, orn-band, orn-frame, orn-dot).

The spine widths and heights all resolve from --sw1--sw5 and --sh1--sh4 in :root, with a compact set for phones in the 560px media query - retune the whole wall from one place.

How to drive it: click or tap a spine, or Tab to it and press Enter. Pull the same spine again, press Escape, or choose "Put it back" to shelve it. One book is open at a time, and closing from the keyboard returns focus to the spine it came from.

Per-section options

  • Hero - the pile of books is decorative (aria-hidden); each .pile-book is a bar you can retitle, recolour or delete. The round stamp is pure CSS - edit its text in place.
  • Shelf - see above. The hint line under the shelf is .stacks-hint.
  • The shop in use - the strip of two photo prints between the shelf and the picks (.snaps-section). Each print is a <figure class="snap-print">: image in a cream mount, caption stamped below. Add, remove or reorder prints freely; the strip wraps and stacks on phones.
  • Picks - three cards; add or remove <article class="pick-card"> blocks freely. The stamp is aria-hidden decoration; the card's link is what keyboard users land on, and focusing it stamps the card.
  • Club - the date-due slip is a real list (.slip-dates); add a <li> per meeting and move the slip-next class to whichever is next. The £4 and the wine are just text. The print of the club above the slip is a .snap-print like the others - delete the <figure> and the slip simply sits alone.
  • Events - one <li class="event-row"> per event: a date block, a title and description, and a mono meta line. Delete rows freely. The storytime print above the list is another .snap-print; recaption or remove it in place.
  • Visit - address, an hours <dl>, and contact links. No map by design: a neighbourhood shop's directions are better written in its own voice.

Palette

There is deliberately no palette switcher: this palette is the identity. A reskin is still a small edit, because every colour on the page resolves from five tokens plus four book-cloth colours (each with an RGB triple feeding every translucent value) at the top of assets/style.css:

Code snippet omitted: it ships with the download.

Change a hex and its triple together. The stylesheet header records the measured contrast of every pair as used - re-measure yours against those floors before shipping, especially the standing rule: the stamp red is text on --paper only (5.09:1); everywhere else it is a button fill carrying paper text, or aria-hidden stamp decoration.

Photography

The four photographs are bundled, optimised WebP derivatives, not hotlinked stock images. Each has the shop's art direction baked into the pixels: a gentle desaturation (the joy stays in), a slight gamma lift, and per-image brightness so four different sources read as one shop. Total weight is about 290KB. Every photograph sits on a cream .snap-print mount with its caption below it, so no text ever needs to survive on top of an image, and the frame behind each one is painted --kraft-deep as a fallback while it loads.

They are generated from assets/img-manifest.json, which keeps the source URL, output name, size, quality and grade for each image:

Code snippet omitted: it ships with the download.

Regenerate with:

Code snippet omitted: it ships with the download.

Swapping the photographs

Either way works:

  • Quick: drop your own files into assets/img/ using the same filenames (front-room.webp, tables.webp, club-night.webp, storytime.webp). Nothing else changes - update the alt text and captions in index.html to match what your photos show.
  • Graded: edit the src values in img-manifest.json to your own image URLs and re-run the command above. Set brightness per image - matching perceived brightness is what makes a mixed set cohere, so expect one photo to need a different number from its neighbours.

Credits

The originals are royalty-free photographs from Unsplash, used here as altered, art-directed derivatives:

Accessibility

  • Keyboard: every spine is a real <button> with aria-expanded and aria-controls; Escape shelves the open book and returns focus; focus rings are always visible and flip to paper on the dark bands.
  • Reduced motion: honoured twice - a CSS media query removes all reveal start states and gives the pulled spine a static offset, and the script's matchMedia reduce branch opens books instantly, never tweens, and never creates Lenis.
  • No JavaScript: the whole page reads. All eight books render in full below the shelf like a printed catalogue; only the Put-it-back button (which would have nothing to do) is hidden.
  • Screen readers: covers, spines' ornaments, the hero pile and the stamps are aria-hidden decoration; every book's information lives in its card's plain text; the date-due slip carries a full aria-label; every photograph has descriptive alt text and a visible caption.
  • Images: plain <img> tags with width, height and loading="lazy" - they render with or without JavaScript and reveal with the same scroll pattern as everything else.

Dependencies

Loaded from CDN at the end of index.html:

  • GSAP core, ScrollTrigger (3.15.0)
  • Lenis smooth scroll (1.3.17) - optional; delete its tag and the page falls back to native scrolling

Fonts: Eczar, Alegreya, PT Mono via Google Fonts.

Worked examples, the events and programmatic API, and the class reference ship with the download, alongside the full source.

Your cart

Your cart is empty

The Vault £99

Every effect, template and UI element: 165 today, plus everything we release next.