<input type="range" id="range">
<p style="position: absolute;bottom: 0;left: 0;z-index: 1;">Forked from <a href="https://codepen.io/kizu/pen/RwvLBqM">https://codepen.io/kizu/pen/RwvLBqM</a> by Roman Komarov</p>
@layer demo {
@supports (timeline-scope: --foo) {
input[type="range"] {
/* only destroy the default look and do a gradient trick if @supports */
appearance: none;
background: none;
inline-size: 75vw;
/* animate an @property from 0-100% */
animation: --range-observer linear reverse;
/* drive the animation to the thumb intersection with the input track */
/* track is a timeline because overflow-x is on it, and the thumb is a child of track */
animation-timeline: --range-thumb;
/* this allows a parent to observe the timeline of a child */
timeline-scope: --range-thumb;
/* thumb creates a timeline of its inline intersection */
&::-webkit-slider-thumb {
view-timeline: --range-thumb inline;
}
/* this width = the animation range = the input's inline-size */
&::-webkit-slider-runnable-track {
/* turn track into a scrollport for intersection observation */
overflow-x: auto;
/* use the @property progress value in a gradient */
background:
linear-gradient(to right in oklab,
oklch(55% .4 350),
/* --range-value stops the gradient at the thumb position */
oklch(90% .3 95) var(--range-value, 50%),
/* and finishes the gradient with a solid track fill */
oklch(from #aaa calc(l * .5) c h) 0
);
/* all that work just to set a % for a gradient stop.. 😅 */
}
}
}
@property --range-value {
syntax: "<percentage>";
initial-value: 0%;
inherits: true;
}
@keyframes --range-observer {
to { --range-value: 100% }
}
input[type="range"] {
--size: 24px;
&::-webkit-slider-thumb {
appearance: none;
cursor: pointer;
width: var(--size);
height: var(--size);
border-radius: 1e3px;
background-color: white;
}
&::-webkit-slider-runnable-track {
/* this gives the thumb breathing room by shrinking and scootin down a bit */
background-size: 100% calc(var(--size) / 2);
background-position-y: calc(var(--size) / 4);
background-repeat: no-repeat;
}
&::-moz-range-thumb {
appearance: none;
width: 24px;
height: 24px;
border-radius: 1e3px;
background-color: CanvasText;
}
}
}
@layer demo.support {
* {
box-sizing: border-box;
margin: 0;
}
html {
block-size: 100%;
color-scheme: dark light;
@media (prefers-color-scheme: light) {
background-color: #ddd;
}
}
body {
min-block-size: 100%;
font-family: system-ui, sans-serif;
display: grid;
place-content: center;
}
}
body::after {
content: "Using JS; try in Chrome";
position: absolute;
top: 0;
left: 0;
pointer-events: none;
}
@supports (timeline-scope: --foo) {
body::after {
content: "Using Scroll-driven animations";
}
}
if (!CSS.supports('timeline-scope', '--foo')) {
range.oninput = () =>
document.body.style.setProperty('--range-value', range.value + '%')
}
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.