Range-Inputs in HTML sehen so aus
<input type="range" name="quantity" min="1" max="10">
In Browsern, die sie unterstützen, sehen sie so aus

Das ist ja alles schön und gut. Man könnte es für alles verwenden, wo man eine Zahl von einem Benutzer erfassen möchte, die einen erzwungenen Mindest- und Höchstwert hat.
Aber fällt Ihnen etwas Merkwürdiges auf? Ganz allein kommuniziert dieses Range-Input dem Benutzer nicht, welche Zahl er tatsächlich absenden wird. Wenn Ihre Eingabe etwas wie „Wie fühlen Sie sich? Links für traurig, rechts für glücklich.“ lautet, dann ist das in Ordnung, Sie müssen dem Benutzer wahrscheinlich keine Zahl anzeigen. Aber ich wette, es ist häufiger der Fall, dass Sie die Zahl anzeigen müssen, als sie nicht anzuzeigen.
Um fair zu sein, die Spezifikation besagt
Das Eingabeelement stellt eine Steuerung dar, um den Wert des Elements auf eine Zeichenfolge zu setzen, die eine Zahl darstellt, jedoch mit der Einschränkung, dass der genaue Wert nicht wichtig ist, was es UAs ermöglicht, eine einfachere Schnittstelle bereitzustellen als für den Zahlenstatus.
Aber mal ehrlich, nur weil wir einen coolen Schieberegler wollen, heißt das nicht automatisch, dass wir dem Benutzer vorenthalten sollten, den gesendeten Wert zu kennen. Ich würde nicht unbedingt sagen, dass Browser ihre UI-Steuerung ändern sollten, um diese Zahl anzuzeigen. Ich sage, wir sollten sie selbst bauen!
Dies ist der perfekte Anwendungsfall für das <output>-Tag, das speziell für Werte gedacht ist, die von Formularelementen berechnet werden. Hier ist eine super einfache Implementierung, wie Sie es verwenden könnten
<input type="range" name="foo">
<output for="foo" onforminput="value = foo.valueAsNumber;"></output>
Update! Neue Version mit Vanilla JavaScript, die auch besser funktioniert.
Unser Ziel ist es hier, eine „Blase“ anzuzeigen, die den aktuellen Wert eines Range-Inputs darstellt.

Das Setzen des Werts unserer „Blase“ aus dem Wert des Inputs ist eine Sache des Abgreifens des Range-Werts und des Platzierens im Bubble
range.addEventListener("input", () => {
bubble.innerHTML = rangel.value;
});
Der *Trick* ist das *Positionieren* der Blase entlang des Range-Inputs, damit sie neben dem „Daumen“ gleitet. Dazu müssen wir berechnen, zu wie viel Prozent die Blase nach links verschoben werden muss. Machen wir also eine Funktion, um das zu tun und die Dinge ein wenig aufzuräumen
range.addEventListener("input", () => {
setBubble(range, bubble);
});
function setBubble(range, bubble) {
const val = range.value;
const min = range.min ? range.min : 0;
const max = range.max ? range.max : 100;
const newVal = Number(((val - min) * 100) / (max - min));
bubble.innerHTML = val;
// Sorta magic numbers based on size of the native UI thumb
bubble.style.left = newVal = "%";
}
Hier stellen wir sicher, dass wir die min- und max-Attribute der Range-Inputs berücksichtigen und eine %-Position zwischen 0-100 basierend auf dem aktuellen Wert in diesem Bereich berechnen. Nicht alle Bereiche sind die Standard 0-100 Zahlen. Wenn ein Bereich also auf den Wert 50 in einem Bereich von 0 bis 200 eingestellt wäre, wären das 25 % des Weges. Dies berücksichtigt das.
Aber es hat einen störenden Fehler: Die Blase ist am Anfang zu weit links und am Ende zu weit rechts. Bei Range-Inputs hängt der Daumen nicht am linken Rand, so dass sein Zentrum am Anfang ist, und ebenso am Ende. Wie ein Scrollbalken hören die Ränder des Daumens innerhalb der Spur auf.
Wir können dort einige magische Zahlen verwenden, die sich bei verschiedenen Browsern gut bewähren
// Sorta magic numbers based on size of the native UI thumb
bubble.style.left = `calc(${newVal}% + (${8 - newVal * 0.15}px))`;
Hier ist die finale Demo
Ich wurde dazu inspiriert, mich damit zu beschäftigen, weil Leser Max Globa mit seiner Version schrieb, die ich hier poste
Ein cooler Aspekt von Max' Version ist, dass der Range-Input CSS-gestylt ist, sodass die genaue Größe des Daumens bekannt ist. Es gibt einige Zahlen, die in der JavaScript-Mathematik ziemlich magisch erscheinen, aber zumindest basieren sie auf realen Zahlen, die in CSS auf die Größe des Daumens gesetzt sind.
Andere Versionen
Dave Olsen hat die (ursprüngliche) Idee portiert, um keine Abhängigkeit von jQuery zu haben. Hier ist diese Version
Sean Stopnik
simurai
Vincent Durand
Vergessen Sie nicht, dass Range-Inputs Datalists haben können, die kleine Einkerbungen an ihnen anbringen, was ziemlich cool ist.
Ana Tudor hat eine massive Sammlung, von denen viele den aktuellen Wert durch ihr Design anzeigen.
😬 Alte Version aus der Originalversion dieses Beitrags (jQuery, funktioniert zudem nicht gut)
Ich lasse das hier nur aus historischen Gründen drin.
Holen wir uns unseren Freund jQuery und machen wir uns an CSS. Das Ziel ist unten. Jeder Range-Input, jederzeit, jeder Min/Max/Step – wir setzen eine Blase darüber, die den aktuellen Wert anzeigt.

