webdevpuneet.com

Buy Now Pay Later Selector — Free BNPL Checkout UI

Buy Now Pay Later Selector · Forms · Plain HTML, CSS & JS · Live preview

CategoryForms

Copy & paste

Source Code

<form class="bnp-card" id="bnpForm">
  <h3>Choose how to pay</h3>
  <p class="bnp-sub">Order total: <b>$198.00</b></p>

  <div class="bnp-group" role="radiogroup" aria-label="Payment method">
    <label class="bnp-option">
      <input type="radio" name="pay-method" value="full" checked>
      <span class="bnp-box">
        <span class="bnp-top">
          <span class="bnp-name">Pay in full</span>
          <span class="bnp-price">$198.00</span>
        </span>
        <span class="bnp-desc">Charged today to your card. No interest, no fees.</span>
        <span class="bnp-tick" aria-hidden="true"></span>
      </span>
    </label>

    <label class="bnp-option">
      <input type="radio" name="pay-method" value="bnpl">
      <span class="bnp-box">
        <span class="bnp-flag">0% interest</span>
        <span class="bnp-top">
          <span class="bnp-name">Pay in 4</span>
          <span class="bnp-price">$49.50<small>&times;4</small></span>
        </span>
        <span class="bnp-desc">Split into 4 interest-free payments, every 2 weeks.</span>
        <span class="bnp-tick" aria-hidden="true"></span>
      </span>
    </label>
  </div>

  <div class="bnp-schedule" id="bnpSchedule" hidden>
    <span class="bnp-schedule-label">Payment schedule</span>
    <ul class="bnp-installments" id="bnpInstallments"></ul>
  </div>

  <button type="submit" class="bnp-submit" id="bnpSubmit">Continue &middot; Pay in full today</button>
</form>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), 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

Native radio cards
Real radio inputs under styled cards give keyboard nav and form submission for free.
Computed installment schedule
Amounts and dates derive from the order total and today's date, never hardcoded.
Reveal, not just relabel
Selecting BNPL opens a dedicated schedule panel instead of a vague badge change.
"Due at checkout" clarity
The first installment is explicitly marked so today's charge is unambiguous.
Commitment-stating CTA
The submit button's label always names the exact payment plan about to be confirmed.
0% interest flag
A pinned badge reduces the perceived risk of the installment option.
Accessible disclosure
The schedule panel uses the hidden attribute, kept in sync with the real selection.
Tabular installment amounts
Monospaced numerals keep the schedule list visually steady.

About this UI Snippet

Buy Now Pay Later Selector — Radio Cards With a Live Installment Schedule

Screenshot of the Buy Now Pay Later Selector snippet rendered live

Offering "Pay in 4" alongside a full-payment option is now standard at checkout, and the interface challenge is showing the installment breakdown clearly the moment a shopper considers it — not burying it behind a tooltip. This snippet builds that BNPL selector as two radio cards, with the second revealing a dated payment schedule inline, a natural pairing with checkout form or multi-step checkout.

Two radio cards, one real form

Like this library's radio card group, each payment method is a <label> wrapping a visually hidden native radio and a styled .bnp-box — so the selection is keyboard-navigable and form-submittable by construction, with the checked-state styling handled entirely by the :checked sibling selector in CSS. No custom click-state JavaScript is needed for the core selection behavior.

The schedule is computed, not hardcoded

buildInstallments() divides the order total by four and generates four due dates two weeks apart starting today, formatting each with toLocaleDateString. Every installment amount and date is derived from ORDER_TOTAL and the current date rather than typed out — change the order total and the whole schedule (and the per-installment amount) recalculates correctly.

Reveal, don't just relabel

Selecting "Pay in 4" doesn't just highlight the card — it reveals a dedicated schedule panel (toggled via the hidden attribute) listing all four payments with their due dates, and marks the first as "Due at checkout" so it's unambiguous which payment happens right now versus later. This answers the two questions a shopper actually has before committing: how much, and when.

The submit button always states the real commitment

The primary button's label changes with the selection — "Continue · Pay in full today" versus "Continue · Pay in 4" — so the call-to-action itself confirms what's about to happen, rather than a generic "Continue" that leaves the payment plan ambiguous until the next screen.

Wiring it to a real BNPL provider

Replace the schedule computation with the actual plan returned by your BNPL provider's API (Klarna, Affirm, Afterpay all return an installment schedule with real dates and any provider fees), and gate the "Pay in 4" option behind that provider's approval check — show a brief loading state while the eligibility check runs, and fall back to "Pay in full" if the shopper isn't approved.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSTwo payment options render with "Pay in full" selected by default.
  2. 2
    Select "Pay in 4"A schedule panel reveals four installments, computed from the order total and today's date.
  3. 3
    Watch the submit buttonIts label updates to state exactly what will happen — pay in full today, or pay in 4.
  4. 4
    Switch back to full paymentThe schedule panel hides again and the button label reverts.
  5. 5
    Change the order totalUpdate ORDER_TOTAL — the installment amounts recompute automatically.
  6. 6
    Connect a real BNPL providerReplace buildInstallments() with the schedule your provider's API returns, gated by an eligibility check.

Real-world uses

Common Use Cases

E-commerce checkout options
Offer Pay in 4 beside full payment, with a revealed schedule panel instead of a hidden tooltip, next to a promo code input.
Multi-step payment methods
Slot in as the payment step of a multi-step checkout, using native radio inputs for keyboard navigation and form submission.
Subscription upgrades
Let users split a large annual upgrade into instalments, with amounts and dates computed from the order total and today's date.
High-ticket purchases
Show instalment framing for electronics or furniture, marking the first payment as due at checkout so today's charge is clear.
Order summary pairing
Place beside an order summary on mobile, where stacked cards work well, and A/B test which option is pre-selected.
Related: Cascading Select
See the Cascading Select for a related forms pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

buildInstallments() divides ORDER_TOTAL by four for the per-installment amount, then generates four due dates spaced two weeks apart starting from today's date, formatting each with toLocaleDateString. Nothing about the schedule is hardcoded — change the order total and every installment amount recalculates, and the dates are always relative to whenever the page loads.

A shopper deciding on BNPL needs to see exactly how much and when each payment happens before committing — a relabeled badge doesn't answer that. The revealed schedule panel lists all four dated installments and explicitly marks the first as "Due at checkout" so there's no ambiguity about what charges immediately versus later.

Most providers return an actual installment plan (with real due dates and any provider fees) from an eligibility or quote API call made at checkout. Replace buildInstallments()'s local computation with that response, and gate showing the "Pay in 4" option behind the provider's approval check — show a brief loading state while checking eligibility, and hide or disable the option if the shopper isn't approved.

A generic "Continue" button leaves the actual payment commitment ambiguous until the next screen. Updating the label to state the exact plan — "Pay in full today" or "Pay in 4" — means the call-to-action itself confirms what's about to happen, reducing surprise (and support tickets) at the moment of commitment.

Hold the selected payment method in component state (radios still bind via value/checked or v-model), and derive the schedule panel's visibility and the submit button's label from that state. Compute the installment list in a memoized function fed by orderTotal, mirroring what buildInstallments() does directly to the DOM here.