Reputation: 43649
I want the left side to be green and the right side to be gray. As pictured above would be PERFECT. Preferably a pure CSS solution (only need to worry about WebKit).
Is such a thing possible?
Upvotes: 225
Views: 384288
Reputation: 1617
Use this simple css property to change color of checkbox, radio button and range
input[type='range']{ accent-color: green; }
Upvotes: 158
Reputation: 5555
.style.accentColor
propertyDOM_range_element.style.accentColor = 'blue'
.css()
$('#DOM_range_element').css({'accent-color':'blue'})
or
$('#DOM_range_element').css('accent-color', 'blue')
Here is my result
Upvotes: -3
Reputation: 297
If you use the first answer, there is a problem with the thumb. In chrome if you want the thumb to be larger than the track, then the box shadow overlaps the track with the height of the thumb.
Just to sum up all the answers I wrote a working slider with a larger slider thumb: jsfiddle
const slider = document.getElementById("myinput")
const min = slider.min
const max = slider.max
const value = slider.value
slider.style.background = `linear-gradient(to right, red 0%, red ${(value-min)/(max-min)*100}%, #DEE2E6 ${(value-min)/(max-min)*100}%, #DEE2E6 100%)`
slider.oninput = function() {
this.style.background = `linear-gradient(to right, red 0%, red ${(this.value-this.min)/(this.max-this.min)*100}%, #DEE2E6 ${(this.value-this.min)/(this.max-this.min)*100}%, #DEE2E6 100%)`
};
#myinput {
border-radius: 8px;
height: 4px;
width: 150px;
outline: none;
-webkit-appearance: none;
}
input[type='range']::-webkit-slider-thumb {
width: 6px;
-webkit-appearance: none;
height: 12px;
background: black;
border-radius: 2px;
}
<div class="chrome">
<input id="myinput" type="range" min="0" value="25" max="200" />
</div>
Upvotes: 28
Reputation: 1124
Here is another approach if you don't mind using JS. This @steveholgado Codepen overlays 3 divs for the track, progress, and thumb over the top of an input[type=range]
with an opacity of zero (transparent). An oninput listener updates the styles for the divs to create pretty much any appearance you want.
The nice thing is that it is fairly browser agnostic, and deals with the inflexibility of styling sliders on Chrome. It offers a lot more styling flexibility in general.
If you want to use something other than 0 to 100 for the slider range, you'll have to scale appropriately in the listener. For example, value = value * 100 / parseInt(range.getAttribute("max"));
(assuming min=0)
https://codepen.io/steveholgado/pen/OEpGXq
HTML:
<div class="wrap">
<input type="range" class="range" min="0" max="100" step="0.1" value="0">
<div class="track">
<div class="track-inner"></div>
</div>
<div class="thumb"></div>
</div>
CSS:
.wrap {
width: 300px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.range {
width: 100%;
cursor: pointer;
opacity: 0;
}
.range::-ms-tooltip {
display: none;
}
.track {
width: 100%;
height: 4px;
background: #DDDDDD;
position: absolute;
top: 50%;
transform: translateY(-50%);
pointer-events: none;
}
.track-inner {
width: 0;
height: 100%;
background: #E24F4F;
}
.thumb {
width: 16px;
height: 16px;
background: #AAAAAA;
border-radius: 50%;
position: absolute;
top: 50%;
left: 0;
transform: translate(0%, -50%);
pointer-events: none;
}
JS:
const range = document.querySelector('.range')
const thumb = document.querySelector('.thumb')
const track = document.querySelector('.track-inner')
const updateSlider = (value) => {
thumb.style.left = `${value}%`
thumb.style.transform = `translate(-${value}%, -50%)`
track.style.width = `${value}%`
}
range.oninput = (e) =>
updateSlider(e.target.value)
updateSlider(50) // Init value
Upvotes: 1
Reputation: 3098
You can simply use the accent color (in Chrome 99)
<input style="accent-color: #2ecc71" type="range"/>
Upvotes: 20
Reputation: 2409
-webkit-appearance: none;
removes tick marks when using datalist
. If the general appearance of the slider is fine, but the default blue color (in Chrome) needs to fit a theme color, apply a filter: hue-rotate();
to the input[type="range"]
element. Other filters can be used. Some even change the background color of the slider.
input[type="range"] {
filter: hue-rotate(180deg); //rotate degrees to get desired color
}
<input type="range" min="0" max="5" step="1" list="data" value="1" />
<datalist id="data">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</datalist>
Upvotes: 8
Reputation: 2942
While the accepted answer is good in theory, it ignores the fact that the thumb then cannot be bigger than size of the track without being chopped off by the overflow: hidden
. See this example of how to handle this with just a tiny bit of JS.
// .chrome styling Vanilla JS
document.getElementById("myinput").oninput = function() {
var value = (this.value-this.min)/(this.max-this.min)*100
this.style.background = 'linear-gradient(to right, #82CFD0 0%, #82CFD0 ' + value + '%, #fff ' + value + '%, white 100%)'
};
#myinput {
background: linear-gradient(to right, #82CFD0 0%, #82CFD0 50%, #fff 50%, #fff 100%);
border: solid 1px #82CFD0;
border-radius: 8px;
height: 7px;
width: 356px;
outline: none;
transition: background 450ms ease-in;
-webkit-appearance: none;
}
<div class="chrome">
<input id="myinput" min="0" max="60" type="range" value="30" />
</div>
Upvotes: 164
Reputation: 1675
Building on top of @dargue3's answer, if you want the thumb to be larger than the track, you want to fully take advantage of the <input type="range" />
element and go cross browser, you need a little extra lines of JS & CSS.
On Chrome/Mozilla you can use the linear-gradient
technique, but you need to adjust the ratio based on the min
, max
, value
attributes as mentioned here by @Attila O.. You need to make sure you are not applying this on Edge, otherwise the thumb is not displayed. @Geoffrey Lalloué explains this in more detail here.
Another thing worth mentioning, is that you need to adjust the rangeEl.style.height = "20px";
on IE/Older. Simply put this is because in this case "the height is not applied to the track but rather the whole input including the thumb". fiddle
/**
* Sniffs for Older Edge or IE,
* more info here:
* https://stackoverflow.com/q/31721250/3528132
*/
function isOlderEdgeOrIE() {
return (
window.navigator.userAgent.indexOf("MSIE ") > -1 ||
!!navigator.userAgent.match(/Trident.*rv\:11\./) ||
window.navigator.userAgent.indexOf("Edge") > -1
);
}
function valueTotalRatio(value, min, max) {
return ((value - min) / (max - min)).toFixed(2);
}
function getLinearGradientCSS(ratio, leftColor, rightColor) {
return [
'-webkit-gradient(',
'linear, ',
'left top, ',
'right top, ',
'color-stop(' + ratio + ', ' + leftColor + '), ',
'color-stop(' + ratio + ', ' + rightColor + ')',
')'
].join('');
}
function updateRangeEl(rangeEl) {
var ratio = valueTotalRatio(rangeEl.value, rangeEl.min, rangeEl.max);
rangeEl.style.backgroundImage = getLinearGradientCSS(ratio, '#919e4b', '#c5c5c5');
}
function initRangeEl() {
var rangeEl = document.querySelector('input[type=range]');
var textEl = document.querySelector('input[type=text]');
/**
* IE/Older Edge FIX
* On IE/Older Edge the height of the <input type="range" />
* is the whole element as oposed to Chrome/Moz
* where the height is applied to the track.
*
*/
if (isOlderEdgeOrIE()) {
rangeEl.style.height = "20px";
// IE 11/10 fires change instead of input
// https://stackoverflow.com/a/50887531/3528132
rangeEl.addEventListener("change", function(e) {
textEl.value = e.target.value;
});
rangeEl.addEventListener("input", function(e) {
textEl.value = e.target.value;
});
} else {
updateRangeEl(rangeEl);
rangeEl.addEventListener("input", function(e) {
updateRangeEl(e.target);
textEl.value = e.target.value;
});
}
}
initRangeEl();
input[type="range"] {
-webkit-appearance: none;
-moz-appearance: none;
width: 300px;
height: 5px;
padding: 0;
border-radius: 2px;
outline: none;
cursor: pointer;
}
/*Chrome thumb*/
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
-moz-appearance: none;
-webkit-border-radius: 5px;
/*16x16px adjusted to be same as 14x14px on moz*/
height: 16px;
width: 16px;
border-radius: 5px;
background: #e7e7e7;
border: 1px solid #c5c5c5;
}
/*Mozilla thumb*/
input[type="range"]::-moz-range-thumb {
-webkit-appearance: none;
-moz-appearance: none;
-moz-border-radius: 5px;
height: 14px;
width: 14px;
border-radius: 5px;
background: #e7e7e7;
border: 1px solid #c5c5c5;
}
/*IE & Edge input*/
input[type=range]::-ms-track {
width: 300px;
height: 6px;
/*remove bg colour from the track, we'll use ms-fill-lower and ms-fill-upper instead */
background: transparent;
/*leave room for the larger thumb to overflow with a transparent border */
border-color: transparent;
border-width: 2px 0;
/*remove default tick marks*/
color: transparent;
}
/*IE & Edge thumb*/
input[type=range]::-ms-thumb {
height: 14px;
width: 14px;
border-radius: 5px;
background: #e7e7e7;
border: 1px solid #c5c5c5;
}
/*IE & Edge left side*/
input[type=range]::-ms-fill-lower {
background: #919e4b;
border-radius: 2px;
}
/*IE & Edge right side*/
input[type=range]::-ms-fill-upper {
background: #c5c5c5;
border-radius: 2px;
}
/*IE disable tooltip*/
input[type=range]::-ms-tooltip {
display: none;
}
input[type="text"] {
border: none;
}
<input type="range" value="80" min="10" max="100" step="1" />
<input type="text" value="80" size="3" />
Upvotes: 16
Reputation: 1
input type="range" min="0" max="50" value="0" style="margin-left: 6%;width: 88%;background-color: whitesmoke;"
above code changes range input style.....
Upvotes: -8
Reputation: 9709
Pure CSS solution:
input[range]
, and fill all the space left to
thumb with shadow color.::-ms-fill-lower
::-moz-range-progress
/*Chrome*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
input[type='range'] {
overflow: hidden;
width: 80px;
-webkit-appearance: none;
background-color: #9a905d;
}
input[type='range']::-webkit-slider-runnable-track {
height: 10px;
-webkit-appearance: none;
color: #13bba4;
margin-top: -1px;
}
input[type='range']::-webkit-slider-thumb {
width: 10px;
-webkit-appearance: none;
height: 10px;
cursor: ew-resize;
background: #434343;
box-shadow: -80px 0 0 80px #43e5f7;
}
}
/** FF*/
input[type="range"]::-moz-range-progress {
background-color: #43e5f7;
}
input[type="range"]::-moz-range-track {
background-color: #9a905d;
}
/* IE*/
input[type="range"]::-ms-fill-lower {
background-color: #43e5f7;
}
input[type="range"]::-ms-fill-upper {
background-color: #9a905d;
}
<input type="range"/>
Upvotes: 219
Reputation: 1317
The previous accepted solution is not working any longer.
I ended up coding a simple function which wraps the range
into a styled container adding the bar that is needed before the cursor.
I wrote this example where easy to see the two colors 'blue' and 'orange' set in the css, so they can be quickly modified.
Upvotes: 6
Reputation: 129
A small update to this one:
if you use the following it will update on the fly rather than on mouse release.
"change mousemove", function"
<script>
$('input[type="range"]').on("change mousemove", function () {
var val = ($(this).val() - $(this).attr('min')) / ($(this).attr('max') - $(this).attr('min'));
$(this).css('background-image',
'-webkit-gradient(linear, left top, right top, '
+ 'color-stop(' + val + ', #2f466b), '
+ 'color-stop(' + val + ', #d3d3db)'
+ ')'
);
});</script>
Upvotes: 12
Reputation: 1260
It's now supported with pseudo elements in each of WebKit, Firefox and IE. But, of course, it's different in each one. : (
See this question's answers and/or search for a CodePen titled prettify <input type=range> #101
for some solutions.
Upvotes: 0
Reputation: 12341
Yes, it is possible. Though I wouldn't recommend it because input range
is not really supported properly by all browsers because is an new element added in HTML5 and HTML5 is only a draft (and will be for long) so going as far as to styling it is perhaps not the best choice.
Also, you'll need a bit of JavaScript too. I took the liberty of using jQuery library for this, for simplicity purposes.
Here you go: http://jsfiddle.net/JnrvG/1/.
Upvotes: 27