Formatieren wir zuerst das Output-Element. Wir werden es absolut über dem Input positionieren. Das gibt uns die Möglichkeit, auch den linken Wert anzupassen, sobald wir mit JavaScript herausgefunden haben, was er sein soll. Wir werden es mit Farbverläufen und abgerundeten Ecken aufpeppen und sogar ein kleines Zeigendreieck mit einem Pseudo-Element hinzufügen.
output {
position: absolute;
background-image: linear-gradient(top, #444444, #999999);
width: 40px;
height: 30px;
text-align: center;
color: white;
border-radius: 10px;
display: inline-block;
font: bold 15px/30px Georgia;
bottom: 175%;
left: 0;
margin-left: -1%;
}
output:after {
content: "";
position: absolute;
width: 0;
height: 0;
border-top: 10px solid #999999;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
top: 100%;
left: 50%;
margin-left: -5px;
margin-top: -1px;
}
Jetzt müssen wir alle Range-Inputs auf Wertänderungen überwachen. Unser Ziel ist es, die linke Position der Blase im Takt mit dem Schieberegler zu verschieben. Das ist nicht ganz einfach, da Schieberegler beliebige Breiten und beliebige Minimal- oder Maximalwerte haben können. Wir werden ein bisschen rechnen müssen. Hier ist das gesamte jQuery JavaScript, kommentiert
// DOM Ready
$(function() {
var el, newPoint, newPlace, offset;
// Select all range inputs, watch for change
$("input[type='range']").change(function() {
// Cache this for efficiency
el = $(this);
// Measure width of range input
width = el.width();
// Figure out placement percentage between left and right of input
newPoint = (el.val() - el.attr("min")) / (el.attr("max") - el.attr("min"));
// Janky value to get pointer to line up better
offset = -1.3;
// Prevent bubble from going beyond left or right (unsupported browsers)
if (newPoint < 0) { newPlace = 0; }
else if (newPoint > 1) { newPlace = width; }
else { newPlace = width * newPoint + offset; offset -= newPoint; }
// Move bubble
el
.next("output")
.css({
left: newPlace,
marginLeft: offset + "%"
})
.text(el.val());
})
// Fake a change to position bubble at page load
.trigger('change');
});
Das einzig hässliche daran ist der Wert 1.3. Ich habe versucht, die Spitze des Blasen-Dreiecks mit der Mitte des Schiebereglers auszurichten. Das ist nicht einfach, da die Mitte des Schiebereglers nie zu 100 % links oder rechts ist. Dieser Wert ist nicht perfekt, noch perfekt implementiert, aber er ist besser, als ihn nicht zu haben.
Als Bonus erhalten Browser, die den Range-Input nicht unterstützen, trotzdem die Blasen-Funktionalität.

Der obige Code *hängt* davon ab, dass die Range-Inputs einen spezifizierten min- und max-Wert haben. Wenn sie das nicht tun, bricht es irgendwie zusammen. Ich finde es seltsam, einen Range-Input zu verwenden, ohne diese Dinge anzugeben, obwohl sie standardmäßig 0 und 100 zu sein scheinen, wenn man sie nicht angibt. Um dies robust zu machen, würden Sie jedes Attribut abrufen, testen und wenn es nicht richtig aussieht, es beheben. Etwas wie
var minValue, maxValue;
if (!el.attr("min")) { minValue = 0; } else { minValue = el.attr("min"); }
...dann die Variable minValue in der Mathematik verwenden. Und ähnliches für Max. Jedenfalls, hier ist die Live-Demo
Das ist ziemlich cool! Danke Chris!
Wie wäre es mit Blasen, die nur erscheinen, wenn man schiebt, und dann verblassen, wenn man loslässt? :P
Sie sind nicht schlecht, aber dann wäre es wirklich cool gewesen, wenn dies nativ implementiert worden wäre.
Übrigens, wenn der „ruckelige“ Wert jedes Mal, wenn sich der Wert des Schiebereglers ändert, zufällig (natürlich innerhalb eines Bereichs) sein könnte, dann wäre der seltsam aussehende Versatz unter Windows (Mac- und Windows-Schieberegler passen sich unterschiedlich an) weniger auffällig. Aber dann haben Sie Ihr Bestes gegeben, und es ist besser, als andere „komplexe“ mathematische Ansätze ergeben würden.
Außerdem wäre es cool,
<output>auszublenden, wenn die Maus nicht auf dem Schieberegler ist. Oh, das wirft eine Frage in meinen Kopf: Wenn Sie zum Beispiel die Opazität des<output>-Elements reduzieren, würde das dann auch die Opazität des:after-Pseudo-Elements beeinflussen?Großartig. Ich kann es kaum erwarten, solche Dinge nativ zu tun. Ihr Beispiel ist genau das, was ich in einer unserer Firmenanwendungen mache
http://www.carprices.com/research.rpro.html
Klicken Sie auf „Search by Price Range“, um einen Schieberegler mit einem pseudo „output“-Element zu sehen.
Wie Sie sehen, hatte ich ähnliche Schwierigkeiten, die Wertblase mit der Mitte des „Daumens“ des Range-Schiebereglers auszurichten. Interessant, dass der HTML5-Range-Schieberegler kein Konzept für einen „Daumen“ oder seine Position hat, sodass Sie seine Position selbst berechnen müssen. Hoffentlich ändert sich das, bis wir eine breite Unterstützung dafür sehen.
Diese Seite: http://wufoo.com/html5/types/8-range.html scheint zumindest im neuen Opera 11.10 komplett leer zu sein. Sieht nach einem z-index-Problem aus. Es ist etwas ironisch, da Opera der einzige Browser auf der Seite ist, der den Range-Input vollständig unterstützt :).
Oh oh, das ist seltsam. Ich kann es aber nicht reproduzieren. Ich verwende hier 11.10 und es wird korrekt geladen.
Oh! Sie haben Recht, es funktioniert perfekt. Ich habe es jedoch unter Windows 7 überprüft. Den Bug habe ich unter Windows XP bemerkt. Hm... Ich werde es noch einmal überprüfen und wenn immer noch etwas schiefgeht, werde ich es Sie wissen lassen.
Ok, der Fehler besteht immer noch, aber anscheinend unter Windows XP (SP 3). Ich habe es nicht unter Vista überprüft.
Ich musste nur diese Deklarationen ausschalten
left: -3500px;
opacity: 0;
für den Selektor „#content, h1 section“ und der Inhalt wird zugänglich.
Chris,
Toller Beitrag! Man kann damit wirklich coole Effekte erzielen! Ich werde es definitiv selbst ausprobieren.
Danke
Warum ist es ein Bonus, dass Browser, die den Range-Input nicht unterstützen, trotzdem die Blasen-Funktionalität erhalten?
Man erhält zweimal denselben Wert... solange man dieses Fallback-Inputfeld nicht per JavaScript durch einen Schieberegler ersetzt, ist die Blase unnötig
Brillante Arbeit. Erstens liebe ich, wie Sie die Blase gestalten. Zweitens ist es eine relativ einfache Möglichkeit, dem Schieberegler-Element eine deutlich bessere Benutzerfreundlichkeit zu verleihen.
Brillant geschriebener Artikel. 3 Hoch auf Chris.
Wie sieht es mit IE aus?
Bei der „Notiz“ gibt es einen Trick: Da die $().attr()-Funktion von jQuery undefined zurückgibt, wenn das Attribut nicht existiert, können Sie Folgendes tun, um den Code dafür zu vereinfachen und zu kürzen.
var minVal, maxVal;
minVal = el.attr("min") || 0;
maxVal = el.attr("max") || 0;
Ich wünschte, ich könnte diese Dinge nativ tun, dann müsste ich nicht 5000 Zeilen Code/Bibliotheken verwenden, nur um diese einfachen Schieberegler zu machen: http://www.zirgo.com/
Es ist großartig
Ich habe versucht, mehrere Variationen mit Range-Input zu erstellen, aber das Verhalten ist unter iOS Webkit etwas anders, das „Tippen und Wert setzen“ nicht kann wie andere Webkits.
http://codepen.io/huang47/full/nDCJi
Irgendwelche Einblicke?
Die Lösung ist einfach. Ersetzen Sie den Range-Thumb durch :before/:after des Outputs.
Hier ist eine Lösung für den ärgerlichen Fehler, dass die Blase am Anfang zu weit links und am Ende zu weit rechts ist. Durch die Berechnung des Transformationswerts bleibt die Blase konstant an derselben Stelle, anstatt sich zu bewegen. Keine magischen Zahlen mehr. Getestet auf Chrome v. 99.0.4844.82 mit nur einem Schieberegler.
‘function setBubble(range, bubble){
bubble.innerHTML = range.value;
bubble.style.left = range.value + ‘%’;
//richtige Transformation für präzise Blasen-Ausrichtung mit dem Schieberegler-Thumb nötig
bubble.style.transform = ‘translateX(-‘ + (50 + parseInt(range.value)) + ‘%)’;
return;
}’
Inspiriert von diesem Beitrag
https://jsfiddle.net/4fL0ur2w
Danke