Smooth Dual Range Slider With Tooltips

Category: Form , Javascript | May 22, 2024
Author:cbolson
Views Total:39 views
Official Page:Go to website
Last Update:May 22, 2024
License:MIT

Preview:

Smooth Dual Range Slider With Tooltips

Description:

A sleek and functional range slider control built with HTML, CSS, JavaScript, and native range inputs.

This range slider control allows users to select a range of values indicated by two sliders, commonly referred to as “thumbs.” When you move the thumbs, the corresponding tooltips update to show the selected minimum and maximum values. This provides immediate visual feedback and makes it easier for users to understand their selections.

How to use it:

1. Place two regular range inputs together with tooltips and a range scale on the page.

<div class="range_container">
  <div class="sliders_control">
    <div id="fromSliderTooltip" class="slider-tooltip">0</div>
    <input id="fromSlider" type="range" value="120" min="50" max="350" steps="10" />
    <div id="toSliderTooltip" class="slider-tooltip">0</div>
    <input id="toSlider" type="range" value="260" min="50" max="350" steps="10" />
  </div>
  <div id="scale" class="scale"></div>
</div>

2. Apply the necessary styles to the range slider control.

  • Slider container and track dimensions
  • Tooltip position, color, and styling
  • Range input thumb design and hover effects
  • Scale marker positioning and text formatting
.range_container {
  --_marker-border-clr: #0EA5E9;
  --_marker-size: 15px;
  --_track-heigt: 3px;
  --_tooltip-bg-clr: rgba(0, 0, 0, 0.4);
  --_tooltip-txt-clr: var(--_marker-border-clr);
  width: 100%;
  max-width: 600px;
  display: flex;
  flex-direction: column;
}
.sliders_control {
  position: relative;
}
.slider-tooltip {
  position: absolute;
  top: -3.5rem;
  left: 0;
  width: fit-content;
  background-color: var(--_tooltip-bg-clr);
  color: var(--_tooltip-txt-clr);
  font-size: 0.8rem;
  border-radius: 4px;
  padding: 0.5rem 1rem;
  text-align: center;
  translate: -50% 0;
}
.slider-tooltip::before {
  content: "";
  position: absolute;
  bottom: -0.25rem;
  left: 50%;
  translate: -50% 0;
  width: .5rem;
  height: .5rem;
  rotate: 45deg;
  z-index: -1;
  background-color: inherit;
}
input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none;
  pointer-events: all;
  width: var(--_marker-size);
  height: var(--_marker-size);
  background-color: var(--_marker-border-clr);
  border-radius: 50%;
  box-shadow: 0 0 0 1px var(--_marker-border-clr);
  cursor: pointer;
}
input[type=range]::-moz-range-thumb {
  -webkit-appearance: none;
  pointer-events: all;
  width: var(--_marker-size);
  height: var(--_marker-size);
  background-color: var(--_marker-border-clr);
  border-radius: 50%;
  box-shadow: 0 0 0 1px var(--_marker-border-clr);
  cursor: pointer;
}
input[type=range]::-webkit-slider-thumb:hover {
  background: #f7f7f7;
}
input[type=range]::-webkit-slider-thumb:active {
  box-shadow: inset 0 0 3px #387bbe, 0 0 9px #387bbe;
  -webkit-box-shadow: inset 0 0 3px #387bbe, 0 0 9px #387bbe;
}
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  height: var(--_track-heigt);
  width: 100%;
  position: absolute;
  background-color: var(--_marker-border-clr);
  pointer-events: none;
}
#fromSlider {
  height: 0;
  z-index: 1;
}
.scale {
  display: flex;
  justify-content: space-between;
  margin-top: 2rem;
  position: relative;
  width: calc(100% - var(--_marker-size));
  margin-inline: auto;
  font-size: 0.8rem;
}
.scale div {
  position: absolute;
  translate: -50% 0;
}
.scale div::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  translate: -50% -125%;
  width: 1px;
  height: 10px;
  background-color:#666;
}

