Snippets E-commmerce

Bootstrap 5 Product Page with Size Selector and Gallery

A single product page with a thumbnail gallery, price with discount badge, pill-style size selector and add-to-cart action.

Bootstrap 5 No jQuery Aug 2020 4.3K views

<section class="wdw-stage">
  <div class="container" style="max-width: 1040px;">
    <div class="wdw-card overflow-hidden pp">
      <div class="row g-0">
        <div class="col-md-6">
          <div class="pp-gallery h-100 p-3 p-md-4 d-flex flex-column gap-3">
            <div class="pp-main rounded-4 overflow-hidden flex-grow-1">
              <img id="ppMain" src="https://images.unsplash.com/photo-1583743814966-8936f5b7be1a?w=900&q=80&fm=jpg" alt="Black slim fit t-shirt on a hanger">
            </div>
            <div class="d-flex gap-2" role="group" aria-label="Product photos">
              <button type="button" class="pp-thumb active" data-pp-thumb data-full="https://images.unsplash.com/photo-1583743814966-8936f5b7be1a?w=900&q=80&fm=jpg" data-alt="Black slim fit t-shirt on a hanger" aria-label="Show black t-shirt" aria-pressed="true"><img src="https://images.unsplash.com/photo-1583743814966-8936f5b7be1a?w=160&h=160&fit=crop&q=70&fm=jpg" alt=""></button>
              <button type="button" class="pp-thumb" data-pp-thumb data-full="https://images.unsplash.com/photo-1521572163474-6864f9cf17ab?w=900&q=80&fm=jpg" data-alt="White slim fit t-shirt worn by a model" aria-label="Show white t-shirt" aria-pressed="false"><img src="https://images.unsplash.com/photo-1521572163474-6864f9cf17ab?w=160&h=160&fit=crop&q=70&fm=jpg" alt=""></button>
              <button type="button" class="pp-thumb" data-pp-thumb data-full="https://images.unsplash.com/photo-1523381210434-271e8be1f52b?w=900&q=80&fm=jpg" data-alt="Green t-shirts hanging on wooden hangers" aria-label="Show green t-shirts" aria-pressed="false"><img src="https://images.unsplash.com/photo-1523381210434-271e8be1f52b?w=160&h=160&fit=crop&q=70&fm=jpg" alt=""></button>
            </div>
          </div>
        </div>
        <div class="col-md-6">
          <div class="p-4 p-md-5 d-flex flex-column h-100">
            <a href="#" class="link-secondary link-underline-opacity-0 small fw-semibold d-inline-flex align-items-center gap-1 mb-4">
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 18-6-6 6-6"/></svg>Back to shop
            </a>
            <span class="wdw-eyebrow">Orianz</span>
            <h2 class="wdw-heading h2 mt-1">Men’s slim fit T-shirt</h2>
            <div class="d-flex align-items-baseline flex-wrap gap-2 mb-3">
              <span class="fs-3 fw-bold text-body-emphasis">$20</span>
              <s class="wdw-muted">$59</s>
              <span class="badge rounded-pill bg-success-subtle text-success-emphasis">Save 66%</span>
            </div>
            <p class="wdw-muted mb-4">A soft cotton tee cut for a close, modern fit. Pair it with jeans or trousers for an easy everyday look.</p>

            <fieldset class="mb-4">
              <legend class="d-flex justify-content-between align-items-center fs-6 fw-semibold mb-2">Size <span class="small fw-normal wdw-muted" id="ppSizeOut">Selected: S</span></legend>
              <div class="d-flex flex-wrap gap-2">
                <input type="radio" class="btn-check" name="ppSize" id="ppS" value="S" checked><label class="btn btn-outline-secondary pp-size rounded-pill" for="ppS">S</label>
                <input type="radio" class="btn-check" name="ppSize" id="ppM" value="M"><label class="btn btn-outline-secondary pp-size rounded-pill" for="ppM">M</label>
                <input type="radio" class="btn-check" name="ppSize" id="ppL" value="L"><label class="btn btn-outline-secondary pp-size rounded-pill" for="ppL">L</label>
                <input type="radio" class="btn-check" name="ppSize" id="ppXL" value="XL"><label class="btn btn-outline-secondary pp-size rounded-pill" for="ppXL">XL</label>
                <input type="radio" class="btn-check" name="ppSize" id="ppXXL" value="XXL"><label class="btn btn-outline-secondary pp-size rounded-pill" for="ppXXL">XXL</label>
              </div>
            </fieldset>

            <div class="d-flex gap-2 mt-auto">
              <button type="button" class="btn btn-primary rounded-pill flex-grow-1 py-2" id="ppAdd">Add to cart</button>
              <button type="button" class="btn btn-outline-secondary rounded-circle p-0 pp-fav" style="width:44px" aria-label="Save to wishlist" aria-pressed="false" id="ppFav">
                <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.8 4.6a5.5 5.5 0 0 0-7.8 0L12 5.7l-1-1.1a5.5 5.5 0 0 0-7.8 7.8l1 1.1L12 21l7.8-7.5 1-1.1a5.5 5.5 0 0 0 0-7.8z"/></svg>
              </button>
            </div>
            <p class="small wdw-muted mt-3 mb-0" id="ppMsg" role="status" aria-live="polite">Free delivery on orders over $50 · 30-day returns</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>

Built on Bootstrap 5.3.8 with plain JavaScript — no jQuery. Supports light and dark mode via data-bs-theme.