Precision

By default <RangeSlider /> will use a precision of 2 decimal places. This controls the values and the display of pips/floats.

It is necessary to control the precision due to the nature of floating point artihmetic in javascript. Without a precision check, values on the slider would end up with rounding errors in certain scenarios (specifically sliders with non-integer steps).

Default Precision

Here you can see the default precision of 2 decimal places.

<script>
  let value = 0.55;
</script>

<RangeSlider step={0.05} pipstep={2} max={1} pips all="label" float bind:value />
Default Precision
0.55
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
0.55

step has too much precision

It’s possible to have steps of more than 2 decimal places, but here you can see that even though the slider is set to a step of 0.005, the values are rounded to 2 decimal places by default.

The slider accepts the value prop as 0.555, but as soon as it is interacted with, it will be rounded to 0.56.

<script>
  let value = 0.555;
</script>

<RangeSlider step={0.005} pipstep={20} max={1} pips all="label" float bind:value />
Precision Mismatch
0.56
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
0.555

Changing the precision

So when you have a step with more than 2 decimal places, you should set the precision to the number of decimal places you want to use.

<RangeSlider step={0.0001} precision={4} />

Video 😬

Video precision setting
0:00.00
currentTime: 0 / duration: undefined
<script>

  // settings for the slider
  const precision = 4;
  const step = 0.0001;
  
  // bindings for the video element and its properties
  let videoElement;
  $: duration = videoElement?.duration;
  let currentTime = 0;
  let buffers = [];
  let bufferStyle = '';

  /* formatting the float as time (mm:ss.ss) with 2 decimal places, 
    even though precision is set to 4 */
  const minuteFormat = new Intl.NumberFormat('en', { minimumIntegerDigits: 1 });
  const secondFormat = new Intl.NumberFormat('en', { minimumIntegerDigits: 2, minimumFractionDigits: 2, maximumFractionDigits: 2 });
  const timeFormat = (v) => `${minuteFormat.format(Math.floor(v / 60))}:${secondFormat.format(v % 60).split('.')[0]}<small>.${secondFormat.format(v % 60).split('.')[1]}</small>`;
  

  /* I'm showing the buffered ranges as a gradient background */
  const updateBufferStyle = (e) => {
    buffers = [];
    if( !duration ) return;
    for (let i = 0; i < videoElement.buffered.length; i++) {
      const start = videoElement.buffered.start(i) / duration * 100;
      const end = videoElement.buffered.end(i) / duration * 100;
      buffers = [...buffers, { start, end }];
    }
    bufferStyle = `background-image: linear-gradient(to right, transparent, ${buffers.map((range, index) => 
      `transparent ${range.start}%, #94b28d ${range.start}%, #94b28d ${range.end}%, transparent ${range.end}%, transparent`
    ).join(', ')})`;
  };
  
</script>

<RangeSlider 
  id="seek-slider"
  bind:value={currentTime} 
  {step} 
  {precision} 
  max={duration} 
  float
  range='min'
  formatter={timeFormat}
  style={bufferStyle}
/>

<video 
  bind:this={videoElement}
  src="https://res.cloudinary.com/simey/video/upload/v1749837864/hxpk2grhbvec0hcitnua.mp4" 
  controls 
  bind:currentTime 
  bind:duration
  on:seeked={updateBufferStyle}
  on:play={updateBufferStyle}
  on:progress={updateBufferStyle}
/>