17 / 17
All 17 in 17 Tailwind CSS Range Sliders
- 01Tailwind CSS Dual-Handle Price Range Slider with Live Product Count
- 02Tailwind CSS Neumorphic Volume Slider with Soft UI Shadows
- 03Tailwind CSS Neon Glow Range Slider for Dark Mode UI
- 04Tailwind CSS Emoji Mood Slider for Feedback & CSAT Surveys
- 05Tailwind CSS Multi-Step Pricing Slider with Snapping Milestones
- 06Tailwind CSS Video Player Seekbar with Hover Scrub & Chapters
- 07Tailwind CSS Vertical Range Sliders — 10-Band Audio Equalizer
- 08Tailwind CSS Circular Dial Range Input — Smart Thermostat UI
- 09Tailwind CSS Gradient Range Slider with Progress Milestones
- 10Tailwind CSS Range Slider with Pop-Up Value Bubble (Loan Calculator)
- 11Tailwind CSS Brutalist Range Slider with Thick Block Track
- 12Tailwind CSS Password Strength Meter with Range Slider Control
- 13Tailwind CSS Centre-Origin Balance Slider for Audio Pan Control
- 14Tailwind CSS Retro 8-Bit Pixel Art Range Slider (Game HP Bar)
- 15Tailwind CSS Isometric 3D Range Slider with Perspective Plane
- 16Tailwind CSS Glassmorphism Range Sliders — RGBA Colour Mixer
- 17Tailwind CSS Liquid Glass Slider with Gooey Morphing Value Bubble
Tailwind CSS Liquid Glass Slider with Gooey Morphing Value Bubble
The iOS-style fluid control: the value bubble grows out of the track itself, fused by a gooey SVG filter, then floats over the thumb as you drag. Everything except the filter primitives is a utility — and the show condition is has-[input:active]:, so hover, drag, and keyboard focus all trigger the same morph.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="trs-17 w-full min-h-svh grid place-items-center px-6 py-10 font-trs17-sans" id="trs-17-root" style="--v:.6">
<svg class="absolute size-0" aria-hidden="true"><filter id="trs-17-goo"><feGaussianBlur in="SourceGraphic" stdDeviation="6" result="b"/><feColorMatrix in="b" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 22 -9"/></filter></svg>
<article class="w-[min(370px,100%)] rounded-3xl isolate p-6 text-white bg-white/11 border border-white/35 backdrop-blur-[22px] saturate-180 shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_-30px_oklch(0_0_0/0.7)]">
<header class="flex items-baseline justify-between gap-3 mb-2">
<h3 class="text-base font-extrabold tracking-wide m-0">Display</h3>
<span class="text-[11px] font-semibold text-white/60">Drag the thumb →</span>
</header>
<div class="mt-3.5">
<div class="flex items-center justify-between gap-2 mb-3">
<label for="trs-17-input" class="inline-flex items-center gap-1.5 text-[13px] font-semibold text-white/90"><span aria-hidden="true">☀︎</span> Brightness</label>
<span class="text-sm font-extrabold tabular-nums min-w-[3ch] text-right" id="trs-17-out">60</span>
</div>
<div class="group/slider relative h-8 flex items-center has-[input:focus-visible]:outline-2 has-[input:focus-visible]:outline-offset-6 has-[input:focus-visible]:outline-white rounded-full">
<div class="absolute inset-x-0 h-2 rounded-full bg-white/16 border border-white/25" aria-hidden="true"></div>
<span class="absolute inset-0 [filter:url(#trs-17-goo)] pointer-events-none" aria-hidden="true">
<span class="absolute left-0 top-1/2 -translate-y-1/2 h-2 rounded-full w-[calc(var(--v)*100%)] bg-gradient-to-r from-trs17-acc/60 to-trs17-acc shadow-[0_0_12px_-2px_var(--color-trs17-acc)]"></span>
<span class="absolute top-1/2 left-[calc(var(--v)*100%)] -translate-x-1/2 -translate-y-1/2 grid place-items-center size-5.5 rounded-full text-[0px] text-[#3a2a05] font-extrabold bg-[radial-gradient(circle_at_35%_30%,#fff,var(--color-trs17-acc))] border border-white/60 shadow-[inset_0_2px_4px_oklch(1_0_0/0.9),inset_0_-3px_5px_oklch(0_0_0/0.18),0_6px_14px_oklch(0_0_0/0.35)] transition-[width,height,font-size] duration-250 ease-[cubic-bezier(0.34,1.6,0.5,1)] group-hover/slider:size-8 group-hover/slider:text-[12px] group-has-[input:active]/slider:size-8 group-has-[input:active]/slider:text-[12px] group-has-[input:focus-visible]/slider:size-8 group-has-[input:focus-visible]/slider:text-[12px] motion-reduce:transition-none" id="trs-17-bubble">60</span>
</span>
<input type="range" min="0" max="100" value="60" id="trs-17-input" aria-label="Brightness"
class="absolute inset-0 w-full h-full m-0 appearance-none bg-transparent opacity-0 cursor-pointer z-10">
</div>
</div>
</article>
</section><section class="trs-17 w-full min-h-svh grid place-items-center px-6 py-10 font-trs17-sans" id="trs-17-root" style="--v:.6">
<svg class="absolute size-0" aria-hidden="true"><filter id="trs-17-goo"><feGaussianBlur in="SourceGraphic" stdDeviation="6" result="b"/><feColorMatrix in="b" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 22 -9"/></filter></svg>
<article class="w-[min(370px,100%)] rounded-3xl isolate p-6 text-white bg-white/11 border border-white/35 backdrop-blur-[22px] saturate-180 shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_-30px_oklch(0_0_0/0.7)]">
<header class="flex items-baseline justify-between gap-3 mb-2">
<h3 class="text-base font-extrabold tracking-wide m-0">Display</h3>
<span class="text-[11px] font-semibold text-white/60">Drag the thumb →</span>
</header>
<div class="mt-3.5">
<div class="flex items-center justify-between gap-2 mb-3">
<label for="trs-17-input" class="inline-flex items-center gap-1.5 text-[13px] font-semibold text-white/90"><span aria-hidden="true">☀︎</span> Brightness</label>
<span class="text-sm font-extrabold tabular-nums min-w-[3ch] text-right" id="trs-17-out">60</span>
</div>
<div class="group/slider relative h-8 flex items-center has-[input:focus-visible]:outline-2 has-[input:focus-visible]:outline-offset-6 has-[input:focus-visible]:outline-white rounded-full">
<div class="absolute inset-x-0 h-2 rounded-full bg-white/16 border border-white/25" aria-hidden="true"></div>
<span class="absolute inset-0 [filter:url(#trs-17-goo)] pointer-events-none" aria-hidden="true">
<span class="absolute left-0 top-1/2 -translate-y-1/2 h-2 rounded-full w-[calc(var(--v)*100%)] bg-gradient-to-r from-trs17-acc/60 to-trs17-acc shadow-[0_0_12px_-2px_var(--color-trs17-acc)]"></span>
<span class="absolute top-1/2 left-[calc(var(--v)*100%)] -translate-x-1/2 -translate-y-1/2 grid place-items-center size-5.5 rounded-full text-[0px] text-[#3a2a05] font-extrabold bg-[radial-gradient(circle_at_35%_30%,#fff,var(--color-trs17-acc))] border border-white/60 shadow-[inset_0_2px_4px_oklch(1_0_0/0.9),inset_0_-3px_5px_oklch(0_0_0/0.18),0_6px_14px_oklch(0_0_0/0.35)] transition-[width,height,font-size] duration-250 ease-[cubic-bezier(0.34,1.6,0.5,1)] group-hover/slider:size-8 group-hover/slider:text-[12px] group-has-[input:active]/slider:size-8 group-has-[input:active]/slider:text-[12px] group-has-[input:focus-visible]/slider:size-8 group-has-[input:focus-visible]/slider:text-[12px] motion-reduce:transition-none" id="trs-17-bubble">60</span>
</span>
<input type="range" min="0" max="100" value="60" id="trs-17-input" aria-label="Brightness"
class="absolute inset-0 w-full h-full m-0 appearance-none bg-transparent opacity-0 cursor-pointer z-10">
</div>
</div>
</article>
</section>@import "tailwindcss";
@theme {
--color-trs17-acc: #f0b429;
--color-trs17-acc: oklch(0.8 0.17 65);
--font-trs17-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
@property --v {
syntax: "<number>";
inherits: true;
initial-value: 0.6;
}
.trs-17 {
transition: --v 75ms linear;
}
@media (prefers-reduced-motion: reduce) {
.trs-17 {
transition: none;
}
}
.trs-17 {
width: 100%;
min-height: 100svh;
background: radial-gradient(120% 120% at 70% 20%, #1e293b, #0f172a 70%);
}
/* The native thumb is a transparent hit target: the visible bubble is the
glass span inside the gooey group. */
.trs-17 input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 32px;
height: 32px;
border-radius: 9999px;
background: transparent;
cursor: grab;
}
.trs-17 input[type="range"]:active::-webkit-slider-thumb {
cursor: grabbing;
}
.trs-17 input[type="range"]::-moz-range-thumb {
width: 32px;
height: 32px;
border: 0;
border-radius: 9999px;
background: transparent;
cursor: grab;
}@import "tailwindcss";
@theme {
--color-trs17-acc: #f0b429;
--color-trs17-acc: oklch(0.8 0.17 65);
--font-trs17-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
@property --v {
syntax: "<number>";
inherits: true;
initial-value: 0.6;
}
.trs-17 {
transition: --v 75ms linear;
}
@media (prefers-reduced-motion: reduce) {
.trs-17 {
transition: none;
}
}
.trs-17 {
width: 100%;
min-height: 100svh;
background: radial-gradient(120% 120% at 70% 20%, #1e293b, #0f172a 70%);
}
/* The native thumb is a transparent hit target: the visible bubble is the
glass span inside the gooey group. */
.trs-17 input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 32px;
height: 32px;
border-radius: 9999px;
background: transparent;
cursor: grab;
}
.trs-17 input[type="range"]:active::-webkit-slider-thumb {
cursor: grabbing;
}
.trs-17 input[type="range"]::-moz-range-thumb {
width: 32px;
height: 32px;
border: 0;
border-radius: 9999px;
background: transparent;
cursor: grab;
}(function(){
var root = document.getElementById('trs-17-root');
var inp = document.getElementById('trs-17-input');
var bubble = document.getElementById('trs-17-bubble');
var out = document.getElementById('trs-17-out');
function update(){
var v = +inp.value;
root.style.setProperty('--v', v / 100);
bubble.textContent = v;
out.textContent = v;
inp.setAttribute('aria-valuetext', v + ' percent brightness');
}
inp.addEventListener('input', update);
update();
})();(function(){
var root = document.getElementById('trs-17-root');
var inp = document.getElementById('trs-17-input');
var bubble = document.getElementById('trs-17-bubble');
var out = document.getElementById('trs-17-out');
function update(){
var v = +inp.value;
root.style.setProperty('--v', v / 100);
bubble.textContent = v;
out.textContent = v;
inp.setAttribute('aria-valuetext', v + ' percent brightness');
}
inp.addEventListener('input', update);
update();
})();Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-trs17-acc: #f0b429;
--color-trs17-acc: oklch(0.8 0.17 65);
--font-trs17-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
@property --v {
syntax: "<number>";
inherits: true;
initial-value: 0.6;
}
.trs-17 {
transition: --v 75ms linear;
}
@media (prefers-reduced-motion: reduce) {
.trs-17 {
transition: none;
}
}
.trs-17 {
width: 100%;
min-height: 100svh;
background: radial-gradient(120% 120% at 70% 20%, #1e293b, #0f172a 70%);
}
/* The native thumb is a transparent hit target: the visible bubble is the
glass span inside the gooey group. */
.trs-17 input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 32px;
height: 32px;
border-radius: 9999px;
background: transparent;
cursor: grab;
}
.trs-17 input[type="range"]:active::-webkit-slider-thumb {
cursor: grabbing;
}
.trs-17 input[type="range"]::-moz-range-thumb {
width: 32px;
height: 32px;
border: 0;
border-radius: 9999px;
background: transparent;
cursor: grab;
}@import "tailwindcss";
@theme {
--color-trs17-acc: #f0b429;
--color-trs17-acc: oklch(0.8 0.17 65);
--font-trs17-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
@property --v {
syntax: "<number>";
inherits: true;
initial-value: 0.6;
}
.trs-17 {
transition: --v 75ms linear;
}
@media (prefers-reduced-motion: reduce) {
.trs-17 {
transition: none;
}
}
.trs-17 {
width: 100%;
min-height: 100svh;
background: radial-gradient(120% 120% at 70% 20%, #1e293b, #0f172a 70%);
}
/* The native thumb is a transparent hit target: the visible bubble is the
glass span inside the gooey group. */
.trs-17 input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 32px;
height: 32px;
border-radius: 9999px;
background: transparent;
cursor: grab;
}
.trs-17 input[type="range"]:active::-webkit-slider-thumb {
cursor: grabbing;
}
.trs-17 input[type="range"]::-moz-range-thumb {
width: 32px;
height: 32px;
border: 0;
border-radius: 9999px;
background: transparent;
cursor: grab;
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@500;700;800&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@500;700;800&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The
.slider:has(input:active) .bubbleselector trio becamegroup-has-[input:active]/slider:utilities on the bubble — same relational logic, stated on the element that morphs. - Size, position and label reveal are one transition on one element (
transition-[width,height,font-size]), so the label cannot appear before the bubble has room for it. - UI upgrade: the focus-visible ring moved to the slider group via
has-[input:focus-visible]:outline-2, so keyboard users get the same morph and a visible ring around the whole control rather than a bare input outline.
Here's a working CSS demo 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: Tailwind CSS Liquid Glass Slider with Gooey Morphing Value Bubble
Source: https://codefronts.com/components/tailwind-css-range-sliders/tailwind-liquid-glass-slider-gooey-value-bubble/
The iOS-style fluid control: the value bubble grows out of the track itself, fused by a gooey SVG filter, then floats over the thumb as you drag. Everything except the filter primitives is a utility — and the show condition is has-[input:active]:, so hover, drag, and keyboard focus all trigger the same morph.
## HTML
```html
<section class="trs-17 w-full min-h-svh grid place-items-center px-6 py-10 font-trs17-sans" id="trs-17-root" style="--v:.6">
<svg class="absolute size-0" aria-hidden="true"><filter id="trs-17-goo"><feGaussianBlur in="SourceGraphic" stdDeviation="6" result="b"/><feColorMatrix in="b" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 22 -9"/></filter></svg>
<article class="w-[min(370px,100%)] rounded-3xl isolate p-6 text-white bg-white/11 border border-white/35 backdrop-blur-[22px] saturate-180 shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_-30px_oklch(0_0_0/0.7)]">
<header class="flex items-baseline justify-between gap-3 mb-2">
<h3 class="text-base font-extrabold tracking-wide m-0">Display</h3>
<span class="text-[11px] font-semibold text-white/60">Drag the thumb →</span>
</header>
<div class="mt-3.5">
<div class="flex items-center justify-between gap-2 mb-3">
<label for="trs-17-input" class="inline-flex items-center gap-1.5 text-[13px] font-semibold text-white/90"><span aria-hidden="true">☀︎</span> Brightness</label>
<span class="text-sm font-extrabold tabular-nums min-w-[3ch] text-right" id="trs-17-out">60</span>
</div>
<div class="group/slider relative h-8 flex items-center has-[input:focus-visible]:outline-2 has-[input:focus-visible]:outline-offset-6 has-[input:focus-visible]:outline-white rounded-full">
<div class="absolute inset-x-0 h-2 rounded-full bg-white/16 border border-white/25" aria-hidden="true"></div>
<span class="absolute inset-0 [filter:url(#trs-17-goo)] pointer-events-none" aria-hidden="true">
<span class="absolute left-0 top-1/2 -translate-y-1/2 h-2 rounded-full w-[calc(var(--v)*100%)] bg-gradient-to-r from-trs17-acc/60 to-trs17-acc shadow-[0_0_12px_-2px_var(--color-trs17-acc)]"></span>
<span class="absolute top-1/2 left-[calc(var(--v)*100%)] -translate-x-1/2 -translate-y-1/2 grid place-items-center size-5.5 rounded-full text-[0px] text-[#3a2a05] font-extrabold bg-[radial-gradient(circle_at_35%_30%,#fff,var(--color-trs17-acc))] border border-white/60 shadow-[inset_0_2px_4px_oklch(1_0_0/0.9),inset_0_-3px_5px_oklch(0_0_0/0.18),0_6px_14px_oklch(0_0_0/0.35)] transition-[width,height,font-size] duration-250 ease-[cubic-bezier(0.34,1.6,0.5,1)] group-hover/slider:size-8 group-hover/slider:text-[12px] group-has-[input:active]/slider:size-8 group-has-[input:active]/slider:text-[12px] group-has-[input:focus-visible]/slider:size-8 group-has-[input:focus-visible]/slider:text-[12px] motion-reduce:transition-none" id="trs-17-bubble">60</span>
</span>
<input type="range" min="0" max="100" value="60" id="trs-17-input" aria-label="Brightness"
class="absolute inset-0 w-full h-full m-0 appearance-none bg-transparent opacity-0 cursor-pointer z-10">
</div>
</div>
</article>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-trs17-acc: #f0b429;
--color-trs17-acc: oklch(0.8 0.17 65);
--font-trs17-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
@property --v {
syntax: "<number>";
inherits: true;
initial-value: 0.6;
}
.trs-17 {
transition: --v 75ms linear;
}
@media (prefers-reduced-motion: reduce) {
.trs-17 {
transition: none;
}
}
.trs-17 {
width: 100%;
min-height: 100svh;
background: radial-gradient(120% 120% at 70% 20%, #1e293b, #0f172a 70%);
}
/* The native thumb is a transparent hit target: the visible bubble is the
glass span inside the gooey group. */
.trs-17 input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 32px;
height: 32px;
border-radius: 9999px;
background: transparent;
cursor: grab;
}
.trs-17 input[type="range"]:active::-webkit-slider-thumb {
cursor: grabbing;
}
.trs-17 input[type="range"]::-moz-range-thumb {
width: 32px;
height: 32px;
border: 0;
border-radius: 9999px;
background: transparent;
cursor: grab;
}
```
## JavaScript
```js
(function(){
var root = document.getElementById('trs-17-root');
var inp = document.getElementById('trs-17-input');
var bubble = document.getElementById('trs-17-bubble');
var out = document.getElementById('trs-17-out');
function update(){
var v = +inp.value;
root.style.setProperty('--v', v / 100);
bubble.textContent = v;
out.textContent = v;
inp.setAttribute('aria-valuetext', v + ' percent brightness');
}
inp.addEventListener('input', update);
update();
})();
```Here's a working CSS demo 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: Tailwind CSS Liquid Glass Slider with Gooey Morphing Value Bubble
Source: https://codefronts.com/components/tailwind-css-range-sliders/tailwind-liquid-glass-slider-gooey-value-bubble/
The iOS-style fluid control: the value bubble grows out of the track itself, fused by a gooey SVG filter, then floats over the thumb as you drag. Everything except the filter primitives is a utility — and the show condition is has-[input:active]:, so hover, drag, and keyboard focus all trigger the same morph.
## HTML
```html
<section class="trs-17 w-full min-h-svh grid place-items-center px-6 py-10 font-trs17-sans" id="trs-17-root" style="--v:.6">
<svg class="absolute size-0" aria-hidden="true"><filter id="trs-17-goo"><feGaussianBlur in="SourceGraphic" stdDeviation="6" result="b"/><feColorMatrix in="b" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 22 -9"/></filter></svg>
<article class="w-[min(370px,100%)] rounded-3xl isolate p-6 text-white bg-white/11 border border-white/35 backdrop-blur-[22px] saturate-180 shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_-30px_oklch(0_0_0/0.7)]">
<header class="flex items-baseline justify-between gap-3 mb-2">
<h3 class="text-base font-extrabold tracking-wide m-0">Display</h3>
<span class="text-[11px] font-semibold text-white/60">Drag the thumb →</span>
</header>
<div class="mt-3.5">
<div class="flex items-center justify-between gap-2 mb-3">
<label for="trs-17-input" class="inline-flex items-center gap-1.5 text-[13px] font-semibold text-white/90"><span aria-hidden="true">☀︎</span> Brightness</label>
<span class="text-sm font-extrabold tabular-nums min-w-[3ch] text-right" id="trs-17-out">60</span>
</div>
<div class="group/slider relative h-8 flex items-center has-[input:focus-visible]:outline-2 has-[input:focus-visible]:outline-offset-6 has-[input:focus-visible]:outline-white rounded-full">
<div class="absolute inset-x-0 h-2 rounded-full bg-white/16 border border-white/25" aria-hidden="true"></div>
<span class="absolute inset-0 [filter:url(#trs-17-goo)] pointer-events-none" aria-hidden="true">
<span class="absolute left-0 top-1/2 -translate-y-1/2 h-2 rounded-full w-[calc(var(--v)*100%)] bg-gradient-to-r from-trs17-acc/60 to-trs17-acc shadow-[0_0_12px_-2px_var(--color-trs17-acc)]"></span>
<span class="absolute top-1/2 left-[calc(var(--v)*100%)] -translate-x-1/2 -translate-y-1/2 grid place-items-center size-5.5 rounded-full text-[0px] text-[#3a2a05] font-extrabold bg-[radial-gradient(circle_at_35%_30%,#fff,var(--color-trs17-acc))] border border-white/60 shadow-[inset_0_2px_4px_oklch(1_0_0/0.9),inset_0_-3px_5px_oklch(0_0_0/0.18),0_6px_14px_oklch(0_0_0/0.35)] transition-[width,height,font-size] duration-250 ease-[cubic-bezier(0.34,1.6,0.5,1)] group-hover/slider:size-8 group-hover/slider:text-[12px] group-has-[input:active]/slider:size-8 group-has-[input:active]/slider:text-[12px] group-has-[input:focus-visible]/slider:size-8 group-has-[input:focus-visible]/slider:text-[12px] motion-reduce:transition-none" id="trs-17-bubble">60</span>
</span>
<input type="range" min="0" max="100" value="60" id="trs-17-input" aria-label="Brightness"
class="absolute inset-0 w-full h-full m-0 appearance-none bg-transparent opacity-0 cursor-pointer z-10">
</div>
</div>
</article>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-trs17-acc: #f0b429;
--color-trs17-acc: oklch(0.8 0.17 65);
--font-trs17-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
@property --v {
syntax: "<number>";
inherits: true;
initial-value: 0.6;
}
.trs-17 {
transition: --v 75ms linear;
}
@media (prefers-reduced-motion: reduce) {
.trs-17 {
transition: none;
}
}
.trs-17 {
width: 100%;
min-height: 100svh;
background: radial-gradient(120% 120% at 70% 20%, #1e293b, #0f172a 70%);
}
/* The native thumb is a transparent hit target: the visible bubble is the
glass span inside the gooey group. */
.trs-17 input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 32px;
height: 32px;
border-radius: 9999px;
background: transparent;
cursor: grab;
}
.trs-17 input[type="range"]:active::-webkit-slider-thumb {
cursor: grabbing;
}
.trs-17 input[type="range"]::-moz-range-thumb {
width: 32px;
height: 32px;
border: 0;
border-radius: 9999px;
background: transparent;
cursor: grab;
}
```
## JavaScript
```js
(function(){
var root = document.getElementById('trs-17-root');
var inp = document.getElementById('trs-17-input');
var bubble = document.getElementById('trs-17-bubble');
var out = document.getElementById('trs-17-out');
function update(){
var v = +inp.value;
root.style.setProperty('--v', v / 100);
bubble.textContent = v;
out.textContent = v;
inp.setAttribute('aria-valuetext', v + ' percent brightness');
}
inp.addEventListener('input', update);
update();
})();
```How this works
The goo is one filter. feGaussianBlur plus a high-contrast feColorMatrix turns two blurred shapes into one fused silhouette; put the fill and the bubble inside that filtered group and the bubble appears to be made of the same liquid as the track.
The input stays real. It sits on top at opacity-0, so arrows, Home/End and screen-reader announcements are untouched; the glass is decoration layered beneath.
One property drives both. --v sizes the fill and positions the bubble, and the bubble's numerals fade in with the size change so the label never appears before there is room for it.
Make it yours
- Accent:
--color-trs17-accretints fill, bubble and glow. - Neck length: the filter's
stdDeviation— higher fuses further, lower detaches sooner. - Always-on bubble: drop the
has-[…]variants and keep the resting size atsize-8.
Gotchas — read before shipping
- The real input must stay ON TOP and
opacity-0; moving it under the glass costs keyboard and screen-reader support. - The fill and the bubble must be inside the SAME filtered group, or they blur separately and never fuse.
- SVG filter ids are document-global. This one is namespaced
trs-17-gooprecisely so two copies on a page cannot collide.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
The gooey morph is an SVG-filter enhancement over a native range input; where filters or :has() are unavailable it degrades to a plain glass bubble.