webdevpuneet.com

Sticky Add to Cart Bar — Free HTML CSS JS E-Commerce Snippet

Sticky Add to Cart Bar · Navigation · Plain HTML, CSS & JS · Live preview

CategoryNavigation

Copy & paste

Source Code

<div class="satc-page">
  <div class="satc-product">
    <div class="satc-gallery" aria-hidden="true">
      <svg viewBox="0 0 200 200" width="100%" height="100%"><rect width="200" height="200" rx="16" fill="#eef2ff"/><circle cx="100" cy="85" r="42" fill="#c7d2fe"/><rect x="55" y="130" width="90" height="48" rx="10" fill="#a5b4fc"/></svg>
    </div>
    <div class="satc-info">
      <p class="satc-brand">AUDIOFORM</p>
      <h1>Wireless Over-Ear Headphones</h1>
      <div class="satc-rating">★★★★★ <span>(1,204 reviews)</span></div>
      <p class="satc-price">$179.00 <span class="satc-was">$229.00</span></p>
      <p class="satc-desc">Active noise cancellation, 40-hour battery life, and memory-foam ear cushions. Free returns within 30 days.</p>
      <div class="satc-buy" id="satcMainBuy">
        <select id="satcMainColor" class="satc-select">
          <option>Midnight Black</option>
          <option>Cloud White</option>
          <option>Sage Green</option>
        </select>
        <button class="satc-add-btn" id="satcMainAddBtn">Add to Cart — $179.00</button>
      </div>
    </div>
  </div>

  <div class="satc-filler">
    <h2>Product details</h2>
    <p>Scroll down to see the sticky bar appear once the main "Add to Cart" button scrolls out of view. Scroll back up and it hides again.</p>
    <p>Bluetooth 5.3 · USB-C fast charging · Multipoint pairing · Foldable travel design · Built-in mic for calls.</p>
    <p>Keep scrolling for more filler content simulating a real product page layout below the fold.</p>
    <p>The sticky bar mirrors the selected color and price so the purchase context never gets lost while browsing.</p>
    <p>This pattern is common on mobile commerce sites where the primary CTA would otherwise scroll off screen.</p>
  </div>

  <div class="satc-bar" id="satcBar" hidden>
    <div class="satc-bar-info">
      <span class="satc-bar-thumb" aria-hidden="true"></span>
      <div>
        <p class="satc-bar-name">Wireless Over-Ear Headphones</p>
        <p class="satc-bar-color" id="satcBarColor">Midnight Black</p>
      </div>
    </div>
    <div class="satc-bar-right">
      <span class="satc-bar-price">$179.00</span>
      <button class="satc-add-btn" id="satcBarAddBtn">Add to Cart</button>
    </div>
  </div>
  <div class="satc-toast" id="satcToast" hidden>Added to cart</div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

IntersectionObserver visibility toggle
Detects when the main buy button leaves the viewport without scroll-event layout thrashing.
getBoundingClientRect fallback
Falls back to a scroll listener in environments without IntersectionObserver support.
Synced variant state
The sticky bar mirrors the color selection from the main form via a single change listener.
Slide-up entrance animation
A CSS keyframe animation gives the bar's appearance a deliberate, non-jarring entrance.
Shared toast confirmation
Both add-to-cart buttons trigger the same debounced toast so rapid clicks don't stack.
Responsive product layout
The gallery and info columns collapse to a single column on narrow viewports.
Truncated product name
text-overflow: ellipsis keeps long product names from breaking the bar's layout.
Zero dependencies
Pure HTML, CSS, and vanilla JavaScript — no scroll library required.

About this UI Snippet

Sticky Add to Cart Bar — IntersectionObserver-Driven Purchase Bar

Screenshot of the Sticky Add to Cart Bar snippet rendered live

Once a shopper scrolls past the main "Add to Cart" button, the purchase action disappears from view — on long product pages this is a real source of lost conversions. A sticky add-to-cart bar solves it by re-surfacing a condensed version of the same action at the bottom of the screen exactly when the original button leaves the viewport, and hiding again once it's back in view.

Detecting visibility with IntersectionObserver, not scroll math

Rather than computing getBoundingClientRect() on every scroll event, the snippet observes the main buy block directly: new IntersectionObserver(entries => { entries.forEach(entry => entry.isIntersecting ? hideBar() : showBar()) }). The browser's compositor tracks intersection changes off the main thread, so the bar's visibility toggles without a single scroll listener running expensive layout reads on every frame. A getBoundingClientRect() fallback is included for the rare environment without IntersectionObserver support.

