Skip to content
  • No data uploaded
  • Instant results

Bootstrap 5 Currency Pricing Table for Vanilla JS

A production-ready minimal currency pricing table: a dynamic pricing section that detects the visitor’s currency, shows purchasing-power-adjusted regional prices and lets users switch between USD, EUR, GBP, INR and JPY. Pick your brand color, toggle dark mode and corner radius — the live preview and the Vanilla JS code update instantly in your browser.

Live component editor

Library
Framework
Style
Theme
Corner radius
Live preview
<!-- Requires Bootstrap 5.3 CSS + theme.css:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="theme.css"> -->
<section class="px-4 py-5">
  <div class="mw-4xl mx-auto">
    <div class="text-center">
      <span class="badge rounded-pill bg-brand-subtle text-brand">Fair regional pricing</span>
      <h2 class="mt-2 fs-3 fw-bold text-body-emphasis">Pricing in your currency</h2>
      <p class="mt-2 text-body-secondary">We detected your currency automatically — switch any time.</p>
      <div class="mt-4 d-flex flex-wrap justify-content-center gap-2" role="group" aria-label="Currency">
        <button type="button" class="btn btn-outline-secondary choice fw-semibold rounded-2" data-set="currency:USD" data-pressed="currency:USD" aria-pressed="true">USD</button>
        <button type="button" class="btn btn-outline-secondary choice fw-semibold rounded-2" data-set="currency:EUR" data-pressed="currency:EUR" aria-pressed="false">EUR</button>
        <button type="button" class="btn btn-outline-secondary choice fw-semibold rounded-2" data-set="currency:GBP" data-pressed="currency:GBP" aria-pressed="false">GBP</button>
        <button type="button" class="btn btn-outline-secondary choice fw-semibold rounded-2" data-set="currency:INR" data-pressed="currency:INR" aria-pressed="false">INR</button>
        <button type="button" class="btn btn-outline-secondary choice fw-semibold rounded-2" data-set="currency:JPY" data-pressed="currency:JPY" aria-pressed="false">JPY</button>
      </div>
    </div>
    <div class="mt-5 row row-cols-1 row-cols-md-2 g-4">
      <div class="col">
        <div class="h-100 p-5 d-flex flex-column bg-body border shadow-sm rounded-3">
          <h3 class="fs-5 fw-semibold text-body-emphasis">Pro</h3>
          <p class="mt-1 small text-body-secondary">For individuals and small teams.</p>
          <p class="mt-4">
            <span data-when="currency:USD"><span class="fs-2 fw-bold text-body-emphasis">$29</span></span>
            <span data-when="currency:EUR" hidden><span class="fs-2 fw-bold text-body-emphasis">€27</span></span>
            <span data-when="currency:GBP" hidden><span class="fs-2 fw-bold text-body-emphasis">£23</span></span>
            <span data-when="currency:INR" hidden><span class="fs-2 fw-bold text-body-emphasis">₹999</span></span>
            <span data-when="currency:JPY" hidden><span class="fs-2 fw-bold text-body-emphasis">¥3,900</span></span>
            <span class="small text-body-secondary">/month</span>
          </p>
          <ul class="list-unstyled mt-4 mb-5 d-flex flex-column gap-2 flex-fill">
            <li class="small text-body">✓ Unlimited projects</li>
            <li class="small text-body">✓ Priority email support</li>
            <li class="small text-body">✓ Custom domain</li>
          </ul>
          <a href="#" class="btn btn-outline-secondary fw-semibold rounded-2 w-100">Choose Pro</a>
        </div>
      </div>
      <div class="col">
        <div class="h-100 p-5 d-flex flex-column bg-body border shadow-sm rounded-3 border-brand">
          <h3 class="fs-5 fw-semibold text-body-emphasis">Team</h3>
          <p class="mt-1 small text-body-secondary">For growing companies.</p>
          <p class="mt-4">
            <span data-when="currency:USD"><span class="fs-2 fw-bold text-body-emphasis">$79</span></span>
            <span data-when="currency:EUR" hidden><span class="fs-2 fw-bold text-body-emphasis">€73</span></span>
            <span data-when="currency:GBP" hidden><span class="fs-2 fw-bold text-body-emphasis">£62</span></span>
            <span data-when="currency:INR" hidden><span class="fs-2 fw-bold text-body-emphasis">₹2,999</span></span>
            <span data-when="currency:JPY" hidden><span class="fs-2 fw-bold text-body-emphasis">¥11,000</span></span>
            <span class="small text-body-secondary">/month</span>
          </p>
          <ul class="list-unstyled mt-4 mb-5 d-flex flex-column gap-2 flex-fill">
            <li class="small text-body">✓ Everything in Pro</li>
            <li class="small text-body">✓ 10 seats included</li>
            <li class="small text-body">✓ SSO & audit log</li>
          </ul>
          <a href="#" class="btn btn-brand fw-semibold rounded-2 w-100">Choose Team</a>
        </div>
      </div>
    </div>
    <p class="mt-4 text-center small text-body-secondary">Prices exclude local taxes. You are charged in the currency shown.</p>
  </div>
