How to create Dynamic Pricing List Template with HTML, Tailwind CSS and JavaScript

Obtain a complimentary, responsive pricing list template. Simply copy and paste the HTML, Tailwind CSS, and JavaScript to integrate a contemporary, engaging pricing page into your website.

A pricing table is a crucial component of any business or SAAS web platform. It allows users to effortlessly compare different plans and choose the one that best meets their requirements.

In this article, we will construct a responsive and engaging pricing table utilizing:

  • HTML for the foundational layout.
  • Tailwind CSS for efficient styling.
  • Custom CSS for distinctive animations and effects.
  • JavaScript for interactive features like toggles and real-time pricing changes.
No additional libraries are necessary apart from Tailwind CSS, which we will incorporate through a straightforward CDN link: <script src=”https://cdn.tailwindcss.com”></script>

This is the fundamental layout of our pricing webpage. It encompasses the design, cards, toggles, and the area where prices are displayed. All required scripts (Tailwind, Google Fonts) are included in the <head> section.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dynamic Pricing List | Coding Jasim</title>
    <!-- Tailwind CSS CDN -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- Google Font: Inter -->
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="styles.css">
</head>
<body class="antialiased">

    <div class="min-h-screen py-16 px-4 sm:px-6 lg:px-8">
        <div class="max-w-7xl w-full mx-auto">
            
            <!-- Section Header -->
            <div class="text-center mb-16">
                <h1 class="text-5xl font-extrabold text-gray-900 mb-4 tracking-tight leading-tight">
                    Find Your Exact Match
                </h1>
                <p class="text-xl text-gray-600 max-w-2xl mx-auto">
                    Pick a plan from the left side to immediately view its features and pricing on the right side.
                </p>
            </div>

            <!-- Monthly/Annual Toggle Switch -->
            <div class="flex items-center justify-center space-x-4 mb-16">
                <span class="text-lg font-medium text-gray-900">Monthly</span>
                <label for="billing-toggle" class="relative inline-block w-14 h-8 cursor-pointer">
                    <input type="checkbox" id="billing-toggle" class="opacity-0 w-0 h-0 peer">
                    <span class="toggle-slider absolute top-0 left-0 right-0 bottom-0 bg-gray-300 rounded-full transition-colors duration-300">
                        <span class="toggle-knob absolute left-1 top-1 w-6 h-6 bg-white rounded-full shadow-md"></span>
                    </span>
                </label>
                <span class="text-lg font-medium text-gray-900">
                    Annual 
                    <span class="hidden sm:inline text-xs font-semibold text-indigo-600 ml-1 py-0.5 px-2 bg-indigo-100 rounded-full">Save 20%</span>
                </span>
            </div>

            <!-- Main Interactive Panel -->
            <div class="grid grid-cols-1 lg:grid-cols-12 gap-8 xl:gap-12">

                <!-- Left Side: Plan Selectors -->
                <div class="lg:col-span-5 space-y-6">
                    
                    <!-- Selector 1: Starter -->
                    <div class="plan-selector-card" data-plan-id="starter">
                        <h3 class="text-2xl font-bold text-gray-900 mb-2">Starter</h3>
                        <p class="text-gray-600 mb-4">Perfect for individuals who are just starting out.</p>
                        <div class="text-lg font-semibold text-gray-800">
                            From 
                            <span class="text-2xl font-bold text-indigo-600" 
                                  data-monthly-price="29" 
                                  data-annual-price="23">
                                $23
                            </span> 
                            /mo
                        </div>
                    </div>
                    
                    <!-- Selector 2: Pro -->
                    <div class="plan-selector-card" data-plan-id="pro">
                        <div class="flex justify-between items-center mb-2">
                            <h3 class="text-2xl font-bold text-gray-900">Pro</h3>
                            <span class="bg-indigo-600 text-white text-xs font-bold px-3 py-1 rounded-full uppercase">Popular</span>
                        </div>
                        <p class="text-gray-600 mb-4">Designed for expanding team and professionals.</p>
                        <div class="text-lg font-semibold text-gray-800">
                            From 
                            <span class="text-2xl font-bold text-indigo-600"
                                  data-monthly-price="79" 
                                  data-annual-price="63">
                                $63
                            </span> 
                            /mo
                        </div>
                    </div>
                    
                    <!-- Selector 3: Enterprise -->
                    <div class="plan-selector-card" data-plan-id="enterprise">
                        <h3 class="text-2xl font-bold text-gray-900 mb-2">Enterprise</h3>
                        <p class="text-gray-600 mb-4">Sophisticated solutions for large organizations.</p>
                        <div class="text-lg font-semibold text-gray-800">
                            <span class="text-2xl font-bold text-indigo-600">Custom</span>
                        </div>
                    </div>

                </div>

                <!-- Right Side: Dynamic Details Panel -->
                <div class="lg:col-span-7">
                    <div class="bg-white rounded-2xl shadow-xl p-8 sticky top-8">
                        
                        <!-- Dynamic Price Header -->
                        <div class="border-b border-gray-200 pb-6 mb-6">
                            <h2 id="plan-name" class="text-3xl font-extrabold text-gray-900 mb-3">Starter</h2>
                            <p id="plan-description" class="text-lg text-gray-600 mb-6 min-h-[56px]">Ideal for individuals getting started.</q>
                            
                            <div class="flex items-baseline">
                                <span class="text-xl font-bold text-gray-500">$</span>
                                <span id="plan-price-value" class="text-6xl font-extrabold text-gray-900 mx-1" data-current-price="29">
                                    29
                                </span>
                                <span id="plan-price-period" class="text-xl font-medium text-gray-500">
                                    per user / mo
                                </span>
                            </div>
                        </div>
                        
                        <!-- Interactive Slider Section -->
                        <div id="slider-container" class="space-y-4 my-8">
                            <div class="flex justify-between items-center">
                                <span class="font-medium text-gray-800">Team Members</span>
                                <span id="slider-value-display" class="font-bold text-lg text-indigo-600 px-3 py-1 bg-indigo-100 rounded-full">
                                    5 Members
                                </span>
                            </div>
                            <input type="range" id="team-slider" class="price-slider" min="1" max="50" value="5">
                        </div>

                        <!-- Interactive Add-Ons Section -->
                        <div id="add-ons-container" class="space-y-4 mb-8">
                            <h4 class="text-xl font-semibold text-gray-900 mb-2">Customize Your Plan</h4>
                            
                            <!-- Add-on 1 -->
                            <label class="add-on-label">
                                <input type="checkbox" class="add-on-checkbox" data-add-on-id="ai">
                                <div>
                                    <span class="font-medium text-gray-800">Advanced AI Suite</span>
                                    <span class="block text-sm text-gray-500">
                                        +<span class="add-on-price" data-monthly-price="10" data-annual-price="8">$10</span>/mo
                                    </span>
                                </div>
                            </label>
                            
                            <!-- Add-on 2 -->
                            <label class="add-on-label">
                                <input type="checkbox" class="add-on-checkbox" data-add-on-id="support">
                                <div>
                                    <span class="font-medium text-gray-800">24/7 Premium Support</span>
                                    <span class="block text-sm text-gray-500">
                                        +<span class="add-on-price" data-monthly-price="15" data-annual-price="12">$15</span>/mo
                                    </span>
                                </div>
                            </label>
                        </div>


                        <!-- Dynamic Feature List -->
                        <div class="mt-8">
                            <h4 class="text-xl font-semibold text-gray-900 mb-4">Included features:</h4>
                            <ul id="feature-list" class="space-y-1">
                                <!-- JavaScript will populate here -->
                            </ul>
                        </div>

                        <!-- Button CTA -->
                        <a href="#" id="cta-button" class="block w-full text-center py-4 px-6 rounded-lg font-semibold text-lg text-white bg-indigo-600 hover:bg-indigo-700 transition-all duration-300 shadow-lg shadow-indigo-500/30 transform hover:scale-[1.02] mt-8">
                            Get Started with Starter
                        </a>
                    </div>
                </div>

            </div>
        </div>
    </div>
    <script src="script.js"></script>
