ChaniLastnamé
ChaniLastnamé

Reputation: 533

Style input range before and after

I was following this method from CSS-Tricks to style an input range and was trying to use the before and after pseudo classes. Below is the code I have tried:

input[type=range]::-webkit-slider-thumb:before {
    background: #fff;
}

This doesn't seem to do the trick. Can someone help me how to style the slider track. I need a pure CSS solution. Essentially I want it to look like this.

I will also paste the code from CSS-Tricks:

input[type=range] {
  -webkit-appearance: none;
  margin: 18px 0;
  width: 100%;
}
input[type=range]:focus {
  outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
  width: 100%;
  height: 8.4px;
  cursor: pointer;
  animate: 0.2s;
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
  background: #3071a9;
  border-radius: 1.3px;
  border: 0.2px solid #010101;
}
input[type=range]::-webkit-slider-thumb {
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
  border: 1px solid #000000;
  height: 36px;
  width: 16px;
  border-radius: 3px;
  background: #ffffff;
  cursor: pointer;
  -webkit-appearance: none;
  margin-top: -14px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
  background: #367ebd;
}
input[type=range]::-moz-range-track {
  width: 100%;
  height: 8.4px;
  cursor: pointer;
  animate: 0.2s;
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
  background: #3071a9;
  border-radius: 1.3px;
  border: 0.2px solid #010101;
}
input[type=range]::-moz-range-thumb {
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
  border: 1px solid #000000;
  height: 36px;
  width: 16px;
  border-radius: 3px;
  background: #ffffff;
  cursor: pointer;
}
input[type=range]::-ms-track {
  width: 100%;
  height: 8.4px;
  cursor: pointer;
  animate: 0.2s;
  background: transparent;
  border-color: transparent;
  border-width: 16px 0;
  color: transparent;
}
input[type=range]::-ms-fill-lower {
  background: #2a6495;
  border: 0.2px solid #010101;
  border-radius: 2.6px;
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
}
input[type=range]::-ms-fill-upper {
  background: #3071a9;
  border: 0.2px solid #010101;
  border-radius: 2.6px;
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
}
input[type=range]::-ms-thumb {
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
  border: 1px solid #000000;
  height: 36px;
  width: 16px;
  border-radius: 3px;
  background: #ffffff;
  cursor: pointer;
}
input[type=range]:focus::-ms-fill-lower {
  background: #3071a9;
}
input[type=range]:focus::-ms-fill-upper {
  background: #367ebd;
}

Upvotes: 8

Views: 18691

Answers (5)

Anton
Anton

Reputation: 691

If anybody is facing this same issue, here is a (selfmade) generator for generating the (pure) css for such a progress-bar:

https://antvil.github.io/css-sos/sos/progress/

Generated Example:

example progress-bar

Tested for: firefox, chrome, edge, opera, safari

But be aware that it sometimes breaks for webkit browsers, because border-radius for the progress cannot be implemented

Upvotes: -1

swisswiss
swisswiss

Reputation: 345

it's possible! if your thumb does not have to be bigger than the progress bar.

some css wizard came up with this: https://codepen.io/noahblon/pen/OyajvN

it uses a box-shadow on the thumb to make the part before the thumb look a different color. important is that the range has overflow hidden to make it work thats why the thumb cant be bigger than the track.

    body {
    height: 100vh;
    margin: 0;
    display: flex;
}

input[type="range"] { 
    margin: auto;
    -webkit-appearance: none;
    position: relative;
    overflow: hidden;
    height: 40px;
    width: 200px;
    cursor: pointer;
    border-radius: 0; /* iOS */
}

::-webkit-slider-runnable-track {
    background: #ddd;
}

/*
 * 1. Set to 0 width and remove border for a slider without a thumb
 */
::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 20px; /* 1 */
    height: 40px;
    background: #fff;
    box-shadow: -100vw 0 0 100vw dodgerblue;
    border: 2px solid #999; /* 1 */
}

::-moz-range-track {
    height: 40px;
    background: #ddd;
}

::-moz-range-thumb {
    background: #fff;
    height: 40px;
    width: 20px;
    border: 3px solid #999;
    border-radius: 0 !important;
    box-shadow: -100vw 0 0 100vw dodgerblue;
    box-sizing: border-box;
}

