I created a range slider using just a single div with ::pseudo elements since I cannot access ::pseudo directly with JavaScript I took help of CSS variables. But there are certain problems I faced along and was not able to solve.
With max-width
const range = document.querySelector(".range");
function setRange(event) {
const rect = range.getBoundingClientRect();
range.style.setProperty(
"--progress",
`${(event.clientX / rect.width) * 100}%`
);
}
range.addEventListener("pointerdown", (event) => {
range.classList.add("active");
range.setPointerCapture(event.pointerId);
setRange(event);
range.addEventListener("pointermove", setRange);
range.addEventListener(
"pointerup",
(event) => {
range.classList.remove("active");
range.releasePointerCapture(event.pointerId);
range.removeEventListener("pointermove", setRange);
}, {
once: true
}
);
});
@import "https://cdn.jsdelivr.net/gh/KunalTanwar/normalize/css/normalize.inter.min.css";
body {
height: 100%;
display: grid;
place-items: center;
}
.range {
width: 100%;
cursor: pointer;
height: 0.25rem;
max-width: 450px;
border-radius: 60rem;
background-color: rgba(120, 120, 128, 0.2);
}
.range::before,
.range::after {
content: "";
position: absolute;
}
.range::before {
width: var(--progress);
height: 100%;
border-radius: inherit;
background-color: #007aff;
}
.range::after {
top: 50%;
cursor: grab;
width: 1.75rem;
height: 1.75rem;
border-radius: 50%;
aspect-ratio: 1/1;
left: var(--progress);
background-color: white;
transform: translate(-50%, -50%);
box-shadow: 0px 0.5px 4px rgba(0, 0, 0, 0.12), 0px 6px 13px rgba(0, 0, 0, 0.12);
}
.range.active {
cursor: grabbing;
}
<div class="range"></div>
Without max-width
const range = document.querySelector(".range");
function setRange(event) {
const rect = range.getBoundingClientRect();
range.style.setProperty(
"--progress",
`${(event.clientX / rect.width) * 100}%`
);
}
range.addEventListener("pointerdown", (event) => {
range.classList.add("active");
range.setPointerCapture(event.pointerId);
setRange(event);
range.addEventListener("pointermove", setRange);
range.addEventListener(
"pointerup",
(event) => {
range.classList.remove("active");
range.releasePointerCapture(event.pointerId);
range.removeEventListener("pointermove", setRange);
}, {
once: true
}
);
});
@import "https://cdn.jsdelivr.net/gh/KunalTanwar/normalize/css/normalize.inter.min.css";
body {
height: 100%;
display: grid;
place-items: center;
}
.range {
width: 100%;
cursor: pointer;
height: 0.25rem;
border-radius: 60rem;
background-color: rgba(120, 120, 128, 0.2);
}
.range::before,
.range::after {
content: "";
position: absolute;
}
.range::before {
width: var(--progress);
height: 100%;
border-radius: inherit;
background-color: #007aff;
}
.range::after {
top: 50%;
cursor: grab;
width: 1.75rem;
height: 1.75rem;
border-radius: 50%;
aspect-ratio: 1/1;
left: var(--progress);
background-color: white;
transform: translate(-50%, -50%);
box-shadow: 0px 0.5px 4px rgba(0, 0, 0, 0.12), 0px 6px 13px rgba(0, 0, 0, 0.12);
}
.range.active {
cursor: grabbing;
}
<div class="range"></div>
My Approach
What my initial thought was that I will put an if condition inside setRange() function :
function setRange(event) {
const rect = range.getBoundingClientRect();
if (
!(window.getComputedStyle(range).getPropertyValue("--progress") > "100%")
) {
range.style.setProperty(
"--progress",
`${(event.clientX / rect.width) * 100}%`
);
}
}
But the above code is not working after first pointerdown although when I am console logging the if condition it is working just fine.
I also tried :
if (!(parseFloat(window.getComputedStyle(range).getPropertyValue('--progress')) > 100)) {
range.style.setProperty('--progress', `${(event.clientX / rect.width) * 100}%`)
}
and again after reaching 100% I am not able to move it back to below 100% in simple words I can't move the slider after reaching 100%.
There are 2 main questions
- Why after setting
max-widththe range slider not working like it should. - Why the
ifcondition I put insidesetRange()working onconsole.log()not inside DOM? - How can I set
max-valueofvar(--progress)so it should not increase beyond 100% ?
P.S - suggest an appropriate title for this question!