</body>
</html>

The following CSS integrates with Tailwind to provide unique styles for toggle, cards, slider, and checkboxes. Insert this code into a new file titled style.css and ensure that it is linked in the <head> section of your HTML document.

body {
  font-family: 'Inter', sans-serif;
  background-color: #f1f4f8; 
  color: #111827; 
}
.antialiased {
  background-color: #8bdaeb;
}

.text-center h1{
  color: #b10c50;
}

/* --- Custom Toggle Switch Styling --- */
.toggle-knob {
  transition: transform 0.3s ease-in-out;
}
input:checked + .toggle-slider .toggle-knob {
  transform: translateX(24px);
}
input:checked + .toggle-slider {
  background-color: rgb(1, 6, 154);
}

/* --- Plan Selector Card (Left Side) --- */
.plan-selector-card {
  background-color: #ffffff;
  border: 2px solid #e5e7eb;
  border-radius: 1rem;
  padding: 1.5rem;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
  transform: scale(1);
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05),
    0 2px 4px -1px rgba(0, 0, 0, 0.03); /* Added subtle shadow */
}

.plan-selector-card:hover {
  border-color: #a5b4fc;
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.05);
}

.plan-selector-card.active {
  border-color: #4f46e5;
  box-shadow: 0 20px 25px -5px rgba(79, 70, 229, 0.1),
    0 10px 10px -5px rgba(79, 70, 229, 0.04);
  transform: scale(1.03);
  background-color: #f0f5ff;
}

