17 CSS Range Sliders06 / 17
Video Player Progress Bar Style
A premium streaming-style video seekbar with a hidden thumb that blooms on hover, a translucent timecode tooltip that tracks the thumb, a buffer indicator layer, and a full player control bar.
Published
The code
<div class="rs-06">
<div class="rs-06__player">
<div class="rs-06__thumbnail">
<div class="rs-06__play-btn" id="rs-06-playbtn">
<svg viewBox="0 0 24 24"><polygon points="5,3 19,12 5,21"/></svg>
</div>
<div class="rs-06__film-title">Neon Horizon</div>
<div class="rs-06__film-sub">2024 · Drama · 2h 07m</div>
</div>
<div class="rs-06__controls">
<div class="rs-06__seekbar" id="rs-06-seekbar">
<div class="rs-06__track-bg"></div>
<div class="rs-06__track-buffer" id="rs-06-buffer"></div>
<div class="rs-06__track-fill" id="rs-06-fill" style="width:32%"></div>
<input class="rs-06__input" type="range" min="0" max="7620" value="2438" id="rs-06-inp">
<div class="rs-06__thumb" id="rs-06-thumb" style="left:32%"></div>
<div class="rs-06__tooltip" id="rs-06-tip" style="left:32%">00:40:38</div>
</div>
<div class="rs-06__bottom">
<div class="rs-06__left-ctrl">
<button class="rs-06__ctrl-btn" aria-label="Play">
<svg viewBox="0 0 24 24"><polygon points="5,3 19,12 5,21"/></svg>
</button>
<button class="rs-06__ctrl-btn" aria-label="Skip">
<svg viewBox="0 0 24 24"><polygon points="5,4 15,12 5,20"/><line x1="19" y1="5" x2="19" y2="19" stroke="currentColor" stroke-width="2"/></svg>
</button>
<div class="rs-06__vol-wrap">
<button class="rs-06__ctrl-btn" aria-label="Volume">
<svg viewBox="0 0 24 24"><polygon points="11,5 6,9 2,9 2,15 6,15 11,19"/><path d="M19.07,4.93a10,10,0,0,1,0,14.14M15.54,8.46a5,5,0,0,1,0,7.07" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"/></svg>
</button>
<input class="rs-06__vol-input" type="range" min="0" max="100" value="80">
</div>
<div class="rs-06__time"><span id="rs-06-cur">40:38</span> / 2:07:00</div>
</div>
<button class="rs-06__ctrl-btn" aria-label="Fullscreen">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15,3 21,3 21,9"/><polyline points="9,21 3,21 3,15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>
</button>
</div>
</div>
</div>
</div><div class="rs-06">
<div class="rs-06__player">
<div class="rs-06__thumbnail">
<div class="rs-06__play-btn" id="rs-06-playbtn">
<svg viewBox="0 0 24 24"><polygon points="5,3 19,12 5,21"/></svg>
</div>
<div class="rs-06__film-title">Neon Horizon</div>
<div class="rs-06__film-sub">2024 · Drama · 2h 07m</div>
</div>
<div class="rs-06__controls">
<div class="rs-06__seekbar" id="rs-06-seekbar">
<div class="rs-06__track-bg"></div>
<div class="rs-06__track-buffer" id="rs-06-buffer"></div>
<div class="rs-06__track-fill" id="rs-06-fill" style="width:32%"></div>
<input class="rs-06__input" type="range" min="0" max="7620" value="2438" id="rs-06-inp">
<div class="rs-06__thumb" id="rs-06-thumb" style="left:32%"></div>
<div class="rs-06__tooltip" id="rs-06-tip" style="left:32%">00:40:38</div>
</div>
<div class="rs-06__bottom">
<div class="rs-06__left-ctrl">
<button class="rs-06__ctrl-btn" aria-label="Play">
<svg viewBox="0 0 24 24"><polygon points="5,3 19,12 5,21"/></svg>
</button>
<button class="rs-06__ctrl-btn" aria-label="Skip">
<svg viewBox="0 0 24 24"><polygon points="5,4 15,12 5,20"/><line x1="19" y1="5" x2="19" y2="19" stroke="currentColor" stroke-width="2"/></svg>
</button>
<div class="rs-06__vol-wrap">
<button class="rs-06__ctrl-btn" aria-label="Volume">
<svg viewBox="0 0 24 24"><polygon points="11,5 6,9 2,9 2,15 6,15 11,19"/><path d="M19.07,4.93a10,10,0,0,1,0,14.14M15.54,8.46a5,5,0,0,1,0,7.07" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"/></svg>
</button>
<input class="rs-06__vol-input" type="range" min="0" max="100" value="80">
</div>
<div class="rs-06__time"><span id="rs-06-cur">40:38</span> / 2:07:00</div>
</div>
<button class="rs-06__ctrl-btn" aria-label="Fullscreen">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15,3 21,3 21,9"/><polyline points="9,21 3,21 3,15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>
</button>
</div>
</div>
</div>
</div>.rs-06,
.rs-06 *,
.rs-06 *::before,
.rs-06 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.rs-06 ::selection {
background: #e50914;
color: #fff;
}
.rs-06 {
--bg: #141414;
--card: #1f1f1f;
--red: #e50914;
--red-glow: rgba(229,9,20,0.4);
--text: #ffffff;
--muted: #808080;
--track-h: 4px;
background: var(--bg);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 40px 24px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
.rs-06__player {
width: 100%;
max-width: 520px;
background: var(--card);
border-radius: 12px;
overflow: hidden;
}
.rs-06__thumbnail {
width: 100%;
aspect-ratio: 16/9;
background: linear-gradient(135deg, #0d0d0d 0%, #1a0a0a 40%, #2d0000 70%, #0d0d0d 100%);
position: relative;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
overflow: hidden;
}
.rs-06__thumbnail::before {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(ellipse at center, rgba(229,9,20,0.06) 0%, transparent 70%);
}
.rs-06__film-title {
position: absolute;
bottom: 20px;
left: 20px;
color: #fff;
font-size: 20px;
font-weight: 800;
text-shadow: 0 2px 12px rgba(0,0,0,0.8);
}
.rs-06__film-sub {
position: absolute;
bottom: 6px;
left: 20px;
color: var(--muted);
font-size: 12px;
}
.rs-06__play-btn {
width: 64px;
height: 64px;
background: rgba(229,9,20,0.85);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.2s, transform 0.2s;
cursor: pointer;
box-shadow: 0 0 40px var(--red-glow);
}
.rs-06__play-btn:hover {
background: var(--red);
transform: scale(1.08);
}
.rs-06__play-btn svg {
width: 26px;
height: 26px;
fill: #fff;
margin-left: 4px;
}
.rs-06__controls {
padding: 12px 16px 16px;
}
.rs-06__seekbar {
position: relative;
height: 20px;
display: flex;
align-items: center;
margin-bottom: 10px;
cursor: pointer;
}
.rs-06__seekbar:hover .rs-06__track-fill {
background: var(--red);
}
.rs-06__seekbar:hover .rs-06__thumb {
opacity: 1;
transform: translateY(-50%) translateX(-50%) scale(1);
}
.rs-06__track-bg {
position: absolute;
width: 100%;
height: var(--track-h);
background: rgba(255,255,255,0.2);
border-radius: 99px;
}
.rs-06__track-buffer {
position: absolute;
left: 0;
height: var(--track-h);
background: rgba(255,255,255,0.35);
border-radius: 99px;
width: 60%;
}
.rs-06__track-fill {
position: absolute;
left: 0;
height: var(--track-h);
background: var(--muted);
border-radius: 99px;
transition: background 0.2s, width 0.05s;
}
.rs-06__input {
position: absolute;
width: 100%;
-webkit-appearance: none;
appearance: none;
height: 20px;
background: transparent;
cursor: pointer;
outline: none;
z-index: 2;
}
.rs-06__input::-webkit-slider-thumb {
-webkit-appearance: none;
width: 0;
height: 0;
}
.rs-06__thumb {
position: absolute;
width: 14px;
height: 14px;
background: #fff;
border-radius: 50%;
top: 50%;
left: 0;
transform: translateY(-50%) translateX(-50%) scale(0);
pointer-events: none;
opacity: 0;
transition: opacity 0.2s, transform 0.2s;
box-shadow: 0 2px 8px rgba(0,0,0,0.5);
}
.rs-06__tooltip {
position: absolute;
bottom: calc(100% + 8px);
transform: translateX(-50%);
background: rgba(20,20,20,0.9);
color: #fff;
font-size: 11px;
font-weight: 600;
padding: 3px 8px;
border-radius: 4px;
pointer-events: none;
white-space: nowrap;
opacity: 0;
transition: opacity 0.2s;
backdrop-filter: blur(4px);
}
.rs-06__seekbar:hover .rs-06__tooltip {
opacity: 1;
}
.rs-06__bottom {
display: flex;
align-items: center;
gap: 12px;
justify-content: space-between;
}
.rs-06__left-ctrl {
display: flex;
align-items: center;
gap: 10px;
}
.rs-06__ctrl-btn {
background: none;
border: none;
color: #fff;
cursor: pointer;
padding: 4px;
opacity: 0.8;
transition: opacity 0.15s;
display: flex;
align-items: center;
}
.rs-06__ctrl-btn:hover {
opacity: 1;
}
.rs-06__ctrl-btn svg {
width: 20px;
height: 20px;
fill: currentColor;
}
.rs-06__time {
font-size: 12px;
color: var(--muted);
font-variant-numeric: tabular-nums;
}
.rs-06__time span {
color: #fff;
}
.rs-06__vol-wrap {
display: flex;
align-items: center;
gap: 6px;
}
.rs-06__vol-input {
width: 60px;
-webkit-appearance: none;
appearance: none;
height: 3px;
background: rgba(255,255,255,0.3);
border-radius: 99px;
outline: none;
cursor: pointer;
}
.rs-06__vol-input::-webkit-slider-thumb {
-webkit-appearance: none;
width: 10px;
height: 10px;
border-radius: 50%;
background: #fff;
}
@media (prefers-reduced-motion: reduce) {
.rs-06__track-fill,
.rs-06__thumb,
.rs-06__tooltip {
transition: none;
}
}.rs-06,
.rs-06 *,
.rs-06 *::before,
.rs-06 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.rs-06 ::selection {
background: #e50914;
color: #fff;
}
.rs-06 {
--bg: #141414;
--card: #1f1f1f;
--red: #e50914;
--red-glow: rgba(229,9,20,0.4);
--text: #ffffff;
--muted: #808080;
--track-h: 4px;
background: var(--bg);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 40px 24px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
.rs-06__player {
width: 100%;
max-width: 520px;
background: var(--card);
border-radius: 12px;
overflow: hidden;
}
.rs-06__thumbnail {
width: 100%;
aspect-ratio: 16/9;
background: linear-gradient(135deg, #0d0d0d 0%, #1a0a0a 40%, #2d0000 70%, #0d0d0d 100%);
position: relative;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
overflow: hidden;
}
.rs-06__thumbnail::before {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(ellipse at center, rgba(229,9,20,0.06) 0%, transparent 70%);
}
.rs-06__film-title {
position: absolute;
bottom: 20px;
left: 20px;
color: #fff;
font-size: 20px;
font-weight: 800;
text-shadow: 0 2px 12px rgba(0,0,0,0.8);
}
.rs-06__film-sub {
position: absolute;
bottom: 6px;
left: 20px;
color: var(--muted);
font-size: 12px;
}
.rs-06__play-btn {
width: 64px;
height: 64px;
background: rgba(229,9,20,0.85);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.2s, transform 0.2s;
cursor: pointer;
box-shadow: 0 0 40px var(--red-glow);
}
.rs-06__play-btn:hover {
background: var(--red);
transform: scale(1.08);
}
.rs-06__play-btn svg {
width: 26px;
height: 26px;
fill: #fff;
margin-left: 4px;
}
.rs-06__controls {
padding: 12px 16px 16px;
}
.rs-06__seekbar {
position: relative;
height: 20px;
display: flex;
align-items: center;
margin-bottom: 10px;
cursor: pointer;
}
.rs-06__seekbar:hover .rs-06__track-fill {
background: var(--red);
}
.rs-06__seekbar:hover .rs-06__thumb {
opacity: 1;
transform: translateY(-50%) translateX(-50%) scale(1);
}
.rs-06__track-bg {
position: absolute;
width: 100%;
height: var(--track-h);
background: rgba(255,255,255,0.2);
border-radius: 99px;
}
.rs-06__track-buffer {
position: absolute;
left: 0;
height: var(--track-h);
background: rgba(255,255,255,0.35);
border-radius: 99px;
width: 60%;
}
.rs-06__track-fill {
position: absolute;
left: 0;
height: var(--track-h);
background: var(--muted);
border-radius: 99px;
transition: background 0.2s, width 0.05s;
}
.rs-06__input {
position: absolute;
width: 100%;
-webkit-appearance: none;
appearance: none;
height: 20px;
background: transparent;
cursor: pointer;
outline: none;
z-index: 2;
}
.rs-06__input::-webkit-slider-thumb {
-webkit-appearance: none;
width: 0;
height: 0;
}
.rs-06__thumb {
position: absolute;
width: 14px;
height: 14px;
background: #fff;
border-radius: 50%;
top: 50%;
left: 0;
transform: translateY(-50%) translateX(-50%) scale(0);
pointer-events: none;
opacity: 0;
transition: opacity 0.2s, transform 0.2s;
box-shadow: 0 2px 8px rgba(0,0,0,0.5);
}
.rs-06__tooltip {
position: absolute;
bottom: calc(100% + 8px);
transform: translateX(-50%);
background: rgba(20,20,20,0.9);
color: #fff;
font-size: 11px;
font-weight: 600;
padding: 3px 8px;
border-radius: 4px;
pointer-events: none;
white-space: nowrap;
opacity: 0;
transition: opacity 0.2s;
backdrop-filter: blur(4px);
}
.rs-06__seekbar:hover .rs-06__tooltip {
opacity: 1;
}
.rs-06__bottom {
display: flex;
align-items: center;
gap: 12px;
justify-content: space-between;
}
.rs-06__left-ctrl {
display: flex;
align-items: center;
gap: 10px;
}
.rs-06__ctrl-btn {
background: none;
border: none;
color: #fff;
cursor: pointer;
padding: 4px;
opacity: 0.8;
transition: opacity 0.15s;
display: flex;
align-items: center;
}
.rs-06__ctrl-btn:hover {
opacity: 1;
}
.rs-06__ctrl-btn svg {
width: 20px;
height: 20px;
fill: currentColor;
}
.rs-06__time {
font-size: 12px;
color: var(--muted);
font-variant-numeric: tabular-nums;
}
.rs-06__time span {
color: #fff;
}
.rs-06__vol-wrap {
display: flex;
align-items: center;
gap: 6px;
}
.rs-06__vol-input {
width: 60px;
-webkit-appearance: none;
appearance: none;
height: 3px;
background: rgba(255,255,255,0.3);
border-radius: 99px;
outline: none;
cursor: pointer;
}
.rs-06__vol-input::-webkit-slider-thumb {
-webkit-appearance: none;
width: 10px;
height: 10px;
border-radius: 50%;
background: #fff;
}
@media (prefers-reduced-motion: reduce) {
.rs-06__track-fill,
.rs-06__thumb,
.rs-06__tooltip {
transition: none;
}
}(function(){
const inp = document.getElementById('rs-06-inp');
const fill = document.getElementById('rs-06-fill');
const thumb = document.getElementById('rs-06-thumb');
const tip = document.getElementById('rs-06-tip');
const cur = document.getElementById('rs-06-cur');
function fmt(s){ const m=Math.floor(s/60), sec=Math.floor(s%60); return m+':'+(sec<10?'0':'')+sec; }
function update(){
const v = +inp.value;
const pct = v/inp.max*100;
fill.style.width = pct+'%';
thumb.style.left = pct+'%';
tip.style.left = pct+'%';
tip.textContent = fmt(v);
cur.textContent = fmt(v);
}
inp.addEventListener('input', update);
update();
})();(function(){
const inp = document.getElementById('rs-06-inp');
const fill = document.getElementById('rs-06-fill');
const thumb = document.getElementById('rs-06-thumb');
const tip = document.getElementById('rs-06-tip');
const cur = document.getElementById('rs-06-cur');
function fmt(s){ const m=Math.floor(s/60), sec=Math.floor(s%60); return m+':'+(sec<10?'0':'')+sec; }
function update(){
const v = +inp.value;
const pct = v/inp.max*100;
fill.style.width = pct+'%';
thumb.style.left = pct+'%';
tip.style.left = pct+'%';
tip.textContent = fmt(v);
cur.textContent = fmt(v);
}
inp.addEventListener('input', update);
update();
})();Here's a working CSS Range Slider from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Video Player Progress Bar Style
Source: https://codefronts.com/components/css-range-sliders/video-player-progress-bar-style/
A premium streaming-style video seekbar with a hidden thumb that blooms on hover, a translucent timecode tooltip that tracks the thumb, a buffer indicator layer, and a full player control bar.
## HTML
```html
<div class="rs-06">
<div class="rs-06__player">
<div class="rs-06__thumbnail">
<div class="rs-06__play-btn" id="rs-06-playbtn">
<svg viewBox="0 0 24 24"><polygon points="5,3 19,12 5,21"/></svg>
</div>
<div class="rs-06__film-title">Neon Horizon</div>
<div class="rs-06__film-sub">2024 · Drama · 2h 07m</div>
</div>
<div class="rs-06__controls">
<div class="rs-06__seekbar" id="rs-06-seekbar">
<div class="rs-06__track-bg"></div>
<div class="rs-06__track-buffer" id="rs-06-buffer"></div>
<div class="rs-06__track-fill" id="rs-06-fill" style="width:32%"></div>
<input class="rs-06__input" type="range" min="0" max="7620" value="2438" id="rs-06-inp">
<div class="rs-06__thumb" id="rs-06-thumb" style="left:32%"></div>
<div class="rs-06__tooltip" id="rs-06-tip" style="left:32%">00:40:38</div>
</div>
<div class="rs-06__bottom">
<div class="rs-06__left-ctrl">
<button class="rs-06__ctrl-btn" aria-label="Play">
<svg viewBox="0 0 24 24"><polygon points="5,3 19,12 5,21"/></svg>
</button>
<button class="rs-06__ctrl-btn" aria-label="Skip">
<svg viewBox="0 0 24 24"><polygon points="5,4 15,12 5,20"/><line x1="19" y1="5" x2="19" y2="19" stroke="currentColor" stroke-width="2"/></svg>
</button>
<div class="rs-06__vol-wrap">
<button class="rs-06__ctrl-btn" aria-label="Volume">
<svg viewBox="0 0 24 24"><polygon points="11,5 6,9 2,9 2,15 6,15 11,19"/><path d="M19.07,4.93a10,10,0,0,1,0,14.14M15.54,8.46a5,5,0,0,1,0,7.07" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"/></svg>
</button>
<input class="rs-06__vol-input" type="range" min="0" max="100" value="80">
</div>
<div class="rs-06__time"><span id="rs-06-cur">40:38</span> / 2:07:00</div>
</div>
<button class="rs-06__ctrl-btn" aria-label="Fullscreen">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15,3 21,3 21,9"/><polyline points="9,21 3,21 3,15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>
</button>
</div>
</div>
</div>
</div>
```
## CSS
```css
.rs-06,
.rs-06 *,
.rs-06 *::before,
.rs-06 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.rs-06 ::selection {
background: #e50914;
color: #fff;
}
.rs-06 {
--bg: #141414;
--card: #1f1f1f;
--red: #e50914;
--red-glow: rgba(229,9,20,0.4);
--text: #ffffff;
--muted: #808080;
--track-h: 4px;
background: var(--bg);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 40px 24px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
.rs-06__player {
width: 100%;
max-width: 520px;
background: var(--card);
border-radius: 12px;
overflow: hidden;
}
.rs-06__thumbnail {
width: 100%;
aspect-ratio: 16/9;
background: linear-gradient(135deg, #0d0d0d 0%, #1a0a0a 40%, #2d0000 70%, #0d0d0d 100%);
position: relative;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
overflow: hidden;
}
.rs-06__thumbnail::before {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(ellipse at center, rgba(229,9,20,0.06) 0%, transparent 70%);
}
.rs-06__film-title {
position: absolute;
bottom: 20px;
left: 20px;
color: #fff;
font-size: 20px;
font-weight: 800;
text-shadow: 0 2px 12px rgba(0,0,0,0.8);
}
.rs-06__film-sub {
position: absolute;
bottom: 6px;
left: 20px;
color: var(--muted);
font-size: 12px;
}
.rs-06__play-btn {
width: 64px;
height: 64px;
background: rgba(229,9,20,0.85);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.2s, transform 0.2s;
cursor: pointer;
box-shadow: 0 0 40px var(--red-glow);
}
.rs-06__play-btn:hover {
background: var(--red);
transform: scale(1.08);
}
.rs-06__play-btn svg {
width: 26px;
height: 26px;
fill: #fff;
margin-left: 4px;
}
.rs-06__controls {
padding: 12px 16px 16px;
}
.rs-06__seekbar {
position: relative;
height: 20px;
display: flex;
align-items: center;
margin-bottom: 10px;
cursor: pointer;
}
.rs-06__seekbar:hover .rs-06__track-fill {
background: var(--red);
}
.rs-06__seekbar:hover .rs-06__thumb {
opacity: 1;
transform: translateY(-50%) translateX(-50%) scale(1);
}
.rs-06__track-bg {
position: absolute;
width: 100%;
height: var(--track-h);
background: rgba(255,255,255,0.2);
border-radius: 99px;
}
.rs-06__track-buffer {
position: absolute;
left: 0;
height: var(--track-h);
background: rgba(255,255,255,0.35);
border-radius: 99px;
width: 60%;
}
.rs-06__track-fill {
position: absolute;
left: 0;
height: var(--track-h);
background: var(--muted);
border-radius: 99px;
transition: background 0.2s, width 0.05s;
}
.rs-06__input {
position: absolute;
width: 100%;
-webkit-appearance: none;
appearance: none;
height: 20px;
background: transparent;
cursor: pointer;
outline: none;
z-index: 2;
}
.rs-06__input::-webkit-slider-thumb {
-webkit-appearance: none;
width: 0;
height: 0;
}
.rs-06__thumb {
position: absolute;
width: 14px;
height: 14px;
background: #fff;
border-radius: 50%;
top: 50%;
left: 0;
transform: translateY(-50%) translateX(-50%) scale(0);
pointer-events: none;
opacity: 0;
transition: opacity 0.2s, transform 0.2s;
box-shadow: 0 2px 8px rgba(0,0,0,0.5);
}
.rs-06__tooltip {
position: absolute;
bottom: calc(100% + 8px);
transform: translateX(-50%);
background: rgba(20,20,20,0.9);
color: #fff;
font-size: 11px;
font-weight: 600;
padding: 3px 8px;
border-radius: 4px;
pointer-events: none;
white-space: nowrap;
opacity: 0;
transition: opacity 0.2s;
backdrop-filter: blur(4px);
}
.rs-06__seekbar:hover .rs-06__tooltip {
opacity: 1;
}
.rs-06__bottom {
display: flex;
align-items: center;
gap: 12px;
justify-content: space-between;
}
.rs-06__left-ctrl {
display: flex;
align-items: center;
gap: 10px;
}
.rs-06__ctrl-btn {
background: none;
border: none;
color: #fff;
cursor: pointer;
padding: 4px;
opacity: 0.8;
transition: opacity 0.15s;
display: flex;
align-items: center;
}
.rs-06__ctrl-btn:hover {
opacity: 1;
}
.rs-06__ctrl-btn svg {
width: 20px;
height: 20px;
fill: currentColor;
}
.rs-06__time {
font-size: 12px;
color: var(--muted);
font-variant-numeric: tabular-nums;
}
.rs-06__time span {
color: #fff;
}
.rs-06__vol-wrap {
display: flex;
align-items: center;
gap: 6px;
}
.rs-06__vol-input {
width: 60px;
-webkit-appearance: none;
appearance: none;
height: 3px;
background: rgba(255,255,255,0.3);
border-radius: 99px;
outline: none;
cursor: pointer;
}
.rs-06__vol-input::-webkit-slider-thumb {
-webkit-appearance: none;
width: 10px;
height: 10px;
border-radius: 50%;
background: #fff;
}
@media (prefers-reduced-motion: reduce) {
.rs-06__track-fill,
.rs-06__thumb,
.rs-06__tooltip {
transition: none;
}
}
```
## JavaScript
```js
(function(){
const inp = document.getElementById('rs-06-inp');
const fill = document.getElementById('rs-06-fill');
const thumb = document.getElementById('rs-06-thumb');
const tip = document.getElementById('rs-06-tip');
const cur = document.getElementById('rs-06-cur');
function fmt(s){ const m=Math.floor(s/60), sec=Math.floor(s%60); return m+':'+(sec<10?'0':'')+sec; }
function update(){
const v = +inp.value;
const pct = v/inp.max*100;
fill.style.width = pct+'%';
thumb.style.left = pct+'%';
tip.style.left = pct+'%';
tip.textContent = fmt(v);
cur.textContent = fmt(v);
}
inp.addEventListener('input', update);
update();
})();
```Here's a working CSS Range Slider from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Video Player Progress Bar Style
Source: https://codefronts.com/components/css-range-sliders/video-player-progress-bar-style/
A premium streaming-style video seekbar with a hidden thumb that blooms on hover, a translucent timecode tooltip that tracks the thumb, a buffer indicator layer, and a full player control bar.
## HTML
```html
<div class="rs-06">
<div class="rs-06__player">
<div class="rs-06__thumbnail">
<div class="rs-06__play-btn" id="rs-06-playbtn">
<svg viewBox="0 0 24 24"><polygon points="5,3 19,12 5,21"/></svg>
</div>
<div class="rs-06__film-title">Neon Horizon</div>
<div class="rs-06__film-sub">2024 · Drama · 2h 07m</div>
</div>
<div class="rs-06__controls">
<div class="rs-06__seekbar" id="rs-06-seekbar">
<div class="rs-06__track-bg"></div>
<div class="rs-06__track-buffer" id="rs-06-buffer"></div>
<div class="rs-06__track-fill" id="rs-06-fill" style="width:32%"></div>
<input class="rs-06__input" type="range" min="0" max="7620" value="2438" id="rs-06-inp">
<div class="rs-06__thumb" id="rs-06-thumb" style="left:32%"></div>
<div class="rs-06__tooltip" id="rs-06-tip" style="left:32%">00:40:38</div>
</div>
<div class="rs-06__bottom">
<div class="rs-06__left-ctrl">
<button class="rs-06__ctrl-btn" aria-label="Play">
<svg viewBox="0 0 24 24"><polygon points="5,3 19,12 5,21"/></svg>
</button>
<button class="rs-06__ctrl-btn" aria-label="Skip">
<svg viewBox="0 0 24 24"><polygon points="5,4 15,12 5,20"/><line x1="19" y1="5" x2="19" y2="19" stroke="currentColor" stroke-width="2"/></svg>
</button>
<div class="rs-06__vol-wrap">
<button class="rs-06__ctrl-btn" aria-label="Volume">
<svg viewBox="0 0 24 24"><polygon points="11,5 6,9 2,9 2,15 6,15 11,19"/><path d="M19.07,4.93a10,10,0,0,1,0,14.14M15.54,8.46a5,5,0,0,1,0,7.07" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"/></svg>
</button>
<input class="rs-06__vol-input" type="range" min="0" max="100" value="80">
</div>
<div class="rs-06__time"><span id="rs-06-cur">40:38</span> / 2:07:00</div>
</div>
<button class="rs-06__ctrl-btn" aria-label="Fullscreen">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15,3 21,3 21,9"/><polyline points="9,21 3,21 3,15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>
</button>
</div>
</div>
</div>
</div>
```
## CSS
```css
.rs-06,
.rs-06 *,
.rs-06 *::before,
.rs-06 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.rs-06 ::selection {
background: #e50914;
color: #fff;
}
.rs-06 {
--bg: #141414;
--card: #1f1f1f;
--red: #e50914;
--red-glow: rgba(229,9,20,0.4);
--text: #ffffff;
--muted: #808080;
--track-h: 4px;
background: var(--bg);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 40px 24px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
.rs-06__player {
width: 100%;
max-width: 520px;
background: var(--card);
border-radius: 12px;
overflow: hidden;
}
.rs-06__thumbnail {
width: 100%;
aspect-ratio: 16/9;
background: linear-gradient(135deg, #0d0d0d 0%, #1a0a0a 40%, #2d0000 70%, #0d0d0d 100%);
position: relative;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
overflow: hidden;
}
.rs-06__thumbnail::before {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(ellipse at center, rgba(229,9,20,0.06) 0%, transparent 70%);
}
.rs-06__film-title {
position: absolute;
bottom: 20px;
left: 20px;
color: #fff;
font-size: 20px;
font-weight: 800;
text-shadow: 0 2px 12px rgba(0,0,0,0.8);
}
.rs-06__film-sub {
position: absolute;
bottom: 6px;
left: 20px;
color: var(--muted);
font-size: 12px;
}
.rs-06__play-btn {
width: 64px;
height: 64px;
background: rgba(229,9,20,0.85);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.2s, transform 0.2s;
cursor: pointer;
box-shadow: 0 0 40px var(--red-glow);
}
.rs-06__play-btn:hover {
background: var(--red);
transform: scale(1.08);
}
.rs-06__play-btn svg {
width: 26px;
height: 26px;
fill: #fff;
margin-left: 4px;
}
.rs-06__controls {
padding: 12px 16px 16px;
}
.rs-06__seekbar {
position: relative;
height: 20px;
display: flex;
align-items: center;
margin-bottom: 10px;
cursor: pointer;
}
.rs-06__seekbar:hover .rs-06__track-fill {
background: var(--red);
}
.rs-06__seekbar:hover .rs-06__thumb {
opacity: 1;
transform: translateY(-50%) translateX(-50%) scale(1);
}
.rs-06__track-bg {
position: absolute;
width: 100%;
height: var(--track-h);
background: rgba(255,255,255,0.2);
border-radius: 99px;
}
.rs-06__track-buffer {
position: absolute;
left: 0;
height: var(--track-h);
background: rgba(255,255,255,0.35);
border-radius: 99px;
width: 60%;
}
.rs-06__track-fill {
position: absolute;
left: 0;
height: var(--track-h);
background: var(--muted);
border-radius: 99px;
transition: background 0.2s, width 0.05s;
}
.rs-06__input {
position: absolute;
width: 100%;
-webkit-appearance: none;
appearance: none;
height: 20px;
background: transparent;
cursor: pointer;
outline: none;
z-index: 2;
}
.rs-06__input::-webkit-slider-thumb {
-webkit-appearance: none;
width: 0;
height: 0;
}
.rs-06__thumb {
position: absolute;
width: 14px;
height: 14px;
background: #fff;
border-radius: 50%;
top: 50%;
left: 0;
transform: translateY(-50%) translateX(-50%) scale(0);
pointer-events: none;
opacity: 0;
transition: opacity 0.2s, transform 0.2s;
box-shadow: 0 2px 8px rgba(0,0,0,0.5);
}
.rs-06__tooltip {
position: absolute;
bottom: calc(100% + 8px);
transform: translateX(-50%);
background: rgba(20,20,20,0.9);
color: #fff;
font-size: 11px;
font-weight: 600;
padding: 3px 8px;
border-radius: 4px;
pointer-events: none;
white-space: nowrap;
opacity: 0;
transition: opacity 0.2s;
backdrop-filter: blur(4px);
}
.rs-06__seekbar:hover .rs-06__tooltip {
opacity: 1;
}
.rs-06__bottom {
display: flex;
align-items: center;
gap: 12px;
justify-content: space-between;
}
.rs-06__left-ctrl {
display: flex;
align-items: center;
gap: 10px;
}
.rs-06__ctrl-btn {
background: none;
border: none;
color: #fff;
cursor: pointer;
padding: 4px;
opacity: 0.8;
transition: opacity 0.15s;
display: flex;
align-items: center;
}
.rs-06__ctrl-btn:hover {
opacity: 1;
}
.rs-06__ctrl-btn svg {
width: 20px;
height: 20px;
fill: currentColor;
}
.rs-06__time {
font-size: 12px;
color: var(--muted);
font-variant-numeric: tabular-nums;
}
.rs-06__time span {
color: #fff;
}
.rs-06__vol-wrap {
display: flex;
align-items: center;
gap: 6px;
}
.rs-06__vol-input {
width: 60px;
-webkit-appearance: none;
appearance: none;
height: 3px;
background: rgba(255,255,255,0.3);
border-radius: 99px;
outline: none;
cursor: pointer;
}
.rs-06__vol-input::-webkit-slider-thumb {
-webkit-appearance: none;
width: 10px;
height: 10px;
border-radius: 50%;
background: #fff;
}
@media (prefers-reduced-motion: reduce) {
.rs-06__track-fill,
.rs-06__thumb,
.rs-06__tooltip {
transition: none;
}
}
```
## JavaScript
```js
(function(){
const inp = document.getElementById('rs-06-inp');
const fill = document.getElementById('rs-06-fill');
const thumb = document.getElementById('rs-06-thumb');
const tip = document.getElementById('rs-06-tip');
const cur = document.getElementById('rs-06-cur');
function fmt(s){ const m=Math.floor(s/60), sec=Math.floor(s%60); return m+':'+(sec<10?'0':'')+sec; }
function update(){
const v = +inp.value;
const pct = v/inp.max*100;
fill.style.width = pct+'%';
thumb.style.left = pct+'%';
tip.style.left = pct+'%';
tip.textContent = fmt(v);
cur.textContent = fmt(v);
}
inp.addEventListener('input', update);
update();
})();
```How this works
The seekbar uses three stacked layers: a grey buffer track, a white fill div, and a fully transparent native <input type="range"> on top. The native thumb is sized to width:0; height:0 so it is completely invisible — interaction is captured by the transparent input but the visual thumb is a separate .rs-06__thumb div repositioned via JavaScript as a percentage of the track width. On :hover of the seekbar container, the fill turns red (var(--red)) and the thumb transitions from scale(0) to scale(1) with opacity.
The tooltip div also tracks thumb position via left: pct% and is kept visible only on hover via a CSS selector rule on the parent. A fmt() function converts the integer second value (0–7620 = 2h7m) into M:SS format using modulo arithmetic, shown in both the tooltip and the current time display. The volume slider uses standard thumb styling as a secondary control.
Make it yours
- Change the accent from Netflix red to any brand color by editing
--red: #e50914— the fill and play button automatically inherit the variable. - Add chapter markers to the seekbar by absolutely positioning small vertical tick divs at specific time percentages, giving each a
titleattribute for browser tooltip fallback. - Make the seekbar always show the thumb (not just on hover) by removing the
opacity: 0andtransform: scale(0)defaults from.rs-06__thumb. - Connect a real HTML5
<video>element by listening tovideo.timeupdateand syncinginp.value = video.currentTime, and on input setvideo.currentTime = inp.value. - Render a miniature preview thumbnail on hover by positioning an absolutely placed
<img>above the tooltip and updating itssrcfrom a sprite sheet based on the hovered time.
Gotchas — read before shipping
- The invisible native thumb still captures pointer events and has a large hit area — if the seekbar feels unresponsive at the edges, add
padding: 0 8pxto the input and compensate in percentage calculations. - The timecode format uses a simple
M:SSpattern — for content over 60 minutes, update thefmt()function to produceH:MM:SSformat to avoid showing times like "127:42". - Safari renders
opacity: 0transitions on pseudo-elements differently — if the hover thumb bloom effect is missing on Safari, apply the transition to the wrapper div instead of the thumb pseudo-element.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 80+ | 14+ | 78+ | 80+ |
Hiding the native thumb via zero dimensions works in Chrome/Safari; Firefox may show a faint ghost thumb requiring additional -moz-range-thumb background:transparent.