Como estilizar a entrada do intervalo HTML5 para ter cores diferentes antes e depois do controle deslizante?

106

insira a descrição da imagem aqui

Quero que o lado esquerdo seja verde e o lado direito cinza. Conforme a foto acima, seria PERFEITO. De preferência uma solução CSS pura (só precisa se preocupar com o WebKit).

É possível uma coisa dessas?

Shamoon
fonte
Provavelmente, o que você tentou? Poste seu código aqui.
j08691
Pergunta muito útil.
Saurav Kumar

Respostas:

127

Solução CSS pura :

  • Chrome: oculte o estouro de input[range]e preencha todo o espaço à esquerda para o polegar com a cor da sombra.
  • IE: não há necessidade de reinventar a roda:::-ms-fill-lower
  • O Firefox não precisa reinventar a roda:::-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"/>

deathangel908
fonte
1
Oi deathangel908, boa solução. Gostaria apenas de melhorar a parte da sombra da caixa: sombra da caixa: -80px 0 0px 80px # 43e5f7;
Filip Witkowski
34
O problema com isso no cromo é se você deseja que o polegar seja maior do que a trilha, então a sombra da caixa sobrepõe a trilha com a altura do polegar. Existe uma maneira de confinar a sombra da caixa dentro da trilha?
mharris7190
1
Isso não funciona para entradas com larguras baseadas em porcentagem. Alguém tem uma solução alternativa para isso?
Remi Sture
2
Uma versão CSS / JS funcional pode ser encontrada aqui: jsfiddle.net/remisture/esyvws3d
Remi Sture
3
@tenwest Uau, isso é horrível. Obrigado pela atualização!
CodeF0x
63

Embora a resposta aceita seja boa em teoria, ela ignora o fato de que o polegar não pode ser maior do que o tamanho da faixa sem ser cortado pelo overflow: hidden. Veja este exemplo de como lidar com isso com apenas um pequeno pedaço de 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>

dargue3
fonte
você pode me sugerir quando eu adicionei max = 5 em HTML e a cor não preenche corretamente
Husna
@Husna Estendi esta resposta para também lidar com os atributos mínimo máximo, espero que ajude.
htmn
1
@Husna Você deve calcular a% como uma diferença entre seu valor máximo e mínimo. Por exemplo, se você tem min: 0 e max: 10, você deve usar, no JS :,+ this.value / (10-0)*100 +'%, #fff
Rosario Russo
5
@Rosario Russo Você só precisa repace this.value no JS com(this.value-this.min)/(this.max-this.min)*100
Silvan
@ dargue3 você deve atualizar sua resposta com a entrada de
silvans
28

Sim, é possível. Embora eu não recomende porqueinput range não é realmente compatível com todos os navegadores porque é um novo elemento adicionado em HTML5 e HTML5 é apenas um rascunho (e será por muito tempo), portanto, ir tão longe quanto ao estilo talvez não seja o melhor escolha.

Além disso, você também precisará de um pouco de JavaScript. Tomei a liberdade de usar jQuery biblioteca para isso, para fins de simplicidade.

Aqui está: http://jsfiddle.net/JnrvG/1/ .

federico-t
fonte
8
Essa não era a questão, o que eu preciso fazer por css, deve haver uma maneira apenas com css.
Ipad de
10
Você pode fazer funcionar no Chrome sem JS ( jsfiddle.net/1xg1j3tw ). Para o IE10 +, você pode usar os pseudo-elementos -ms-fill-lower e -ms-fill-upper.
Ales,
1
@Ales Você deve colocar isso em uma resposta extra.
Luca Steeb
4
Altere .change(para on('input', func..para que o plano de fundo seja alterado quando o usuário mover o polegar, não apenas para cima.
Yami Odymel
10

Uma pequena atualização para este:

se você usar o seguinte, ele será atualizado instantaneamente, em vez de quando o mouse for liberado.

"mudar o mouse", função "

<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>
James Parker
fonte
9

Com base na resposta de @ dargue3 , se você quiser que o polegar seja maior do que a trilha, você deseja aproveitar totalmente o <input type="range" />elemento e ir para o navegador cruzado, você precisa de algumas linhas extras de JS e CSS.

No Chrome / Mozilla você pode usar a linear-gradienttécnica, mas você precisa para ajustar a relação baseada na min, max, valueatributos como mencionado aqui por @Attila O. . Você precisa ter certeza de que não está aplicando isso no Edge, caso contrário, o polegar não será exibido. @Geoffrey Lalloué explica isso com mais detalhes aqui .

Outra coisa que vale a pena mencionar, é que você precisa ajustar o rangeEl.style.height = "20px";no IE / Older. Simplificando, porque neste caso "a altura não é aplicada à trilha, mas sim a toda a entrada, incluindo o polegar". rabeca

/**
 * 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" />

htmn
fonte
5

A solução aceita anteriormente não está funcionando mais .

Acabei codificando uma função simples que envolve o rangeem um contêiner estilizado adicionando a barra necessária antes do cursor. Escrevi este exemplo onde é fácil ver as duas cores 'azul' e 'laranja' definidas no css, para que possam ser rapidamente modificadas.

fedeghe
fonte
2

Se você usar a primeira resposta , há um problema com o polegar. No cromo, se você quiser que o polegar seja maior do que a trilha , a sombra da caixa sobrepõe a trilha com a altura do polegar.

Basta somar todas essas respostas e escrever o controle deslizante normalmente funcionando com o polegar maior do controle deslizante: 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>

abdigali
fonte
1
isso funciona para mim como adicionar cor ao botão de controle. Obrigado
Frank
0

Agora é compatível com pseudoelementos em cada WebKit, Firefox e IE. Mas, claro, é diferente em cada um. : (

Veja as respostas a esta pergunta e / ou pesquise um CodePen intitulado prettify <input type=range> #101para algumas soluções.

Wilson F
fonte
-5
input type="range" min="0" max="50" value="0"  style="margin-left: 6%;width: 88%;background-color: whitesmoke;"

o código acima muda o estilo de entrada do intervalo .....

Krish
fonte
Funciona no FireFox 57, mas não no Opera 49 nem no Safari 11 - pior, nada suporta a cor do primeiro plano.
devon