/* --- Custom Add-On Checkbox Styling --- */
.add-on-label {
  display: flex;
  align-items: center;
  padding: 1rem;
  background-color: #f9fafb;
  border-radius: 0.75rem; 
  border: 2px solid #f3f4f6;
  cursor: pointer;
  transition: all 0.2s ease;
}
.add-on-label:hover {
  border-color: #d1d5db; 
}

.add-on-checkbox {
  -webkit-appearance: none;
  appearance: none;
  height: 1.5rem;
  width: 1.5rem;
  flex-shrink: 0;
  background-color: #ffffff;
  border: 2px solid #d1d5db;
  border-radius: 0.375rem;
  margin-right: 0.75rem; 
  display: grid;
  place-content: center;
  transition: all 0.2s ease;
}

.add-on-checkbox:checked {
  background-color: #4f46e5;
  border-color: #4f46e5;
}

.add-on-checkbox::before {
  content: '';
  width: 0.8rem;
  height: 0.8rem;
  transform: scale(0);
  transition: 120ms transform ease-in-out;
  box-shadow: inset 1em 1em #ffffff;
  clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
}

.add-on-checkbox:checked::before {
  transform: scale(1);
}

.add-on-label.peer-checked {
  border-color: #4f46e5;
  background-color: #f0f5ff;
}

/* --- Dynamic Feature List (Right Side) --- */
.feature-item {
  display: flex;
  height: 11px;
  align-items: center;
  padding: 0.75rem 0;
  border-bottom: 1px solid #dcdde1;
  transition: all 0.3s ease-in-out;
  opacity: 1;
}

.feature-item.disabled {
  opacity: 0.6;
}

.feature-item .feature-name {
  transition: all 0.3s ease;
}

.feature-item.disabled .feature-name {
  text-decoration: line-through;
  color: #6b7280; 
}

.icon-wrapper {
  width: 1.25rem; 
  height: 1.25rem;
  margin-right: 0.75rem; 
  flex-shrink: 0;
  position: relative;
}

.icon-check,
.icon-cross {
  position: absolute;
  transition: transform 0.3s ease, opacity 0.3s ease;
}

.icon-check {
  color: #0d8437;
  opacity: 1;
  transform: scale(1);
}
.icon-cross {
  color: #9ca3af; 
  opacity: 0;
  transform: scale(0.5);
}

.feature-item.disabled .icon-check {
  opacity: 0;
  transform: scale(0.5);
}
.feature-item.disabled .icon-cross {
  opacity: 1;
  transform: scale(1);
}

/* --- Animated Price Counter --- */
#plan-price-value {
  transition: all 0.3s ease;
}

/* --- Custom Range Slider --- */
.price-slider {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 8px;
  background: #e5e7eb; 
  border-radius: 9999px;
  outline: none;
  transition: opacity 0.2s;
}

/* Thumb (Chrome, Safari, etc.) */
.price-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 24px;
  height: 24px;
  background: #4f46e5; 
  border-radius: 50%;
  cursor: pointer;
  border: 4px solid #ffffff;
  box-shadow: 0 4px 10px rgba(79, 70, 229, 0.2);
  transition: all 0.2s ease;
}
.price-slider:hover::-webkit-slider-thumb {
  transform: scale(1.1);
}

