Skip to content

Instantly share code, notes, and snippets.

@bellbind
Created April 22, 2022 15:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bellbind/6b774e2a51affce1a89a54a000951f69 to your computer and use it in GitHub Desktop.
Save bellbind/6b774e2a51affce1a89a54a000951f69 to your computer and use it in GitHub Desktop.
[browser] custmizing input range sliders
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<style>
.container {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 50vh;
--thumb-size: 6em;
--width: 90%;
}
.background {
position: absolute;
height: 50%;
border:solid;
z-index: -1;
/* width adjuster for Chrome and Firefox */
width: calc(var(--width) - 0.87 * var(--thumb-size));
box-sizing: content-box;
}
/* width adjuster for Safari (hack) */
@media screen and (-webkit-min-device-pixel-ratio: 0) {
_::-webkit-full-page-media, _:future, :root,
.background {
width: calc(var(--width) - 0.77 * var(--thumb-size));
}
}
.slider {
flex: 1;
width: var(--width);
-webkit-appearance: none;
appearance: none;
background-color: transparent;
cursor: pointer;
box-sizing: content-box;
}
.slider:focus {
outline: none;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
margin-top: calc(-var(--thumb-size) / 2);
width: var(--thumb-size);
height: var(--thumb-size);
background-size: var(--thumb-size);
background-color: transparent;
cursor: pointer;
box-sizing: content-box;
}
.slider::-moz-range-thumb {
margin-top: calc(-var(--thumb-size) / 2);
width: var(--thumb-size);
height: var(--thumb-size);
background-size: var(--thumb-size);
background-color: transparent;
border: none;
cursor: pointer;
box-sizing: content-box;
}
</style>
<script type="module">
// Set slider emoji icons
const svgEmoji = emoji => `<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="40" height="40" viewBox="0 0 40 40">
<text x="50%" y="50%" text-anchor="middle" dominant-baseline="central" font-size="40">${emoji}</text></svg>`;
const svgEmojiUrl = emoji => `data:image/svg+xml,${encodeURIComponent(svgEmoji(emoji))}`;
try {
document.styleSheets[0].insertRule(`.upper::-webkit-slider-thumb {background-image: url(${svgEmojiUrl("&#x1f6b4;")});}`, 0);
document.styleSheets[0].insertRule(`.lower::-webkit-slider-thumb {background-image: url(${svgEmojiUrl("&#x1f3e0;")});}`, 0);
} catch {}
try {
document.styleSheets[0].insertRule(`.upper::-moz-range-thumb {background-image: url(${svgEmojiUrl("&#x1f6b4;")});}`, 0);
document.styleSheets[0].insertRule(`.lower::-moz-range-thumb {background-image: url(${svgEmojiUrl("&#x1f3e0;")});}`, 0);
} catch {} // fails to parse css on chrome and safari
const container = document.querySelector(".container");
const upper = container.querySelector(".upper");
const lower = container.querySelector(".lower");
const canvas = container.querySelector(".background");
const drawBackground = () => {
const max = +upper.max;
const min = +upper.min;
const up = +upper.value;
const low = +lower.value;
const c2d = canvas.getContext("2d");
c2d.clearRect(0, 0, canvas.width, canvas.height);
c2d.save();
c2d.scale(canvas.width / (max - min), 1);
c2d.fillStyle = "hsla(240, 75%, 50%, 0.5)";
if (low <= up) {
c2d.fillRect(low - min, 0, up - low, canvas.height);
} else {
c2d.fillRect(0, 0, up - min, canvas.height);
c2d.fillRect(low - min, 0, max - low, canvas.height);
}
c2d.restore();
};
upper.addEventListener("input", ev => drawBackground());
lower.addEventListener("input", ev => drawBackground());
</script>
</head>
<body>
<div class="container" tabindex="0">
<canvas class="background"></canvas>
<input class="slider upper" type="range" value="0" min="0" max="12345" step="1" />
<input class="slider lower" type="range" value="0" min="0" max="12345" step="1" />
</div>
</body>
</html>
@bellbind
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment