Jak stylizować dane wejściowe zakresu HTML5, aby miały inny kolor przed i po suwaku?

93

wprowadź opis obrazu tutaj

Chcę, aby lewa strona była zielona, ​​a prawa szara. Jak na zdjęciu powyżej byłoby IDEALNE. Najlepiej czyste rozwiązanie CSS (wystarczy martwić się o WebKit).

Czy to możliwe?

Shamoon
źródło
Prawdopodobnie czego próbowałeś? Opublikuj swój kod tutaj.
j08691

Odpowiedzi:

118

Czyste rozwiązanie CSS :

  • Chrome: ukryj przepełnienie przed input[range]i wypełnij całą przestrzeń pozostałą do kciuka kolorem cienia.
  • IE: nie ma potrzeby odkrywania koła na nowo:::-ms-fill-lower
  • Firefox nie ma potrzeby odkrywania na nowo koła:::-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"/>

śmierć anioła908
źródło
1
Cześć deathangel908, fajne rozwiązanie. Po prostu poprawiłbym część box shadow: box-shadow: -80px 0 0px 80px # 43e5f7;
Filip Witkowski,
32
Problem z tym w chrome polega na tym, że jeśli chcesz, aby kciuk był większy niż ścieżka, cień ramki nakłada się na ścieżkę z wysokością kciuka. Czy istnieje sposób na ograniczenie cienia pudełka wewnątrz toru?
mharris7190
1
Nie działa to w przypadku danych wejściowych z szerokościami procentowymi. Czy ktoś ma na to obejście?
Remi Sture
2
Działającą wersję CSS / JS można znaleźć tutaj: jsfiddle.net/remisture/esyvws3d
Remi Sture
3
@tenwest Wow, to okropne. Dziękuję za aktualizację!
CodeF0x
50

Chociaż przyjęta odpowiedź jest dobra w teorii, pomija ona fakt, że kciuk nie może być większy niż rozmiar ścieżki bez odcięcia przez overflow: hidden. Zobacz ten przykład, jak sobie z tym poradzić za pomocą niewielkiej ilości kodu JS.

// .chrome styling Vanilla JS

document.getElementById("myinput").oninput = function() {
  this.style.background = 'linear-gradient(to right, #82CFD0 0%, #82CFD0 ' + this.value + '%, #fff ' + this.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" type="range" value="50" />
</div>

dargue3
źródło
czy możesz mi zasugerować, kiedy dodałem max = 5 w HTML, a kolor nie wypełnił się prawidłowo
Husna
@Husna Rozszerzyłem tę odpowiedź, aby obsługiwała również atrybuty min max, mam nadzieję, że to pomoże.
htmn
1
@Husna Musisz obliczyć% jako różnicę między wartością maksymalną i minimalną. Na przykład, jeśli masz min: 0 i max: 10, powinieneś użyć, w JS :,+ this.value / (10-0)*100 +'%, #fff
Rosario Russo
4
@Rosario Russo Wystarczy, że zmienisz this.value w JS z(this.value-this.min)/(this.max-this.min)*100
Silvan
29

Tak to mozliwe. Chociaż nie polecałbym tego, ponieważ input rangenie jest właściwie obsługiwany przez wszystkie przeglądarki, ponieważ jest nowym elementem dodanym w HTML5, a HTML5 jest tylko szkicem (i będzie na długo), więc posuwanie się do stylizacji nie jest chyba najlepsze wybór.

Będziesz także potrzebował trochę JavaScript. Pozwoliłem sobie do tego wykorzystać bibliotekę jQuery dla uproszczenia.

Proszę bardzo: http://jsfiddle.net/JnrvG/1/ .

federico-t
źródło
8
Nie o to chodziło, po co mi to robić przez css, musi być sposób tylko z css.
Ipad,
10
Możesz sprawić, by działał w Chrome bez JS ( jsfiddle.net/1xg1j3tw ). W IE10 + można użyć pseudoelementów -ms-fill-lower i -ms-fill-upper.
Ales
1
@Ales Powinieneś to umieścić w dodatkowej odpowiedzi.
Luca Steeb
4
Zmień .change(na, on('input', func..aby tło zmieniło się, gdy użytkownik przesunie kciuk, a nie tylko mysz w górę.
Yami Odymel
10

Mała aktualizacja tego:

jeśli użyjesz poniższego, zaktualizuje się w locie, a nie po zwolnieniu myszy.

„zmień ruch myszy”, funkcja „

<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
źródło
7

Opierając się na odpowiedzi @ dargue3 , jeśli chcesz, aby kciuk był większy niż ścieżka, chcesz w pełni wykorzystać <input type="range" />element i przejść między przeglądarkami, potrzebujesz trochę dodatkowych linii JS i CSS.

Chrome / Mozilla można użyć linear-gradienttechniki, ale trzeba zmienić stosunek oparty na min, max, valueatrybuty, jak wspomniano tu o @Attila O. . Musisz się upewnić, że nie stosujesz tego w Edge, w przeciwnym razie kciuk nie zostanie wyświetlony. @Geoffrey Lalloué wyjaśnia to bardziej szczegółowo tutaj .

Kolejną rzeczą, o której warto wspomnieć, jest to, że musisz dostosować rangeEl.style.height = "20px";IE / starszą wersję. Mówiąc najprościej jest tak, ponieważ w tym przypadku „wysokość nie jest stosowana do ścieżki, ale raczej do całego wejścia łącznie z kciukiem”. skrzypce

/**
 * 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
źródło
5

Poprzednie przyjęte rozwiązanie już nie działa .

Skończyło się na tym, że zakodowałem prostą funkcję, która opakowuje rangekontener w stylizowany kontener, dodając pasek, który jest potrzebny przed kursorem. Napisałem ten przykład, w którym łatwo zobaczyć dwa kolory „niebieski” i „pomarańczowy” ustawione w css, dzięki czemu można je szybko zmodyfikować.

fedeghe
źródło
1

Jeśli użyjesz pierwszej odpowiedzi , pojawia się problem z kciukiem. W przypadku chromu, jeśli chcesz, aby kciuk był większy niż ścieżka , cień ramki nakłada się na ścieżkę z wysokością kciuka.

Wystarczy podsumować wszystkie te odpowiedzi i napisać normalnie działający suwak z większym kciukiem: 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
źródło
0

Jest teraz obsługiwany przez pseudoelementy w każdym z WebKit, Firefox i IE. Ale oczywiście w każdym jest inaczej. : (

Zobacz odpowiedzi na to pytanie i / lub wyszukaj CodePen z tytułem prettify <input type=range> #101niektórych rozwiązań.

Wilson F.
źródło
-5
input type="range" min="0" max="50" value="0"  style="margin-left: 6%;width: 88%;background-color: whitesmoke;"

powyższy kod zmienia styl wprowadzania zakresu .....

Krish
źródło
Działa w FireFox 57, ale nie w Operze 49 ani Safari 11 - co gorsza, nic nie obsługuje koloru pierwszego planu.
devon,