1

var slider = document.getElementById("myRange");
var output = document.getElementById("demo");
output.innerHTML = slider.value;

slider.oninput = function() {
  output.innerHTML = this.value;
}
.slidecontainer {
  width: 100%;
}

.slider {
  -webkit-appearance: none;
  width: 100%;
  height: 15px;
  border-radius: 5px;
  background: #d3d3d3;
  outline: none;
  opacity: 0.7;
  -webkit-transition: .2s;
  transition: opacity .2s;
}

.slider:hover {
  opacity: 1;
}

.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 25px;
  height: 25px;
  border-radius: 50%;
  background: #04AA6D;
  cursor: pointer;
}

.slider::-moz-range-thumb {
  width: 25px;
  height: 25px;
  border-radius: 50%;
  background: #04AA6D;
  cursor: pointer;
}
<h1>Round Range Slider</h1>

<div class="slidecontainer">
  <input type="range" min="1" max="100" value="50" class="slider" id="myRange" style="width: 200px">
  <p>Value: <span id="demo"></span></p>
</div>

The code above is a range slider made in HTML.

enter image description here

This is example of how it could look.

1 Answers1

1

For the solution, first need to get the input range, then the width of step, because of the range will be greater than your maximum value, the bubble can't to place by center to the thumb. Finally multiply range and step to get the bubble position. The bubble better create with the svg create bubble. For styling the range input link

function App() {
  const [range, setRange] = React.useState(0);
  const [step, setStep] = React.useState(0);
  const ref = React.useRef(null);

  const getRange = (ev) => {
    setRange(ev.target.value);
  };

  React.useEffect(() => {
    const rangeLinePadding = 16;
    const calcStep =
      (ref.current.offsetWidth - rangeLinePadding) / ref.current.max;
    setStep(calcStep);
  }, []);

  return ( <div className="App">
      <h1> Range Slider </h1>
      <div className="slider">
        <input
          type="range"
          id="range"
          min="0"
          max="100"
          value={range}
          onChange={getRange}
          ref={ref}
        />
        <label
          htmlFor="range"
          style={{
            transform: `translateX(${range * step}px)`,
          }}>
          <span> {range} </span>
          <svg viewBox="0 0 15 18">
            <path d="M14,7a7,7,0,0,1-2,4.87L7.72,16.35a1,1,0,0,1-1.44,0L2,11.87A6.93,6.93,0,0,1,0,7,7,7,0,0,1,14,7Z" />
          </svg>
        </label>
      </div>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render( <
  App / > ,
  rootElement
);
.App {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 50px;
  font-family: sans-serif;
  text-align: center;
}

.slider {
  width: 200px;
  display: flex;
  flex-direction: column;
  position: relative;
  padding: 0 10px;
}

label[for='range'] {
  width: 35px;
  height: 40px;
  position: absolute;
  top: -45px;
  left: 0;
  color: hsl(0, 0%, 0%);
  pointer-events: none;
}

label[for='range'] span {
  position: absolute;
  top: 8px;
  left: 50%;
  text-align: center;
  font-size: 0.9em;
  font-weight: bold;
  transform: translateX(-50%);
  z-index: 5;
}

label[for='range'] svg {
  height: inherit;
  position: relative;
  left: 1px;
  fill: hsl(207, 90%, 77%);
  z-index: -1;
  pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Anton
  • 4,081
  • 1
  • 5
  • 17