Quick Start
- Copy the whole folder to your web host (or open
index.htmllocally). - Replace the shop name, address and hours - search
index.htmlfor "Dog-Ear", "Bakehouse Yard" and the hours in#visit. - Point the contact links at your own inbox: search for
hello@dogearbooks.co.uk. - 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:
- Copy an existing
<li class="book">and<article class="book-detail">pair, and give them fresh matchingaria-controls/idvalues. - Pick the spine's shape and binding with classes: width
spine--w1(thinnest) tospine--w5(widest), heightspine--h1tospine--h4, bindingspine--olive,spine--navy,spine--tobacco,spine--oxblood,spine--red,spine--inkorspine--cream. - 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 variantsspine--bandandspine--frame. - Give the card's cover the matching binding (
cover--oliveetc.) 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-bookis 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 isaria-hiddendecoration; 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 theslip-nextclass to whichever is next. The £4 and the wine are just text. The print of the club above the slip is a.snap-printlike 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 thealttext and captions inindex.htmlto match what your photos show. - Graded: edit the
srcvalues inimg-manifest.jsonto your own image URLs and re-run the command above. Setbrightnessper 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:
- The front room - https://unsplash.com/photos/tv8PIPPY3rQ
- The browsing tables - https://unsplash.com/photos/UANi9GAiS0Q
- The club - https://unsplash.com/photos/M5DpQOpZ8aA
- Storytime - https://unsplash.com/photos/Wv4_uJ0zlTw
Accessibility
- Keyboard: every spine is a real
<button>witharia-expandedandaria-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-hiddendecoration; every book's information lives in its card's plain text; the date-due slip carries a fullaria-label; every photograph has descriptivealttext and a visible caption. - Images: plain
<img>tags withwidth,heightandloading="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.