JSFiddle - React, Tailwind, and code Playground

Pricing Slider - Pure JS

by Christopher O

HTML

<script src="https://fonts.googleapis.com/css?family=Heebo:400,500&amp;display=swap"></script>
<!DOCTYPE html>
<div class="pricing">
    <div class="pricing-slider">
        <label class="form-slider">
        <span style="white-space: nowrap;">How many Active Contacts per month?</span>
            <div class="pricing-slider-value"></div><br>
            <input type="range" value="0" data-price-input='{
                "0": "200",
                "1": "1,000",
                "2": "2,500",
                "3": "5,000",
                "4": "10,000",
                "5": "25,000",
                "6": "50,000",
                "7": "75,000",
                "8": "100,000+"                        
              }' />
        </label>
        <!-- <div class="pricing-slider-value"></div> -->
    </div>
    <div class="pricing-items">
        <div class="pricing-item" id="connectplan">
            <div class="pricing-item-inner">
                <div class="pricing-item-content">
                    <div class="pricing-item-header">
                        <div class="pricing-item-title">Connect</div>
                        <span class="pricing-item-price-amount">Free</span>
                    </div>
                    <div class="bestfor">
                      <strong>Best for: </strong>Small teams wanting to centralize and collaborate on customer messages
                    </div>
                    <div class="pricing-item-features">
                        <ul class="pricing-item-features-list">
                            <li class="is-checked">Unlimited users</li>
                            <li class="is-checked">Unlimited chats <span class="sub">1</span></li>
                            <li class="is-checked">Unlimited messages</li>
                            <li class="is-checked">1 inbox</li>
                            <li class="is-checked">20 contact fields</li>
                            <li class="is-checked">10,000 contacts storage</li>
      ...

CSS

*,
*:before,
*:after {
  box-sizing: border-box;
}

.smaller{
  font-size:12px !important;
  color: #ccc !important;
  margin: -20px 0 0 0 !important;
}

html {
  font-size: 16px;
  line-height: 24px;
  letter-spacing: -0.1px;
}

body {
  color: #607090;
  font-size: 1rem;
  margin: 0;
  padding: 48px;
  -moz-osx-font-smoothing: grayscale;
  -webkit-font-smoothing: antialiased;
}

body,
button,
input,
select,
textarea {
  font-family: "Heebo", sans-serif;
  font-weight: 400;
}
.button {
  display: flex;
  width: 100%;
  font-size: 14px;
  line-height: 22px;
  font-weight: 700;
  padding: 12px 29px;
  text-decoration: none !important;
  text-transform: uppercase;
  color: #ffffff;
  background-color: #00c5cd;
  border-width: 1px;
  border-style: solid;
  border-color: transparent;
  border-radius: 2px;
  cursor: pointer;
  justify-content: center;
  text-align: center;
  letter-spacing: inherit;
  white-space: nowrap;
  transition: background 0.15s ease;
}
input[type="range"] {
  -moz-appearance: none;
  -webkit-appearance: none;
  background: #aaa;
  border-radius: 3px;
  height: 6px;
  width: 100%;
  margin-top: 15px;
  margin-bottom: 15px;
  outline: none;
}
input[type="range"]::-webkit-slider-thumb {
  appearance: none;
  -webkit-appearance: none;
  background-color: #00c5cd;
  background-image: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2212%22%20height%3D%228%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M8%20.5v7L12%204zM0%204l4%203.5v-7z%22%20fill%3D%22%23FFFFFF%22%20fill-rule%3D%22nonzero%22%2F%3E%3C%2Fsvg%3E");
  background-position: center;
  background-repeat: no-repeat;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  height: 36px;
  width: 36px;
}
input[type="range"]::-moz-range-thumb {
  background-color: #5f48ff;
  background-image:...

JavaScript

(function() {
  const pricingSliders = document.querySelectorAll(".pricing-slider");

  if (pricingSliders.length > 0) {
    for (let i = 0; i < pricingSliders.length; i++) {
      const pricingSlider = pricingSliders[i];

      // Build the input object
      const pricingInput = {
        el: pricingSlider.querySelector("input")
      };
      pricingInput.data = JSON.parse(
        pricingInput.el.getAttribute("data-price-input")
      );
      pricingInput.currentValEl = pricingSlider.querySelector(
        ".pricing-slider-value"
      );
      pricingInput.thumbSize = parseInt(
        window
        .getComputedStyle(pricingInput.currentValEl)
        .getPropertyValue("--thumb-size"),
        10
      );

      // Build the output array
      const pricingOutputEls = pricingSlider.parentNode.querySelectorAll(
        ".pricing-item-price"
      );
      const pricingOutput = [];
      for (let i = 0; i < pricingOutputEls.length; i++) {
        const pricingOutputEl = pricingOutputEls[i];
        const pricingOutputObj = {};
        pricingOutputObj.currency = pricingOutputEl.querySelector(
          ".pricing-item-price-currency"
        );
        pricingOutputObj.amount = pricingOutputEl.querySelector(
          ".pricing-item-price-amount"
        );
        pricingOutputObj.after = pricingOutputEl.querySelector(
          ".pricing-item-price-after"
        );
        pricingOutputObj.data = JSON.parse(
          pricingOutputEl.getAttribute("data-price-output")
        );
        pricingOutput.push(pricingOutputObj);
      }

      pricingInput.el.setAttribute("min", 0);
      pricingInput.el.setAttribute(
        "max",
        Object.keys(pricingInput.data).length - 1
      );
      !pricingInput.el.getAttribute("value") &&
        pricingInput.el.setAttribute("value", 0);

      handlePricingSlider(pricingInput, pricingOutput);
      window.addEventListener("input", function() {
        handlePricingSlider(pricingInput, pricingOutput);
      });
 ...