Source Code

<div class="bsc-card">
  <div class="bsc-head">
    <h3>Build your bundle</h3>
    <p>Uncheck anything you don't need — the price updates live</p>
  </div>

  <ul class="bsc-items" id="bscItems">
    <li class="bsc-item" data-price="15" data-bundle="10.50">
      <label>
        <input type="checkbox" class="bsc-check" checked />
        <span class="bsc-item-info">
          <span class="bsc-item-name">Design System Kit</span>
          <span class="bsc-item-desc">200+ components, Figma + code</span>
        </span>
      </label>
      <span class="bsc-item-price">$15</span>
    </li>
    <li class="bsc-item" data-price="22" data-bundle="15.40">
      <label>
        <input type="checkbox" class="bsc-check" checked />
        <span class="bsc-item-info">
          <span class="bsc-item-name">Icon Pack Pro</span>
          <span class="bsc-item-desc">1,200 icons, SVG + web font</span>
        </span>
      </label>
      <span class="bsc-item-price">$22</span>
    </li>
    <li class="bsc-item" data-price="18" data-bundle="12.60">
      <label>
        <input type="checkbox" class="bsc-check" checked />
        <span class="bsc-item-info">
          <span class="bsc-item-name">Illustration Set</span>
          <span class="bsc-item-desc">80 editable scenes, SVG</span>
        </span>
      </label>
      <span class="bsc-item-price">$18</span>
    </li>
  </ul>

  <div class="bsc-summary">
    <div class="bsc-row">
      <span>Individual total</span>
      <span class="bsc-strike" id="bscIndividual">$55.00</span>
    </div>
    <div class="bsc-row bsc-bundle-row">
      <span>Bundle price</span>
      <b id="bscBundle">$38.50</b>
    </div>
    <div class="bsc-savings" id="bscSavings">You save $16.50 <span id="bscSavingsPct">(30%)</span></div>
  </div>
</div>

Bundle Savings Card — Free Product Bundle Discount Widget (HTML/CSS/JS)

Bundle Savings Card · Pricing · Plain HTML, CSS & JS · Live preview

What's included

Features

Per-item dual pricing
Each product carries both its standalone and its bundle-share price.
Proportional discount
Bundle-share prices keep the savings percentage constant across selections.
Full recompute per toggle
Totals and savings are derived fresh, never adjusted in place.
Verified example math
$55.00 individual, $38.50 bundle, $16.50 (30%) savings — hand-checked.
Struck-through comparison
Individual total crossed out beside the bold bundle price.
Dimmed unchecked rows
:has() fades an unselected item without extra JavaScript.
Graceful empty state
Savings callout hides rather than showing $0.00 at zero items.
Framework-agnostic core
render() is pure and ports directly to any component's state.

About this UI Snippet

Bundle Savings Card — Real Savings Math That Updates as Items Are Toggled

Screenshot of the Bundle Savings Card snippet rendered live

Bundle pricing pages usually show one fixed "buy all 3 for $X" price and let it go stale the moment a customer only wants two of the three items. This snippet keeps the math honest: three products with real individual prices, a discounted bundle price, and a savings figure that recalculates correctly the instant an item is checked or unchecked.

Two prices per item, not one

Each product carries both data-price (its standalone price) and data-bundle (its proportional share of the discounted bundle price) as data attributes. The three products are $15, $22, and $18 individually — summing to $55 — and their bundle-share prices are $10.50, $15.40, and $12.60, which sum to exactly $38.50, the full bundle price. Because every item carries its own bundle-share price, removing an item removes *its own* discounted share too, not an arbitrary fraction of the total.

Verified 30% off, at every level

$55 individually vs. $38.50 bundled is a $16.50 saving, and $16.50 ÷ $55 = 30% — exactly the discount rate applied. Because each item's bundle price is that same item's individual price × 0.7 ($15 × 0.7 = $10.50, $22 × 0.7 = $15.40, $18 × 0.7 = $12.60), the 30% savings percentage stays mathematically consistent whether all three items are selected or only one — uncheck any two and the remaining item alone still shows the same 30% saving, because the math is proportional rather than a single fixed discount applied to a fixed set.

Full recompute on every toggle

render() filters to the currently checked items, sums their standalone prices for the individual total and their bundle-share prices for the bundle total, and derives both the dollar savings and the percentage fresh — never adjusting a previous total in place. Toggling an item off immediately drops both the crossed-out individual total and the bundle total by that item's own two prices.

A clear before/after presentation

The individual total is shown with a strikethrough next to the bold bundle price, and a separate savings callout states both the dollar amount and the percentage — the same before/after pattern as a pricing card's struck-through price, applied to a multi-item bundle instead of a single plan.

Where it fits

