Want to add a sleek, animated audio volume control to your web project? This tutorial walks you through building a custom volume slider widget—complete with an SVG speaker icon that changes level bars and toggles mute—all using pure HTML, CSS and vanilla JavaScript. Perfect for music players, podcast apps or any interface that needs a custom volume slider.
HTML Structure
Our markup pairs a scalable SVG speaker icon with a hidden range input. Each radio‑style <path>
inside the SVG represents low, medium and high volume bars plus a mute “X.” A wrapper .box
vertically centers the elements for a compact HTML volume control layout.
<div class="main-container">
<div class="box">
<svg viewBox="-10 -14 52 52" xmlns="http://www.w3.org/2000/svg" width="50">
<g stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="transparent">
<path stroke-width="4" fill="white" d="M8 9H5v6h3l5 4V5L8 9z"></path>
<path d="M18.5 8a3.657 5 0 010 8" class="low hidden"></path>
<path d="M23 6a2.657 6.5 0 010 12" class="medium hidden"></path>
<path d="M27 3a3.5 9.1 0 010 18" class="high hidden"></path>
<path d="M20 9L26 15M26 9L20 15" class="mute hidden"></path>
</g>
</svg>
<div class="field">
<input type="range" id="volume" value="50">
</div>
</div>
</div>
.main-container
centers everything;.box
stacks SVG and range slider.- The speaker base (
M8 9…
) is constant. Bar paths.low .medium .high
and mute path.mute
are toggled via JavaScript. <input type="range">
provides user audio control from 0 to 100 and is rotated via CSS to sit vertically—delivering an intuitive interactive volume slider.
With minimal HTML, we have every element needed for dynamic volume feedback: a clickable SVG speaker icon and a smooth range slider ready for styling.
Styling Custom Volume Slider with CSS
CSS transforms the raw markup into a polished, CSS volume slider with a glassy track, animated bar colors and smooth hover/drag feedback. The slider rotates 90° for a vertical orientation and hidden SVG bars fade in as volume increases.
:root {
--width: 150px;
}
.main-container {
min-width: 100px;
min-height: 100vh;
}
.main-container,
.box,
.field {
display: flex;
align-items: center;
justify-content: center;
}
.box {
gap: 5px;
flex-direction: column;
}
.field {
height: var(--width);
}
#volume {
height: 6px;
cursor: pointer;
appearance: none;
overflow: hidden;
width: var(--width);
border-radius: 10px;
transform: rotate(-90deg);
transition: height .15s ease-in;
background: rgb(82, 82, 82);
}
#volume::-moz-range-thumb {
width: 0;
height: 0;
border: none;
box-shadow: calc(var(--width) * -1) 0 0 var(--width) #fff;
}
#volume::-webkit-slider-thumb {
-webkit-appearance: none;
width: 0;
height: 0;
border: none;
box-shadow: calc(var(--width) * -1) 0 0 var(--width) #fff;
}
#volume:hover {
height: 10px;
}
.fa-solid {
color: white;
flex-grow: 1;
}
.hidden {
visibility: hidden;
opacity: 0 !important;
}
svg {
cursor: pointer;
}
path {
transition: .3s;
opacity: 1;
}
transform: rotate(-90deg)
turns the horizontal range input into a vertical HTML audio slider.- Custom thumb styling (
box-shadow
) creates a seamless white fill that grows with the value—no extra markup required. .hidden
class keeps bar paths invisible until JavaScript reveals them, while smooth.3s
transitions fade bars in/out.- Hover enlarges slider height for better UX without changing layout.
These styles produce a clean, touch‑friendly audio volume UI that blends effortlessly into dark or light site themes with just CSS—no external libraries.
JavaScript Implementation
A concise script synchronizes slider value, SVG bar visibility and mute toggling. Users can drag the range input or click the speaker icon to mute/unmute with a smooth animated countdown or ramp‑up.
const input = document.querySelector('input');
const svg = document.querySelector('svg')
const alls = Array.from(document.querySelectorAll('.low, .medium, .high, .mute'))
let mute = false;
let lastLevel = 50;
function VolLevel(val) {
val === 0 ? alls[3].classList.remove('hidden') : '';
for (let i = 0; i < val; i++) {
alls[i].classList.remove('hidden')
}
}
function updateVol() {
alls.forEach(elem => elem.classList.add('hidden'));
const val = input.value;
const level = val >= 70 ? 3 : (val >= 30 ? 2 : (val > 0 ? 1 : 0));
VolLevel(level);
}
function toggleVol() {
const interval = setInterval(() => {
const value = parseInt(input.value);
if (!mute) {
input.value = Math.max(0, value - 1);
if (value === 0) {
clearInterval(interval);
mute = true;
}
} else {
if (value < lastLevel) {
input.value = Math.min(100, value + 1);
} else {
clearInterval(interval);
mute = false;
}
}
updateVol();
}, 1);
}
input.addEventListener('input', updateVol);
input.addEventListener('change', () => {
mute = input.value === 0;
lastLevel = input.value;
});
svg.addEventListener('click', toggleVol);
updateVol();
renderLevel()
maps slider value to 0–3 levels: low, medium, high—or mute when value is 0.- Clicking the SVG runs
toggle()
, which animates the slider toward 0 (muting) or back tolastLevel
(unmuting), creating a smooth fade rather than an abrupt jump. - Event listeners update in real time, ensuring the live volume meter always mirrors user interaction.
- No external dependencies, making the component perfect for lightweight projects.
We bind input, visuals and click behavior to deliver a fully interactive JavaScript custom volume slider widget—ready to drop into any music player or media dashboard.
This SVG speaker icon with vertical volume slider provides:
- Real‑time bar/emoji feedback without images
- Smooth mute/unmute via animated slider transitions
- Pure HTML CSS JS implementation—fast and framework‑free
- Easy customization for color, size and orientation
Drop this custom volume slider component into your next audio project to elevate user experience with stylish, intuitive controls.