About this snippet

Increase SaaS conversions with an animated pricing switcher. When you toggle between monthly and yearly billing, the numbers seamlessly count up or down securely using vanilla JavaScript.

Size
5.5 KB
Uses
HTML, CSS, JavaScript
Loads
Nothing external
Views
227
<div class="pricing-container">
  
  <div class="billing-toggle">
    <span class="billing-label">Monthly</span>
    <label class="switch-box">
      <input type="checkbox" class="billing-cb" id="billing-checkbox">
      <span class="switch-slider"></span>
    </label>
    <span class="billing-label">Yearly <span class="discount-badge">Save 20%</span></span>
  </div>
  
  <div class="pricing-cards">
    <div class="plan-card">
      <h3>Basic Plan</h3>
      <div class="price-display">
        <span class="currency">$</span>
        <span class="price-val" data-monthly="19" data-yearly="15" id="price-basic">19</span>
        <span class="period">/mo</span>
      </div>
      <button class="plan-btn">Choose Basic</button>
    </div>
    
    <div class="plan-card popular">
      <div class="popular-tag">Most Popular</div>
      <h3>Pro Plan</h3>
      <div class="price-display">
        <span class="currency">$</span>
        <span class="price-val" data-monthly="49" data-yearly="39" id="price-pro">49</span>
        <span class="period">/mo</span>
      </div>
      <button class="plan-btn primary">Choose Pro</button>
    </div>
  </div>
  
</div>
*, *::before, *::after {
  box-sizing: border-box;
}

body {
  font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
  margin: 0;
  background: #f8fafc;
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  padding: 40px 20px;
}

.pricing-container {
  width: 100%;
  max-width: 800px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.billing-toggle {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 50px;
}

.billing-label {
  font-weight: 600;
  color: #334155;
  display: flex;
  align-items: center;
  gap: 8px;
}

.discount-badge {
  background: #dcfce7;
  color: #166534;
  padding: 4px 8px;
  border-radius: 12px;
  font-size: 0.75rem;
}

.switch-box {
  position: relative;
  display: inline-block;
  width: 60px;
  height: 32px;
}

.billing-cb {
  display: none;
}

.switch-slider {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  background-color: #cbd5e1;
  border-radius: 32px;
  cursor: pointer;
  transition: 0.3s;
}

.switch-slider::before {
  position: absolute;
  content: "";
  height: 24px;
  width: 24px;
  left: 4px;
  bottom: 4px;
  background-color: #ffffff;
  border-radius: 50%;
  transition: 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
  box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}

.billing-cb:checked + .switch-slider {
  background-color: #3b82f6;
}

.billing-cb:checked + .switch-slider::before {
  transform: translateX(28px);
}

.pricing-cards {
  display: flex;
  gap: 24px;
  width: 100%;
  justify-content: center;
  flex-wrap: wrap;
}

.plan-card {
  background: #ffffff;
  border: 1px solid #e2e8f0;
  border-radius: 24px;
  padding: 40px 30px;
  width: 100%;
  max-width: 320px;
  text-align: center;
  box-shadow: 0 10px 20px -5px rgba(0,0,0,0.05);
  position: relative;
}

.plan-card.popular {
  border: 2px solid #3b82f6;
  transform: translateY(-10px);
  box-shadow: 0 20px 40px -10px rgba(59, 130, 246, 0.2);
}

.popular-tag {
  position: absolute;
  top: -12px;
  left: 50%;
  transform: translateX(-50%);
  background: #3b82f6;
  color: #ffffff;
  font-size: 0.8rem;
  font-weight: 700;
  padding: 4px 16px;
  border-radius: 20px;
  text-transform: uppercase;
}

.plan-card h3 {
  margin: 0 0 20px 0;
  color: #0f172a;
  font-size: 1.25rem;
}

.price-display {
  display: flex;
  justify-content: center;
  align-items: baseline;
  margin-bottom: 30px;
}

.currency {
  font-size: 1.5rem;
  font-weight: 700;
  color: #0f172a;
}

.price-val {
  font-size: 4rem;
  font-weight: 800;
  color: #0f172a;
  letter-spacing: -2px;
  /* Add monospace font to prevent layout shifting during number animation */
  font-variant-numeric: tabular-nums;
}

.period {
  font-size: 1rem;
  color: #64748b;
  font-weight: 500;
}

.plan-btn {
  width: 100%;
  background: #f1f5f9;
  color: #0f172a;
  border: none;
  padding: 14px;
  border-radius: 12px;
  font-size: 1rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.2s;
}

.plan-btn:hover { background: #e2e8f0; }

.plan-btn.primary {
  background: #3b82f6;
  color: #ffffff;
}

.plan-btn.primary:hover { background: #2563eb; }
const toggle = document.getElementById("billing-checkbox");
const priceBasic = document.getElementById("price-basic");
const pricePro = document.getElementById("price-pro");

/* Safely animate number counting without external libraries */
function animateValue(obj, start, end, duration) {
  let startTimestamp = null;
  const step = function(timestamp) {
    if (!startTimestamp) startTimestamp = timestamp;
    const progress = Math.min((timestamp - startTimestamp) / duration, 1);
    
    const currentVal = Math.floor(progress * (end - start) + start);
    obj.innerText = currentVal;
    
    if (progress < 1) {
      window.requestAnimationFrame(step);
    } else {
      obj.innerText = end;
    }
  };
  window.requestAnimationFrame(step);
}

toggle.addEventListener("change", function(e) {
  const isYearly = e.target.checked;
  
  const basicStart = parseInt(priceBasic.innerText);
  const basicEnd = isYearly ? parseInt(priceBasic.getAttribute("data-yearly")) : parseInt(priceBasic.getAttribute("data-monthly"));
  
  const proStart = parseInt(pricePro.innerText);
  const proEnd = isYearly ? parseInt(pricePro.getAttribute("data-yearly")) : parseInt(pricePro.getAttribute("data-monthly"));
  
  animateValue(priceBasic, basicStart, basicEnd, 400);
  animateValue(pricePro, proStart, proEnd, 400);
});
Esc
↑↓ moveEnter select

Start from a template

Open an .html file, or HTML, CSS, JS, Markdown, Less or TypeScript files. You can also drop them here. Styles and scripts go into their panes.

Share

Source

Keyboard shortcuts

Save