</section>

<script>
  (() => {
    // Region → currency (extend as needed). Prices below are regional, not FX conversions.
    const EUROZONE = ['AT', 'BE', 'CY', 'DE', 'EE', 'ES', 'FI', 'FR', 'GR', 'HR', 'IE', 'IT', 'LT', 'LU', 'LV', 'MT', 'NL', 'PT', 'SI', 'SK'];
    const REGION_CURRENCY = { US: 'USD', GB: 'GBP', IN: 'INR', JP: 'JPY' };

    function detectCurrency() {
      try {
        // Prefer a country injected by your edge (e.g. Cloudflare CF-IPCountry) if present.
        const region = document.documentElement.dataset.country || new Intl.Locale(navigator.language).maximize().region;
        if (REGION_CURRENCY[region]) return REGION_CURRENCY[region];
        if (EUROZONE.includes(region)) return 'EUR';
      } catch {
        // SSR / very old browsers → fall through to the default
      }
      return 'USD';
    }
    const state = { currency: detectCurrency() };
    const actions = {  };
    const pair = (s) => s.split(':');
    const sync = () => {
      document.querySelectorAll('[data-show]').forEach((el) => (el.hidden = !state[el.dataset.show]));
      document.querySelectorAll('[data-hide]').forEach((el) => (el.hidden = !!state[el.dataset.hide]));
      document.querySelectorAll('[data-when]').forEach((el) => { const [k, v] = pair(el.dataset.when); el.hidden = state[k] !== v; });
      document.querySelectorAll('[data-pressed]').forEach((el) => { const [k, v] = pair(el.dataset.pressed); el.setAttribute('aria-pressed', String(state[k] === v)); });
      document.querySelectorAll('[data-expanded]').forEach((el) => el.setAttribute('aria-expanded', String(!!state[el.dataset.expanded])));
    };
    document.addEventListener('click', (e) => {
      const t = e.target.closest('[data-toggle],[data-open],[data-close],[data-set],[data-call]');
      if (!t) return;
      const { toggle, open, close, set, call } = t.dataset;
      if (call) actions[call]?.(e);
      if (toggle) state[toggle] = !state[toggle];
      if (open) state[open] = true;
      if (close) state[close] = false;
      if (set) { const [k, v] = pair(set); state[k] = v; }
      sync();
    });
    sync();
  })();
</script>
All components →

Free Bootstrap 5 Currency Pricing Table for Vanilla JS by pGento

Install Bootstrap 5 for Vanilla JS

Include Bootstrap 5.3 from the CDN (or npm install bootstrap) and the generated theme.css:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="theme.css">

Use the currency pricing table in Vanilla JS

Paste the markup where the component should appear. The small inline <script> wires up the interactive state with one delegated click listener — no framework needed.

How currency detection works

The generated detectCurrency() reads the browser locale (navigator.language → Intl.Locale(...).maximize().region) and maps the region to a currency — no network request, no third-party geo-IP service, nothing to slow down rendering.

For IP-based detection, pass the country from your CDN: Cloudflare exposes it as the CF-IPCountry request header (and request.cf.country in Workers). Inject it into the page (for example as <html data-country="IN">) and read it first in detectCurrency(). Always let users override the guess, and charge in the currency you display.

Accessibility & customization

The currency switcher is a labelled group of toggle buttons using aria-pressed; prices are rendered as text for every currency so screen readers and search engines always see a price.

Every color, radius and dark-mode choice is baked into plain Bootstrap classes plus a tiny CSS-variable theme file, so the copied code has no runtime dependency on this site.

Compatibility

ItemDetails
CSS frameworkBootstrap 5.3+ (CSS only)
LibraryPlain HTML + optional vanilla JS
Interactive statecurrency
Dark modeYes — toggle in the editor
StyleMinimal

Frequently asked questions

How do I install this Bootstrap currency pricing table in Vanilla JS?
Create a web page, install Bootstrap 5 as shown in the installation section, then paste the generated code. Also save the generated theme.css file.
Can I change the color of the currency pricing table?
Yes. Use the brand color picker or type any hex code — the preview and code update instantly, and the color is written directly into the classes you copy.
Does the currency pricing table support dark mode?
Yes. Toggle “Dark mode” in the editor to generate a dark palette version of the same component.
Is the currency pricing table accessible?
The currency switcher is a labelled group of toggle buttons using aria-pressed; prices are rendered as text for every currency so screen readers and search engines always see a price.
Is this component free for commercial use?
Yes. The generated code is yours to use in personal and commercial projects without attribution.
Bootstrap 5 Currency Pricing Table for Vanilla JS

Embed this tool on your site

Paste this code into any web page. It stays free, fast and ad-free inside your site.

Print or save as PDF

Prints just this tool and its result. Choose “Save as PDF” as the printer to get a file. Branding is stored only in this browser.