Templates

Independent Bookstore

A warm neighborhood bookstore page with staff picks, readings, hours, and a hold request form.

Retail HTML CSS Free
Live preview View code

Use this free Pebble Books page as a starting point for a bookstore or small retail shop. The layout is a single HTML file with CSS variables for color, staff-pick cards, and a demo hold form you can connect later.

What's included

  • Sticky navigation with a mobile menu
  • Hero with open hours and shelf placeholder
  • Staff-pick cards with CSS cover placeholders
  • Readings, address, and hours
  • Accessible hold form that does not pretend to submit to a backend

Responsive support

This template is built as a full page and adapts to desktop, tablet, and mobile widths. Use the live preview to check each viewport before you copy the code.

Template source

Copy the HTML below into your project. A short README in the template folder explains colors, content, and placeholder visuals.

<!--
  Pebble Books — Independent bookstore landing page
  See README.md in this folder for usage, colors, content, and placeholder visuals.
-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Pebble Books — Independent bookstore</title>
  <meta name="description" content="Pebble Books is a neighborhood bookstore with staff picks, evening readings, and a quiet table by the window.">
  <style>
    :root {
      --bg: #f4efe4;
      --bg-strong: #e8dfcf;
      --ink: #1c1914;
      --muted: #5f5648;
      --card: #fffaf1;
      --line: #d8cdb8;
      --accent: #9a3412;
      --accent-dark: #7c2d12;
      --spine: #3f4f3a;
      --radius: 14px;
      --font: "Iowan Old Style", "Palatino Linotype", Palatino, "Times New Roman", serif;
      --ui: "Avenir Next", "Segoe UI", sans-serif;
      --max: 1080px;
    }
    * { box-sizing: border-box; }
    html { scroll-behavior: smooth; }
    body {
      margin: 0;
      color: var(--ink);
      background: var(--bg);
      font-family: var(--ui);
      line-height: 1.55;
    }
    a { color: inherit; }
    button, input, textarea, select { font: inherit; color: inherit; }
    .skip-link {
      position: absolute;
      left: 1rem;
      top: -40px;
      background: var(--ink);
      color: #fff;
      padding: 0.5rem 0.75rem;
      z-index: 20;
    }
    .skip-link:focus { top: 1rem; }
    .wrap { width: min(var(--max), calc(100% - 2rem)); margin: 0 auto; }
    .site-header {
      position: sticky;
      top: 0;
      z-index: 10;
      background: rgba(244, 239, 228, 0.94);
      backdrop-filter: blur(16px);
      border-bottom: 1px solid var(--line);
    }
    .nav {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 1rem;
      min-height: 76px;
    }
    .logo {
      text-decoration: none;
      font-family: var(--font);
      font-size: 1.4rem;
      letter-spacing: -0.03em;
    }
    .nav-links { display: flex; align-items: center; gap: 1.2rem; }
    .nav-links a:not(.btn) { text-decoration: none; color: var(--muted); }
    .nav-links a:not(.btn):hover { color: var(--ink); }
    .nav-links .btn-primary { color: #fff; }
    .nav-toggle {
      display: none;
      border: 1px solid var(--line);
      background: var(--card);
      border-radius: 8px;
      padding: 0.45rem 0.7rem;
    }
    .btn {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border: 0;
      border-radius: 999px;
      padding: 0.8rem 1.2rem;
      text-decoration: none;
      font-weight: 600;
      cursor: pointer;
    }
    .btn-primary { background: var(--accent); color: #fff; }
    .btn-primary:hover { background: var(--accent-dark); color: #fff; }
    .btn-ghost { background: transparent; border: 1px solid var(--ink); }
    .hero {
      padding: 4.2rem 0 3rem;
      display: grid;
      grid-template-columns: 1.15fr 0.85fr;
      gap: 2.4rem;
      align-items: center;
    }
    .eyebrow {
      color: var(--spine);
      font-weight: 700;
      letter-spacing: 0.1em;
      text-transform: uppercase;
      font-size: 0.76rem;
      margin: 0 0 0.8rem;
    }
    h1, h2, h3 { font-family: var(--font); letter-spacing: -0.03em; line-height: 1.15; }
    h1 { font-size: clamp(2.5rem, 5vw, 4.1rem); margin: 0 0 1rem; }
    h2 { font-size: clamp(1.8rem, 3vw, 2.5rem); margin: 0 0 0.7rem; }
    h3 { font-size: 1.2rem; margin: 0 0 0.35rem; }
    .lede { font-size: 1.12rem; color: var(--muted); max-width: 36rem; }
    .hero-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.6rem; }
    .shelf {
      background: var(--card);
      border: 1px solid var(--line);
      border-radius: 22px;
      padding: 1.3rem;
      box-shadow: 0 20px 44px rgba(28, 25, 20, 0.08);
    }
    .spines {
      display: grid;
      grid-template-columns: repeat(6, 1fr);
      gap: 0.45rem;
      height: 180px;
      margin-bottom: 1rem;
    }
    .spines span {
      border-radius: 3px 3px 0 0;
      align-self: end;
    }
    .spines span:nth-child(1) { height: 88%; background: var(--spine); }
    .spines span:nth-child(2) { height: 72%; background: var(--accent); }
    .spines span:nth-child(3) { height: 96%; background: #1c1914; }
    .spines span:nth-child(4) { height: 64%; background: #8a7a5c; }
    .spines span:nth-child(5) { height: 80%; background: #4a5d6a; }
    .spines span:nth-child(6) { height: 90%; background: #7a3b2e; }
    section { padding: 3.4rem 0; }
    .picks, .events, .visit-grid {
      display: grid;
      gap: 1rem;
      margin-top: 1.5rem;
    }
    .picks { grid-template-columns: repeat(3, 1fr); }
    .events, .visit-grid { grid-template-columns: 1fr 1fr; }
    .card, .panel {
      background: var(--card);
      border: 1px solid var(--line);
      border-radius: var(--radius);
      padding: 1.2rem;
    }
    .cover {
      height: 140px;
      border-radius: 8px;
      margin-bottom: 1rem;
    }
    .cover.a { background: linear-gradient(160deg, #3f4f3a, #e8dfcf); }
    .cover.b { background: linear-gradient(160deg, #9a3412, #f4efe4); }
    .cover.c { background: linear-gradient(160deg, #1c1914, #8a7a5c); }
    .when { color: var(--spine); font-weight: 700; font-size: 0.9rem; }
    form { display: grid; gap: 0.85rem; }
    label { font-weight: 600; font-size: 0.92rem; }
    input, select, textarea {
      width: 100%;
      background: var(--bg);
      border: 1px solid var(--line);
      border-radius: 10px;
      padding: 0.75rem 0.9rem;
    }
    .form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.85rem; }
    .form-status { min-height: 1.4em; color: var(--muted); }
    .site-footer {
      border-top: 1px solid var(--line);
      padding: 2.4rem 0;
      color: var(--muted);
    }
    .footer-grid {
      display: grid;
      grid-template-columns: 1.4fr 1fr 1fr;
      gap: 1.5rem;
    }
    :focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
    @media (max-width: 860px) {
      .hero, .picks, .events, .visit-grid, .footer-grid, .form-row { grid-template-columns: 1fr; }
      .nav-toggle { display: inline-flex; }
      .nav-links {
        display: none;
        position: absolute;
        left: 1rem;
        right: 1rem;
        top: 76px;
        background: var(--card);
        border: 1px solid var(--line);
        border-radius: 12px;
        padding: 1rem;
        flex-direction: column;
        align-items: flex-start;
      }
      .nav-links.is-open { display: flex; }
    }
  </style>
</head>
<body>
  <a class="skip-link" href="#main">Skip to content</a>
  <header class="site-header">
    <div class="wrap nav">
      <a class="logo" href="#top">Pebble Books</a>
      <button class="nav-toggle" type="button" aria-expanded="false" aria-controls="site-nav">Menu</button>
      <nav id="site-nav" class="nav-links" aria-label="Primary">
        <a href="#picks">Staff picks</a>
        <a href="#events">Events</a>
        <a href="#visit">Visit</a>
        <a class="btn btn-primary" href="#hold">Request a hold</a>
      </nav>
    </div>
  </header>

  <main id="main">
    <section class="wrap hero" id="top">
      <div>
        <p class="eyebrow">Independent bookstore · Portland</p>
        <h1>A small shop for books you will actually finish.</h1>
        <p class="lede">Pebble Books keeps a short shelf: fiction, essays, and a few cookbooks. Staff write the cards. The window table is for reading, not laptops.</p>
        <div class="hero-actions">
          <a class="btn btn-primary" href="#picks">See this week’s picks</a>
          <a class="btn btn-ghost" href="#events">Upcoming readings</a>
        </div>
      </div>
      <aside class="shelf">
        <div class="spines" aria-hidden="true">
          <span></span><span></span><span></span><span></span><span></span><span></span>
        </div>
        <p class="eyebrow">Open today</p>
        <p>Tuesday–Sunday, 10–7. Monday restock.</p>
      </aside>
    </section>

    <section class="wrap" id="picks" aria-labelledby="picks-heading">
      <h2 id="picks-heading">Staff picks</h2>
      <p class="lede">Three titles we are handing to people this week. Replace the covers and blurbs with your own cards.</p>
      <div class="picks">
        <article class="card">
          <div class="cover a" aria-hidden="true"></div>
          <h3>The Quiet Inventory</h3>
          <p>A novel about a shop that only sells books people return. Hand-sold by Mara.</p>
        </article>
        <article class="card">
          <div class="cover b" aria-hidden="true"></div>
          <h3>Bread, Salt, and Maps</h3>
          <p>Essays on cooking for one. The kind of book you leave on the counter.</p>
        </article>
        <article class="card">
          <div class="cover c" aria-hidden="true"></div>
          <h3>Night Shift Geology</h3>
          <p>Poems from a museum night guard. Short enough to finish on the bus.</p>
        </article>
      </div>
    </section>

    <section class="wrap" id="events" aria-labelledby="events-heading">
      <h2 id="events-heading">Readings at the window</h2>
      <div class="events">
        <article class="panel">
          <p class="when">Thu 7 Sep · 19:00</p>
          <h3>Mara Chen reads new fiction</h3>
          <p>Twenty minutes, then questions. Chairs are limited; standing is allowed if you buy a book.</p>
        </article>
        <article class="panel">
          <p class="when">Sat 13 Sep · 11:00</p>
          <h3>Kids’ hour: maps and monsters</h3>
          <p>Picture books on the rug. Grown-ups can sit at the window with coffee from next door.</p>
        </article>
      </div>
    </section>

    <section class="wrap" id="visit" aria-labelledby="visit-heading">
      <h2 id="visit-heading">Find the shop</h2>
      <div class="visit-grid">
        <article class="panel">
          <h3>Pebble Books</h3>
          <p>88 Splitter Lane<br>Portland, OR 97214</p>
          <p>Two blocks from the river. Bike parking on the side wall.</p>
        </article>
        <article class="panel">
          <h3>Hours</h3>
          <p>Tue–Sun 10–19<br>Monday closed for restock</p>
          <p>Orders can be held at the desk if you write ahead.</p>
        </article>
      </div>
    </section>

    <section class="wrap" id="hold" aria-labelledby="hold-heading">
      <h2 id="hold-heading">Request a hold</h2>
      <p class="lede">This demo form does not place a real hold. Connect it to email or your shop system before you publish.</p>
      <form id="hold-form" class="panel" style="margin-top: 1.2rem;">
        <div class="form-row">
          <div>
            <label for="name">Name</label>
            <input id="name" name="name" type="text" autocomplete="name" required>
          </div>
          <div>
            <label for="email">Email</label>
            <input id="email" name="email" type="email" autocomplete="email" required>
          </div>
        </div>
        <div>
          <label for="title">Book title or author</label>
          <input id="title" name="title" type="text" required>
        </div>
        <div>
          <label for="note">Note</label>
          <textarea id="note" name="note" rows="3" placeholder="Edition, pickup day, or a gift wrap request."></textarea>
        </div>
        <button class="btn btn-primary" type="submit">Ask the desk</button>
        <p class="form-status" id="hold-status" role="status" aria-live="polite"></p>
      </form>
    </section>
  </main>

  <footer class="site-footer">
    <div class="wrap footer-grid">
      <div>
        <a class="logo" href="#top">Pebble Books</a>
        <p>A sample bookstore page from Designyff. Replace the name, picks, and address before you ship.</p>
      </div>
      <div>
        <h3>Visit</h3>
        <p>88 Splitter Lane<br>Portland, OR 97214</p>
      </div>
      <div>
        <h3>Shop</h3>
        <p><a href="#picks">Staff picks</a></p>
        <p><a href="#hold">Holds</a></p>
      </div>
    </div>
    <div class="wrap" style="margin-top: 1.5rem;">
      <p>© <span id="year"></span> Pebble Books. Template by Designyff. Sample address only.</p>
    </div>
  </footer>

  <script>
    document.getElementById('year').textContent = new Date().getFullYear();
    const toggle = document.querySelector('.nav-toggle');
    const nav = document.getElementById('site-nav');
    toggle.addEventListener('click', () => {
      const open = toggle.getAttribute('aria-expanded') === 'true';
      toggle.setAttribute('aria-expanded', String(!open));
      nav.classList.toggle('is-open', !open);
    });
    const form = document.getElementById('hold-form');
    const status = document.getElementById('hold-status');
    form.addEventListener('submit', (event) => {
      event.preventDefault();
      status.textContent = 'This demo form does not send data. Connect it to your email or shop system.';
      form.reset();
    });
  </script>
</body>
</html>
Nocturne Gallery preview
Gallery HTML CSS JavaScript Premium $9

Nocturne Gallery

A contemporary gallery page with a pinned white-cube hero, a horizontal hanging reel, and a collector viewing form.

Meridian Private Office preview
Finance HTML CSS JavaScript Premium $9

Meridian Private Office

A quiet private-wealth page on paper and navy, with household figures, a mandate reel, and a referral introduction form.

Real Estate Landing Page preview
Real estate HTML CSS Free

Real Estate Landing Page

A residential brokerage page with featured homes, neighborhood notes, and a viewing request form.

Occasional updates with new UI components, page templates, and design resources.

Components and templates may be used in personal, commercial, and client projects. Do not redistribute or resell the original source. Terms of Service

Designyff © 2026 | Free UI components and page templates | Powered by  Tacko