Create a range slider

This post introduces two popular ways to create a range slider.

1. Use a range input

HTML provides a built-in range input:
<input type="range" />
It's supported in modern browsers, IE 10 and later. But there're some limitations such as:
Jump to the next section if you want to have a customizable slider.
Tip
Using the similar technique mentioned in this post, we can check if the range input is supported or not:
const isRangeInputSupported = function () {
const ele = document.createElement('input');
ele.setAttribute('type', 'range');
// If the browser doesn't support the `range` input,
// the `type` attribute will be reverted back to `text`
return ele.type !== 'text';
};

2. Create a customizable range slider

A slider is a combination of three parts: a knob, and two sides located at the left and right of the knob.
<div class="container">
<div class="left"></div>
<div class="knob" id="knob"></div>
<div class="right"></div>
</div>
These parts are placed in the same row. The right element takes the available width. So, we can use the following styles to build the layout:
.container {
/* Content is centered horizontally */
align-items: center;
display: flex;
/* Size */
height: 1.5rem;
}
.right {
/* Take the remaining width */
flex: 1;
height: 2px;
}
You can take a look at the demo to see the full styles of elements.
Resource
This page demonstrates the simplest layout for a range slider

Handle the events

The idea of making the knob draggable is quite simple:
// Query the element
const knob = document.getElementById('knob');
const leftSide = knob.previousElementSibling;
// The current position of mouse
let x = 0;
let y = 0;
let leftWidth = 0;
// Handle the mousedown event
// that's triggered when user drags the knob
const mouseDownHandler = function (e) {
// Get the current mouse position
x = e.clientX;
y = e.clientY;
leftWidth = leftSide.getBoundingClientRect().width;
// Attach the listeners to `document`
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
};
const mouseMoveHandler = function (e) {
// How far the mouse has been moved
const dx = e.clientX - x;
const dy = e.clientY - y;
const containerWidth = knob.parentNode.getBoundingClientRect().width;
let newLeftWidth = ((leftWidth + dx) * 100) / containerWidth;
newLeftWidth = Math.max(newLeftWidth, 0);
newLeftWidth = Math.min(newLeftWidth, 100);
leftSide.style.width = `${newLeftWidth}%`;
};
There're more small things that aren't listed in this post since you can see them in the demo's source. But I always recommend to cleanup everything when the handlers aren't used:
// Triggered when user drops the knob
const mouseUpHandler = function() {
...
// Remove the handlers of `mousemove` and `mouseup`
document.removeEventListener('mousemove', mouseMoveHandler);
document.removeEventListener('mouseup', mouseUpHandler);
};
Tip

Use cases

Enjoy the demo!

Demo

Create a range slider

See also