::-ms-fill-lower { 
    background: dodgerblue;
}

::-ms-thumb { 
    background: #fff;
    border: 2px solid #999;
    height: 40px;
    width: 20px;
    box-sizing: border-box;
}

::-ms-ticks-after { 
    display: none; 
}

::-ms-ticks-before { 
    display: none; 
}

::-ms-track { 
    background: #ddd;
    color: transparent;
    height: 40px;
    border: none;
}

::-ms-tooltip { 
    display: none;
}
<input type="range" value="25">

Upvotes: 3

paul
paul

Reputation: 548

As far as I know it is not possible to do progress indication (i.e. to have different styles on different sides of the handle) purely in CSS across browsers.

Here's an idea how to do it easily with a bit of javascript code:
https://css-tricks.com/sliding-nightmare-understanding-range-input/#the-range-progress-fill-component

Here's a tool that generates CSS based on that method:
https://toughengineer.github.io/demo/slider-styler

Example:

for (let e of document.querySelectorAll('input[type="range"].slider-progress')) {
  e.style.setProperty('--value', e.value);
  e.style.setProperty('--min', e.min == '' ? '0' : e.min);
  e.style.setProperty('--max', e.max == '' ? '100' : e.max);
  e.addEventListener('input', () => e.style.setProperty('--value', e.value));
}
/*generated with Input range slider CSS style generator (version 20201223)
https://toughengineer.github.io/demo/slider-styler*/
input[type=range].styled-slider {
  height: 2.8em;
  -webkit-appearance: none;
}

/*progress support*/
input[type=range].styled-slider.slider-progress {
  --range: calc(var(--max) - var(--min));
  --ratio: calc((var(--value) - var(--min)) / var(--range));
  --sx: calc(0.5 * 2.8em + var(--ratio) * (100% - 2.8em));
}

input[type=range].styled-slider:focus {
  outline: none;
}

/*webkit*/
input[type=range].styled-slider::-webkit-slider-thumb {
  width: 2.8em;
  height: 2.8em;
  border-radius: 1.4em;
  background: #1381A9;
  border: 0.3em solid #FFFFFF;
  box-shadow: none;
  margin-top: calc(1em * 0.5 - max(2.8em * 0.5,0.3em));
  -webkit-appearance: none;
}

input[type=range].styled-slider::-webkit-slider-runnable-track {
  height: 1em;
  border-radius: 0.5em;
  background: #D0D0D0;
  border: none;
  box-shadow: none;
}
input[type=range].styled-slider::-webkit-slider-thumb:hover {
  background: #0E6180;
}

input[type=range].styled-slider:hover::-webkit-slider-runnable-track {
  background: #A8A8A8;
}

input[type=range].styled-slider::-webkit-slider-thumb:active {
  background: #18A5D9;
}

input[type=range].styled-slider:active::-webkit-slider-runnable-track {
  background: #DBDBDB;
}

