This post introduces two popular ways to create a range slider.
1. Use a range
input
HTML provides a built-in range
input:
It's supported in modern browsers, IE 10 and later. But there're some limitations such as:
- You can't customize the knob
- At the time of writing this, the vertical-oriented slider isn't supported in all modern browsers
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');
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 {
align-items: center;
display: flex;
height: 1.5rem;
}
.right {
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:
- Handle the knob's
mousedown
event. The handler stores the mouse position:
const knob = document.getElementById('knob');
const leftSide = knob.previousElementSibling;
let x = 0;
let y = 0;
let leftWidth = 0;
const mouseDownHandler = function (e) {
x = e.clientX;
y = e.clientY;
leftWidth = leftSide.getBoundingClientRect().width;
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
};
- When the knob is moving, based on the current and original mouse position, we know how far the mouse has been moved.
We then set the width for the left side:
const mouseMoveHandler = function (e) {
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:
const mouseUpHandler = function() {
...
document.removeEventListener('mousemove', mouseMoveHandler);
document.removeEventListener('mouseup', mouseUpHandler);
};
Use cases
Enjoy the demo!
Demo
See also