This example will show you how to use pure css3 to implement some numeric range slider input component on a web page. Below is the demo video.
1. Numeric Range Slider Input With CSS3 Source Files.
This example contains below files.
./ ├── css │ ├── normalize.min.css │ └── style.css └── index.html
1.1 index.html.
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <title>How To Implement Numeric Range Slider Input With CSS3</title> <link rel="stylesheet" href="css/normalize.min.css"> <link rel="stylesheet" href="css/style.css"> </head> <body> <div class="range" style='--min:0; --max:1000; --value:170; --text-value:"170"; --thumb-size: 22px; --track-height: calc(var(--thumb-size)/3);'> <input type="range" min="0" max="1000" value="170" oninput="this.parentNode.style.setProperty('--value',this.value); this.parentNode.style.setProperty('--text-value', JSON.stringify(this.value))"> <output></output> <div class='range__progress'></div> </div> <div class="range" style='--step:5; --min:20; --max:100; --value:40; --text-value:"40"; --tickEvery:4; --fill-color:linear-gradient(to right, white, var(--primaryColor));'> <input type="range" min="20" max="100" step="5" value="40" oninput="this.parentNode.style.setProperty('--value',this.value); this.parentNode.style.setProperty('--text-value', JSON.stringify(this.value))"> <output></output> <div class='range__progress'></div> </div> <div class="range" data-ticks-position='top' style='--step:.1; --min:-1; --max:1; --value:.5; --text-value:"0.5"; --primaryColor:gold; --fill-color:linear-gradient(to right, TOMATO 50%, MEDIUMSEAGREEN 50%); --value-active-color:unset;'> <input type="range" min="-1" max="1" step=".1" value=".5" oninput="this.parentNode.style.setProperty('--value',this.value); this.parentNode.style.setProperty('--text-value', JSON.stringify(this.value))"> <output></output> <div class='range__progress'></div> </div> <label dir="rtl"> <xmp><label dir=rtl></xmp> <div class="range" style='--min:0; --max:1000; --value:170; --text-value:"170"; --thumb-size:22px; --track-height:calc(var(--thumb-size)/3);'> <input type="range" min="0" max="1000" value="170" oninput="this.parentNode.style.setProperty('--value',this.value); this.parentNode.style.setProperty('--text-value', JSON.stringify(this.value))"> <output></output> <div class='range__progress'></div> </div> </label> </body> </html>
1.2 css/style.css.
body { height: 100vh; display: grid; place-content: center; place-items: center; gap: 10%; } a { position: fixed; top: 1em; left: 50%; -webkit-transform: translateX(-50%); transform: translateX(-50%); display: inline-block; width: 200px; } a > img { display: inherit; width: 100%; } .controller { display: -webkit-box; display: flex; width: 90vw; border-bottom: 1px solid #DDD; padding: 2em 0; } .controller .range { width: 100%; min-width: 100px; } .controller label { -webkit-box-flex: 1; flex: 1; } .controller label:not(:last-child) { padding-right: 1em; } .controller label > span { display: block; margin-bottom: 1em; } body > label > xmp { text-align: center; } body > label > span { margin-left: 1em; } .range { width: 50vw; min-width: 200px; } .range { --primaryColor: #0366D6; --value-active-color: white; --value-background: white; --value-font: 700 12px/1 Arial; --progress-color: #EEE; --progress-shadow: 2px 2px 4px rgba(0,0,0, .1) inset; --fill-color: var(--primaryColor); --thumb-size: 16px; --track-height: calc(var(--thumb-size)/2); --thumb-shadow: 0 0 3px rgba(0,0,0,.2); --ticks-thickness: 1px; --ticks-height: 5px; --ticks-color: silver; --step: 1; --ticks-count: (var(--max) - var(--min)) / var(--step); --maxTicksAllowed: 30; --too-many-ticks: Min(1, Max(var(--ticks-count) - var(--maxTicksAllowed), 0)); --x-step: Max( var(--step), var(--too-many-ticks) * (var(--max) - var(--min)) ); --tickInterval: 100/((var(--max) - var(--min)) / var(--step)) * var(--tickEvery, 1); --tickIntervalPerc: calc((100% - var(--thumb-size))/( (var(--max) - var(--min)) / var(--x-step) ) * var(--tickEvery, 1)); --completed: calc((var(--value) - var(--min) ) / (var(--max) - var(--min)) * 100); --LTR: 1; display: inline-block; height: Max(var(--track-height), var(--thumb-size)); background: linear-gradient(to right, var(--ticks-color) var(--ticks-thickness), transparent 1px) repeat-x; background-size: var(--tickIntervalPerc) var(--ticks-height); background-position-x: calc(var(--thumb-size)/2); background-position-y: var(--flip-y, bottom); position: relative; z-index: 1; padding-bottom: var(--flip-y, var(--ticks-height)); padding-top: calc(var(--flip-y) * var(--ticks-height)); } [dir="rtl"] .range { --LTR: -1; } .range[data-ticks-position='top'] { --flip-y: 1; } .range::before, .range::after { --offset: calc(var(--thumb-size)/2); content: counter(x); font: 12px Arial; position: absolute; bottom: var(--flip-y, -2.5ch); top: calc(-2.5ch * var(--flip-y)); opacity: var(--min-max-opacity, 0.5); pointer-events: none; } .range::before { counter-reset: x var(--min); left: var(--offset); -webkit-transform: translateX(Calc(-50% * var(--LTR))); transform: translateX(Calc(-50% * var(--LTR))); } [dir='rtl'] .range::before { left: auto; right: var(--offset); } .range::after { counter-reset: x var(--max); right: var(--offset); -webkit-transform: translateX(Calc(50% * var(--LTR))); transform: translateX(Calc(50% * var(--LTR))); } [dir='rtl'] .range::after { right: auto; left: var(--offset); } .range__progress { position: absolute; left: 0; top: calc(50% - var(--ticks-height)/2); -webkit-transform: var(--flip-y, translateY(-50%) translateZ(0)); transform: var(--flip-y, translateY(-50%) translateZ(0)); width: 100%; height: calc(var(--track-height)); pointer-events: none; z-index: -1; box-shadow: var(--progress-shadow); border-radius: 20px; background: var(--fill-color, white); } .range__progress::after { content: ''; display: block; margin-left: auto; margin-right: -1px; width: calc((100% - var(--completed) * 1%) + (var(--completed)/100) * var(--thumb-size)); height: 100%; background: var(--progress-color, #EEE); box-shadow: inherit; border-radius: 0 20px 20px 0; } [dir="rtl"] .range__progress::after { margin-right: auto; margin-left: -1px; border-radius: 20px 0 0 20px; } .range > input { -webkit-appearance: none; width: 100%; height: var(--thumb-size); margin: 0; cursor: -webkit-grab; cursor: grab; outline: none; background: none; } .range > input::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; height: var(--thumb-size); width: var(--thumb-size); border-radius: 50%; background: var(--thumb-color, white); border: 1px solid silver; box-shadow: var(--inner-shadow, 0 0), var(--thumb-shadow); } .range > input::-moz-slider-thumb { -moz-appearance: none; appearance: none; height: var(--thumb-size); width: var(--thumb-size); border-radius: 50%; background: var(--thumb-color, white); border: 1px solid silver; box-shadow: var(--inner-shadow, 0 0), var(--thumb-shadow); } .range > input::-ms-thumb { appearance: none; height: var(--thumb-size); width: var(--thumb-size); border-radius: 50%; background: var(--thumb-color, white); border: 1px solid silver; box-shadow: var(--inner-shadow, 0 0), var(--thumb-shadow); } .range > input:active { cursor: -webkit-grabbing; cursor: grabbing; --thumb-color: var(--fill-color); --inner-shadow: 0 0 0 calc(var(--thumb-size)/4) inset white; } .range > input:active + output { -webkit-transition: 0s; transition: 0s; } .range > input:hover + output { --value-background: var(--primaryColor); color: var(--value-active-color); -webkit-transform: translate(var(--x-offset), 0); transform: translate(var(--x-offset), 0); box-shadow: 0 0 0 3px var(--value-background); } .range > output { --x-offset: calc(var(--completed) * -1% * var(--LTR)); --pos: calc(((var(--value) - var(--min))/(var(--max) - var(--min))) * 100%); pointer-events: none; position: absolute; z-index: 5; background: var(--value-background); border-radius: 10px; padding: 0 4px; top: -3ch; left: var(--pos); -webkit-transform: translate(var(--x-offset), 6px); transform: translate(var(--x-offset), 6px); -webkit-transition: all .12s ease-out, left 0s, top 0s; transition: all .12s ease-out, left 0s, top 0s; } [dir='rtl'] .range > output { left: auto; right: var(--pos); } .range > output::after { content: var(--text-value); font: var(--value-font); }
1.3 css/normalize.min.css.
button,hr,input{overflow:visible}audio,canvas,progress,video{display:inline-block}progress,sub,sup{vertical-align:baseline}html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0} menu,article,aside,details,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{}button,select{text-transform:none}[type=submit], [type=reset],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:ButtonText dotted 1px}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}[hidden],template{display:none}/*# sourceMappingURL=normalize.min.css.map */
Below is the video demo.
Reference