Mirroring state, not duplicating logic

The sticky bar doesn't own its own copy of the product state — it reflects the primary form's current selection. The color <select>'s change event updates barColor.textContent directly, so switching variants above the fold instantly updates what the bar shows below, keeping a single source of truth instead of two independently-tracked selections that could drift out of sync.

A slide-up entrance, not a hard cut

@keyframes satcSlideUp animates transform: translateY(100%) to translateY(0) with a fade, so the bar's appearance reads as a deliberate UI response to scrolling rather than a layout-shifting pop-in. Because the animation only runs once when hidden is removed (not on every scroll tick), it stays cheap even on long pages.

Shared add-to-cart handler with a lightweight toast

Both the main button and the bar's button call the same addToCart() function, which shows a toast and clears/resets its own setTimeout so rapid repeated clicks don't stack multiple toasts on top of each other — each click restarts the same 1.6-second timer instead of scheduling a new one.

Customizing it

Swap the IntersectionObserver's target for your real buy-box container, wire addToCart() to your cart API instead of a toast, or add a slide-in product thumbnail carousel to the bar for multi-image products.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA product page renders with a main "Add to Cart" button near the top.
  2. 2
    Scroll downOnce the main button scrolls out of view, a sticky bar slides up from the bottom mirroring the price and variant.
  3. 3
    Change the color selectorSwitching the variant above updates the sticky bar's label to match.
  4. 4
    Click either Add to Cart buttonA toast confirmation appears near the bottom of the screen.
  5. 5
    Scroll back upThe sticky bar disappears once the main button is back in view.
  6. 6
    Wire up your cart APIReplace addToCart() with a real fetch() call to your cart endpoint, keeping the toast as the success confirmation.

Real-world uses

Common Use Cases

Product page buy bars
Keep the purchase action reachable on long pages, appearing when the main Add to Cart button scrolls out of view.
Mobile commerce
Help small screens where the buy button disappears quickly, with a slide-up keyframe animation for the bar's entrance.
Ticketing and event pages
Keep a Get tickets action visible, using IntersectionObserver with a getBoundingClientRect fallback where it is unavailable.
Course and subscription pages
Keep an Enroll or Subscribe call to action visible on course and subscription pages as the visitor reads through the curriculum details.
Listings with synced details
Mirror the selected variant, price or shipping details in a condensed bar for real estate or marketplace pages.
Related: Accordion — Native <details>/<summary> (No JavaScript)
See the Accordion — Native <details>/<summary> (No JavaScript) for a related misc pattern worth pairing with this one.
Related: Timezone Meeting Overlap Finder
See the Timezone Meeting Overlap Finder for a related misc pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

IntersectionObserver lets the browser's own compositor track when an element enters or leaves the viewport, running off the main thread and only firing callbacks on actual state changes. A scroll listener, by contrast, fires dozens of times per second and typically needs getBoundingClientRect() calls that force synchronous layout recalculation — much more expensive at scale.

The <select> element's change event listener directly updates barColor.textContent whenever the shopper picks a different variant above the fold. There's no separate state object — the bar simply reads and mirrors the DOM value at the moment of selection, so the two can never drift out of sync.

Each click calls addToCart(), which first clears any pending toastTimer with clearTimeout() before scheduling a new one. This means rapid clicks reset the same toast's dismiss timer instead of stacking multiple toast elements on top of each other.

Yes — the script checks 'IntersectionObserver' in window and falls back to a scroll listener that manually checks mainBuy.getBoundingClientRect().bottom against 0. This fallback only runs in the rare case the API is unavailable, so the fast path is used whenever possible.

Replace the body of addToCart() with a fetch() POST to your cart endpoint, passing the selected product ID, variant, and quantity. Keep calling the toast display code on a successful response, and add error handling (e.g. a red toast variant) for failed requests.

Yes. While the Sticky Add to Cart Bar snippet gives you one pattern to copy, the free Responsive Navbar Builder at webdevpuneet.com/navbar-builder/ designs a whole navigation bar: logo, links and dropdown menus, a mobile hamburger menu (dropdown panel, slide-in drawer or full screen) and a scroll effect (sticky, shrink, hide on scroll or transparent). It has six presets, a live preview that runs the real code, and exports HTML + CSS + vanilla JS, React, Tailwind, Vue 3 or Angular — or you can click Fork & Edit to keep editing it in My Code.