3. The JavaScript code initializes the range slider by setting up event listeners for the range inputs.

  • As the user interacts with the slider thumbs, the event handlers perform calculations to update the tooltips’ positions and values accordingly.
  • The range track’s appearance is dynamically adjusted using CSS linear gradients.
  • The createScale function generates the range scale by iterating over the specified range and creating marker elements with corresponding values.
document.addEventListener('DOMContentLoaded', () => {
  const COLOR_TRACK = "#666";
  const COLOR_RANGE = "#0EA5E9"; /* this can be the same or different to the markers */
  const MIN = 50;
  const MAX = 350;
  const STEPS = 50;
  function controlFromSlider(fromSlider, toSlider, fromTooltip, toTooltip) {
      const [from, to] = getParsed(fromSlider, toSlider);
      fillSlider(fromSlider, toSlider, COLOR_TRACK, COLOR_RANGE, toSlider);
      if (from > to) {
          fromSlider.value = to;
      }
      setTooltip(fromSlider, fromTooltip);
  }
  function controlToSlider(fromSlider, toSlider, fromTooltip, toTooltip) {
      const [from, to] = getParsed(fromSlider, toSlider);
      fillSlider(fromSlider, toSlider, COLOR_TRACK, COLOR_RANGE, toSlider);
      setToggleAccessible(toSlider);
      if (from <= to) {
          toSlider.value = to;
      } else {
          toSlider.value = from;
      }
      setTooltip(toSlider, toTooltip);
  }
  function getParsed(currentFrom, currentTo) {
      const from = parseInt(currentFrom.value, 10);
      const to = parseInt(currentTo.value, 10);
      return [from, to];
  }
  function fillSlider(from, to, sliderColor, rangeColor, controlSlider) {
      const rangeDistance = to.max - to.min;
      const fromPosition = from.value - to.min;
      const toPosition = to.value - to.min;
      controlSlider.style.background = `linear-gradient(
        to right,
        ${sliderColor} 0%,
        ${sliderColor} ${(fromPosition) / (rangeDistance) * 100}%,
        ${rangeColor} ${((fromPosition) / (rangeDistance)) * 100}%,
        ${rangeColor} ${(toPosition) / (rangeDistance) * 100}%, 
        ${sliderColor} ${(toPosition) / (rangeDistance) * 100}%, 
        ${sliderColor} 100%)`;
  }
  function setToggleAccessible(currentTarget) {
      const toSlider = document.querySelector('#toSlider');
      if (Number(currentTarget.value) <= 0) {
          toSlider.style.zIndex = 2;
      } else {
          toSlider.style.zIndex = 0;
      }
  }
  function setTooltip(slider, tooltip) {
      const value = slider.value;
      tooltip.textContent = `$${value}`;;
      const thumbPosition = (value - slider.min) / (slider.max - slider.min);
      const percent = thumbPosition * 100;
      const markerWidth = 20; // Width of the marker in pixels
      const offset = (((percent - 50) / 50) * markerWidth) / 2;
      tooltip.style.left = `calc(${percent}% - ${offset}px)`;
  }
  function createScale(min, max, step) {
      const scale = document.getElementById('scale');
      const range = max - min;
      const steps = range / step;
      for (let i = 0; i <= steps; i++) {
          const value = min + (i * step);
          const percent = (value - min) / range * 100;
          const marker = document.createElement('div');
          marker.style.left = `${percent}%`;
          marker.textContent = `$${value}`;
          scale.appendChild(marker);
      }
  }
  const fromSlider = document.querySelector('#fromSlider');
  const toSlider = document.querySelector('#toSlider');
  const fromTooltip = document.querySelector('#fromSliderTooltip');
  const toTooltip = document.querySelector('#toSliderTooltip');
  // events
  fromSlider.oninput = () => controlFromSlider(fromSlider, toSlider, fromTooltip, toTooltip);
  toSlider.oninput = () => controlToSlider(fromSlider, toSlider, fromTooltip, toTooltip);
  // Initial load
  fillSlider(fromSlider, toSlider, COLOR_TRACK, COLOR_RANGE, toSlider);
  setToggleAccessible(toSlider);
  setTooltip(fromSlider, fromTooltip);
  setTooltip(toSlider, toTooltip);
  createScale(MIN, MAX, STEPS);
});

You Might Be Interested In:


Leave a Reply