/* Thumb (Firefox) */
.price-slider::-moz-range-thumb {
  width: 24px;
  height: 24px;
  background: #4f46e5;
  border-radius: 50%;
  cursor: pointer;
  border: 4px solid #ffffff;
  box-shadow: 0 4px 10px rgba(79, 70, 229, 0.2);
  transition: all 0.2s ease;
}
.price-slider:hover::-moz-range-thumb {
  transform: scale(1.1);
}
document.addEventListener('DOMContentLoaded', () => {
  // --- DATA ---
  const dataPlans = {
    starter: {
      name: 'Starter',
      description: 'Ideal for individuals getting started and hobby projects.',
      monthlyPricePerUser: 33,
      annualPricePerUser: 27,
      minUsers: 1,
      maxUsers: 10,
      defaultUsers: 5,
      ctaText: 'Get Started with Starter',
    },
    pro: {
      name: 'Pro',
      description:
        'For developing teams and professionals requiring advanced resources',
      monthlyPricePerUser: 79,
      annualPricePerUser: 63,
      minUsers: 5,
      maxUsers: 50,
      defaultUsers: 10,
      ctaText: 'Opt for Pro',
    },
    enterprise: {
      name: 'Enterprise',
      description:
        'Tailored solutions for large organizations and complex needs.',
      monthlyPrice: 'Custom',
      annualPrice: 'Custom',
      minUsers: 50,
      maxUsers: 500,
      defaultUsers: 50,
      ctaText: 'Contact Sales',
    },
  };

  const addOnsData = {
    ai: {
      monthlyPrice: 10,
      annualPrice: 8,
    },
    support: {
      monthlyPrice: 15,
      annualPrice: 12,
    },
  };

  const allFeatures = [
    { id: 'projects', name: 'Up to 10 Projects', plans: ['starter'] },
    {
      id: 'projects-pro',
      name: 'Unlimited Projects',
      plans: ['pro', 'enterprise'],
    },
    { id: 'team-members', name: '5 Team Members', plans: ['starter'] },
    {
      id: 'team-members-pro',
      name: 'Unlimited Team Members',
      plans: ['pro', 'enterprise'],
    },
    { id: 'storage', name: '50GB Storage', plans: ['starter', 'pro'] },
    { id: 'storage-ent', name: 'Unlimited Storage', plans: ['enterprise'] },
    {
      id: 'analytics',
      name: 'Basic Analytics',
      plans: ['starter', 'pro', 'enterprise'],
    },
    { id: 'integrations', name: 'Basic Integrations', plans: ['starter'] },
    {
      id: 'integrations-pro',
      name: 'Advanced Integrations',
      plans: ['pro', 'enterprise'],
    },
    { id: 'ai-tools', name: 'Advanced AI Tools', plans: ['pro', 'enterprise'] },
    { id: 'api-access', name: 'API Access', plans: ['pro', 'enterprise'] },
    {
      id: 'priority-support',
      name: 'Priority Chat Assistance',
      plans: ['pro', 'enterprise'],
    },
    { id: 'sso', name: 'Advanced SSO & Security', plans: ['enterprise'] },
    { id: 'sla', name: 'Uptime SLA', plans: ['enterprise'] },
    {
      id: 'dedicated-support',
      name: '24/7/356 Dedicated Support',
      plans: ['enterprise'],
    },
  ];

  // --- DOM ELEMENTS ---
  const toggle = document.getElementById('billing-toggle');
  const planSelectors = document.querySelectorAll('.plan-selector-card');
  const selectorPriceSpans = document.querySelectorAll(
    '.plan-selector-card span[data-monthly-price]'
  );

  const planNameEl = document.getElementById('plan-name');
  const planDescriptionEl = document.getElementById('plan-description');
  const planPriceValueEl = document.getElementById('plan-price-value');
  const planPricePeriodEl = document.getElementById('plan-price-period');
  const ctaButton = document.getElementById('cta-button');
  const featureListEl = document.getElementById('feature-list');

  const sliderContainer = document.getElementById('slider-container');
  const teamSlider = document.getElementById('team-slider');
  const sliderValueDisplay = document.getElementById('slider-value-display');

  const addOnsContainer = document.getElementById('add-ons-container');
  const addOnCheckboxes = document.querySelectorAll('.add-on-checkbox');
  const addOnPriceSpans = document.querySelectorAll('.add-on-price');

  let currentPlanId = 'starter';
  let isAnnual = false;
  let priceAnimationInterval = null;
  let activeAddOns = new Set();

  // --- FUNCTIONS ---

  // 1. Initialize: Render all possible features into the list
  function initializeFeatureList() {
    allFeatures.forEach((feature) => {
      const li = document.createElement('li');
      li.className = 'feature-item';
      li.dataset.featureId = feature.id;
      li.innerHTML = `
      <div class="icon-wrapper">
      <svg class="icon-check w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
      <svg class="icon-cross w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>
  </div>
  <span class="feature-name text-gray-700">${feature.name}</span>
            `;
      featureListEl.appendChild(li);
    });
  }

  // 2. Animate Price Counter
  function animatePrice(newPrice) {
    if (typeof newPrice !== 'number') {
      if (priceAnimationInterval) clearInterval(priceAnimationInterval);
      planPriceValueEl.innerText = newPrice;
      planPriceValueEl.dataset.currentPrice = 'NaN'; // Mark as non-numeric
      return;
    }

    let currentPrice = parseInt(planPriceValueEl.dataset.currentPrice);
    if (isNaN(currentPrice)) {
      currentPrice = 0;
    }

    clearInterval(priceAnimationInterval); // Clear any existing animation

    const step =
      newPrice > currentPrice
        ? Math.ceil((newPrice - currentPrice) / 10)
        : Math.floor((newPrice - currentPrice) / 10);
    if (step === 0) {
      // Already at target
      planPriceValueEl.dataset.currentPrice = newPrice;
      planPriceValueEl.innerText = newPrice; // Set text if no animation
      return;
    }

    let animatedPrice = currentPrice; // Use a variable for animation state

    priceAnimationInterval = setInterval(() => {
      if (animatedPrice !== newPrice) {
        animatedPrice += step;
        // Overshoot/undershoot check
        if (
          (step > 0 && animatedPrice >= newPrice) ||
          (step < 0 && animatedPrice <= newPrice)
        ) {
          animatedPrice = newPrice;
          clearInterval(priceAnimationInterval);
        }
        planPriceValueEl.innerText = animatedPrice; // Update text with animated value
      } else {
        clearInterval(priceAnimationInterval);
      }
    }, 20); // Animation speed
    planPriceValueEl.dataset.currentPrice = newPrice; // Set the new *target* price
  }

  // 3. Update all UI components based on selected plan
  function updatePlanDetails(planId) {
    currentPlanId = planId;
    const planData = dataPlans[planId];
    isAnnual = toggle.checked;

    // Reset add-ons when changing plans
    activeAddOns.clear();
    addOnCheckboxes.forEach((cb) => (cb.checked = false));

    // Update text details
    planNameEl.innerText = planData.name;
    planDescriptionEl.innerText = planData.description;
    ctaButton.innerText = planData.ctaText;
    ctaButton.href = `#${planId}`;

    // Show/Hide Add-ons & Slider
    if (planId === 'enterprise') {
      addOnsContainer.style.display = 'none';
      sliderContainer.style.display = 'none';
    } else {
      addOnsContainer.style.display = 'block';
      sliderContainer.style.display = 'block';

      // Update slider properties
      teamSlider.min = planData.minUsers;
      teamSlider.max = planData.maxUsers;
      teamSlider.value = planData.defaultUsers;
      updateSliderDisplay();
    }

    // Update price (will be called by updateTotalPrice)
    updateTotalPrice();

    // Feature list update
    allFeatures.forEach((feature) => {
      const featureEl = document.querySelector(
        `.feature-item[data-feature-id="${feature.id}"]`
      );
      if (feature.plans.includes(planId)) {
        featureEl.classList.remove('disabled');
      } else {
        featureEl.classList.add('disabled');
      }
    });

    // Update selector card active state
    planSelectors.forEach((card) => {
      if (card.dataset.planId === planId) {
        card.classList.add('active');
      } else {
        card.classList.remove('active');
      }
    });
  }

  // 4. Update prices on the selector cards (left side)
  function updateSelectorCardPrices() {
    isAnnual = toggle.checked;
    selectorPriceSpans.forEach((span) => {
      const price = isAnnual
        ? span.dataset.annualPrice
        : span.dataset.monthlyPrice;
      span.innerText = `$${price}`;
    });
  }

  // 5. Update Add-on price text
  function updateAddOnPrices() {
    isAnnual = toggle.checked;
    addOnPriceSpans.forEach((span) => {
      const monthly = span.dataset.monthlyPrice;
      const annual = span.dataset.annualPrice;
      span.innerText = isAnnual ? `$${annual}` : `$${monthly}`;
    });
  }

  // 6. Calculate Total Price
  function updateTotalPrice() {
    const planData = dataPlans[currentPlanId];
    isAnnual = toggle.checked;

    // Handle Enterprise "Custom" price
    if (currentPlanId === 'enterprise') {
      animatePrice('Custom');
      planPricePeriodEl.innerText = 'Custom Pricing';
      return;
    }

    const selectedUsers = parseInt(teamSlider.value);
    const perUserPrice = isAnnual
      ? planData.annualPricePerUser
      : planData.monthlyPricePerUser;
    const basePlanPrice = selectedUsers * perUserPrice;

    let totalAddOnPrice = 0;
    activeAddOns.forEach((addOnId) => {
      const addOnData = addOnsData[addOnId];
      // Making add-ons a flat monthly fee, not per-user
      totalAddOnPrice += isAnnual
        ? addOnData.annualPrice
        : addOnData.monthlyPrice;
    });

    const totalPrice = basePlanPrice + totalAddOnPrice;
    animatePrice(totalPrice);
    planPricePeriodEl.innerText = isAnnual ? 'per year' : 'per month';
  }

  // 7. Update Slider Value Display
  function updateSliderDisplay() {
    const users = teamSlider.value;
    sliderValueDisplay.innerText = `${users} Member${users > 1 ? 's' : ''}`;
  }

  // --- EVENT LISTENERS ---
  // Billing toggle
  toggle.addEventListener('change', () => {
    isAnnual = toggle.checked;
    updateSelectorCardPrices();
    updateAddOnPrices();
    updateTotalPrice(); // Re-calculate total price
  });

  // Team slider
  teamSlider.addEventListener('input', () => {
    updateSliderDisplay();
    updateTotalPrice();
  });

  // Plan selector cards
  planSelectors.forEach((card) => {
    card.addEventListener('click', () => {
      const planId = card.dataset.planId;
      updatePlanDetails(planId);
    });
  });

  // Add-on checkboxes
  addOnCheckboxes.forEach((checkbox) => {
    checkbox.addEventListener('change', () => {
      const addOnId = checkbox.dataset.addOnId;
      if (checkbox.checked) {
        activeAddOns.add(addOnId);
      } else {
        activeAddOns.delete(addOnId);
      }
      updateTotalPrice(); // Recalculate price on add-on change
    });
  });

  // --- INITIALIZATION ---
  initializeFeatureList();
  updateSelectorCardPrices();
  updateAddOnPrices();
  // Set "Pro" as the default active plan on load
  const defaultPlanId = 'pro';
  currentPlanId = defaultPlanId;
  document
    .querySelector(`.plan-selector-card[data-plan-id="${defaultPlanId}"]`)
    .classList.add('active');
  updatePlanDetails(defaultPlanId);

  // Set initial price without animation
  const initialPlan = dataPlans[defaultPlanId];
  const initialUsers = initialPlan.defaultUsers;
  const initialPrice = initialPlan.monthlyPricePerUser * initialUsers;
  planPriceValueEl.innerText = initialPrice;
  planPriceValueEl.dataset.currentPrice = initialPrice;
  teamSlider.value = initialUsers;
  updateSliderDisplay();
});

Conclusion & Final Thoughts

And that’s all! You know possess a completely functional, responsive, and engaging pricing list that employs a per-user pricing strategy. Users can clearly see what they are receiving and the associated costs, all updated in real-time.

From this point, you can effortlessly tailor this code. Consider modifying the plan information in the plans Data JavaScript object to align with your own offerings, or tweak the Tailwind CSS utility classes in the HTML to alter the colors and spacing to suit your brand.

Download Button with Timer | CodingJasim
Scroll to Top