input[type=range].styled-slider.slider-progress::-webkit-slider-runnable-track {
  background: linear-gradient(#666666,#666666) 0/var(--sx) 100% no-repeat, #D0D0D0;
}

input[type=range].styled-slider.slider-progress:hover::-webkit-slider-runnable-track {
  background: linear-gradient(#404040,#404040) 0/var(--sx) 100% no-repeat, #A8A8A8;
}

input[type=range].styled-slider.slider-progress:active::-webkit-slider-runnable-track {
  background: linear-gradient(#8C8C8C,#8C8C8C) 0/var(--sx) 100% no-repeat, #DBDBDB;
}

/*mozilla*/
input[type=range].styled-slider::-moz-range-thumb {
  width: max(calc(2.8em - 0.3em - 0.3em),0px);
  height: max(calc(2.8em - 0.3em - 0.3em),0px);
  border-radius: 1.4em;
  background: #1381A9;
  border: 0.3em solid #FFFFFF;
  box-shadow: none;
}

input[type=range].styled-slider::-moz-range-track {
  height: 1em;
  border-radius: 0.5em;
  background: #D0D0D0;
  border: none;
  box-shadow: none;
}

input[type=range].styled-slider::-moz-range-thumb:hover {
  background: #0E6180;
}

input[type=range].styled-slider:hover::-moz-range-track {
  background: #A8A8A8;
}

input[type=range].styled-slider::-moz-range-thumb:active {
  background: #18A5D9;
}

input[type=range].styled-slider:active::-moz-range-track {
  background: #DBDBDB;
}

input[type=range].styled-slider.slider-progress::-moz-range-track {
  background: linear-gradient(#666666,#666666) 0/var(--sx) 100% no-repeat, #D0D0D0;
}

input[type=range].styled-slider.slider-progress:hover::-moz-range-track {
  background: linear-gradient(#404040,#404040) 0/var(--sx) 100% no-repeat, #A8A8A8;
}

input[type=range].styled-slider.slider-progress:active::-moz-range-track {
  background: linear-gradient(#8C8C8C,#8C8C8C) 0/var(--sx) 100% no-repeat, #DBDBDB;
}

/*ms*/
input[type=range].styled-slider::-ms-fill-upper {
  background: transparent;
  border-color: transparent;
}

input[type=range].styled-slider::-ms-fill-lower {
  background: transparent;
  border-color: transparent;
}

input[type=range].styled-slider::-ms-thumb {
  width: 2.8em;
  height: 2.8em;
  border-radius: 1.4em;
  background: #1381A9;
  border: 0.3em solid #FFFFFF;
  box-shadow: none;
  margin-top: 0;
  box-sizing: border-box;
}

input[type=range].styled-slider::-ms-track {
  height: 1em;
  border-radius: 0.5em;
  background: #D0D0D0;
  border: none;
  box-shadow: none;
  box-sizing: border-box;
}

input[type=range].styled-slider::-ms-thumb:hover {
  background: #0E6180;
}

input[type=range].styled-slider:hover::-ms-track {
  background: #A8A8A8;
}

input[type=range].styled-slider::-ms-thumb:active {
  background: #18A5D9;
}

input[type=range].styled-slider:active::-ms-track {
  background: #DBDBDB;
}

input[type=range].styled-slider.slider-progress::-ms-fill-lower {
  height: 1em;
  border-radius: 0.5em 0 0 0.5em;
  margin: -undefined 0 -undefined -undefined;
  background: #666666;
  border: none;
  border-right-width: 0;
}

input[type=range].styled-slider.slider-progress:hover::-ms-fill-lower {
  background: #404040;
}

input[type=range].styled-slider.slider-progress:active::-ms-fill-lower {
  background: #8C8C8C;
}
<input type="range" class="styled-slider slider-progress" style="width: 50em;" />

Upvotes: 0

Ihor
Ihor

Reputation: 324

It is possible in Firefox and IE -

// Mozilla    
input[type="range"]::-moz-range-progress {
    background: #cc1a1a;
    height: 12px;
    border-radius: 12px;
}
// IE
input[type="range"]::-ms-fill-lower {
    background: #CC1A1A;
    border: 0 solid #000101;
    border-radius: 50px;
    box-shadow: 0 0 0 #000000, 0 0 0 #0d0d0d;
}
input[type="range"]::-ms-fill-upper {
    background: #c0c0c0;
    border: 0 solid #000101;
    border-radius: 50px;
    box-shadow: 0 0 0 #000000, 0 0 0 #0d0d0d;
}

Only one way was for Chrome :before and :after, isn't supported any more (since March 2016). The best I found - is http://rangeslider.js.org/. Also it works fine with Angular JS - https://github.com/danielcrisp/angular-rangeslider

Upvotes: 3

lpslater
lpslater

Reputation: 11

Bit of a delayed reply here:

A pure CSS solution is not possible cross-browser here - IE is the only one that makes this possible via ::-ms-fill-lower and ::-ms-fill-upper

For a full cross-browser solution you'll need to use js. There's an example here that updates CSS gradients with the input's value to do roughly what you're after: http://codepen.io/ryanttb/pen/fHyEJ

You can also find information about this in this answer to a similar question: Style lower and upper fill in HTML5 range input

Upvotes: 1

Related Questions