Pair it with an annual savings badge if the bundle also has a monthly/annual choice, follow it with a promo code input for stacking an extra discount, or place it beside a pricing card grid as an add-on bundle offer.

Customizing it

Swap in your real products and prices — keep each item's bundle-share price proportional to its individual price if you want the savings percentage to stay constant across selections, or make it non-proportional if certain items should carry a bigger discount than others.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You don't have to re-derive the proportional-discount math by hand. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly why storing a separate bundle-share price per item (rather than dividing one shared discount evenly, or applying it only to the full set) is what keeps the savings percentage constant no matter which items are checked, and how render() derives the individual total, bundle total, dollar savings, and percentage fresh from the currently selected items on every toggle. The same assistant can help you verify the arithmetic — ask it to confirm $15 + $22 + $18 = $55.00, that the three bundle-share prices sum to $38.50, and that $16.50 divided by $55.00 is exactly 30% — or extend the widget: ask how to let a non-proportional discount apply (where some items keep a bigger share of the total discount than others), how to enforce a minimum-two-items rule before showing bundle pricing at all, or how to animate the totals when they change. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a "bundle savings card" in plain HTML, CSS, and JavaScript with no framework or library.

Requirements:
- List exactly three products, each with a checkbox (checked by default), a name, a short description, its own standalone individual price, and its own separate bundle-share price stored as data attributes on that product's element.
- Choose the three individual prices and a single overall bundle discount percentage, then compute each item's bundle-share price as individual price × (1 − discount) so that summing all three bundle-share prices equals the advertised full bundle price exactly (verify this arithmetic before finalizing your example numbers).
- Show an "individual total" (the sum of standalone prices for checked items only, displayed with a strikethrough) and a "bundle price" (the sum of bundle-share prices for checked items only, displayed prominently) plus a savings callout stating both the dollar amount saved and the percentage saved.
- On every checkbox change, recompute both totals and the savings figures from scratch by filtering to the currently checked items and summing their two respective prices — do not increment/decrement a running total in place.
- Confirm in your own testing that the savings percentage stays the same (matching your chosen discount rate) regardless of which subset of items is checked, since each item's bundle-share price is a consistent proportion of its individual price.
- Add a fallback: if every item is unchecked, hide the savings callout entirely rather than showing a "$0.00 (0%)" line, and visually de-emphasize (e.g. dim) any unchecked item's row.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSAll three items are checked; totals show $55.00 vs. $38.50.
  2. 2
    Uncheck an itemBoth totals drop by that item's own two prices.
  3. 3
    Read the savings line"You save $16.50 (30%)" recalculates for whatever is selected.
  4. 4
    Verify the math$55.00 − $38.50 = $16.50, and $16.50 / $55.00 = 30%.
  5. 5
    Uncheck everythingThe savings callout hides rather than showing a $0.00 saving.
  6. 6
    Wire up real productsSet each item's data-price and proportional data-bundle price.

Real-world uses

Common Use Cases

Digital product bundles
Sell design kits, templates, or courses as a discounted set.
SaaS add-on bundles
Pair with a pricing card offering bundled add-ons.
E-commerce cross-sells
Bundle complementary physical products with real per-item math.
Course/curriculum bundles
Let a learner opt out of a module and see the price adjust.
Agency service packages
Bundle deliverables with a transparent per-item discount.
Promo stacking
Combine with a promo code input for an extra discount layer.

Got questions?

Frequently Asked Questions

Each item stores its own bundle-share price (its individual price × 0.7) rather than the page applying one discount to whatever total happens to be selected. Design System Kit is $15 individually and $10.50 in the bundle, Icon Pack Pro is $22 and $15.40, and Illustration Set is $18 and $12.60 — those three bundle-share prices sum to exactly $38.50, the full bundle price.

Because every item's bundle-share price is exactly 70% of its individual price, the 30% discount is proportional rather than a single fixed amount spread across whatever is selected. Whether all three items are checked or only one, that item's individual price minus its bundle-share price is always 30% of its individual price, so the percentage line stays consistent.

render() detects zero selected items and hides the entire savings callout rather than showing a "You save $0.00 (0%)" line, which would read as broken. The individual and bundle totals both show $0.00 in that state.

The individual total sums each selected item's standalone price: $15 + $22 + $18 = $55.00. The bundle total sums each item's bundle-share price: $10.50 + $15.40 + $12.60 = $38.50. Savings is the difference, $55.00 − $38.50 = $16.50, and the percentage is $16.50 divided by $55.00, which is exactly 30%.

Model items as an array of {name, description, price, bundlePrice, selected} objects. Derive individualTotal and bundleTotal with a memoized reduce over the selected items, and savings/savingsPct as further derived values — the arithmetic is pure and needs no DOM access at all.