Formulare/Eingabe von Zahlen

Aus SELFHTML-Wiki
< Formulare(Weitergeleitet von Type="number")
Wechseln zu: Navigation, Suche

HTML5 bietet eine Vielzahl von neuen Eingabe-Typen für die Eingabe von Zahlen. Sie sind benutzerfreundlich, weil der Browser so nur Zahlen „durchlässt“. Bei mobilen Geräten wird dann ein Nummernfeld eingeblendet, das die Eingabe erleichtert. Falls ein älterer Browser diese nicht kennt, erscheint ein normales Eingabefeld vom type="text", das ebenfalls die Eingabe einer Zahl zulässt. Diese wird dann aber nicht vom Browser, sondern erst vom Server validiert.

<input type="number"> und <input type="range"> in HTML werden beide für numerische Eingaben verwendet, aber sie dienen unterschiedlichen Zwecken und bieten unterschiedliche Benutzererfahrungen.

type = "number"

Ein Eingabefeld mit <input type="number"> beschränkt die Eingabe auf Zahlenwerte, wenn gewünscht, auch mit Dezimalstellen.[1]

Anwendungsfälle sind Eingaben, bei denen …

  • der Benutzer einen genauen numerischen Wert eingeben muss, z. B. ein Alter, eine Menge, einen Preis oder eine andere Zahl, bei der Präzision wichtig ist.
  • der Bereich der akzeptablen Werte breit ist oder nicht fortlaufend ist, so dass der Benutzer die genaue Zahl eingeben kann, die er möchte.
  • Nutzern die Möglichkeit geboten werden soll, den Wert mit Auf-/Ab-Pfeilen einzugeben oder anzupassen, was den Zugang für Nutzer mit Behinderungen erleichtert.

Berechnung des Body-Mass-Index

Zahleneingabe mit type="number" ansehen …
<form>
  <label for="groesse">
    Größe: 
    <input id="groesse" type="number" 
          min="100" max="220" step="1" value="175"
    inputmode="decimal">
    cm
  </label>
  <label for="masse">
    Masse: 
    <input id="masse" type="number" 
          min="30" max="225" step="0.5" value="75"
    inputmode="decimal">
    kg
  </label>
</form>

In diesem Beispiel werden zwei Zahleneingaben erwartet.

Folgende Attribute können verwendet werden:

  • max: legt Maximalwert fest.
  • min: legt Mindestwert fest.
  • step: legt fest, in welchen Stufen die Werte (durch eine Scrollbar) eingegeben werden dürfen.
  • value: Vorbelegung mit einem bestimmten Wert
  • inputmode: hilft mobilen Geräten, die richtige systemeigene Tastatur-(belegung) zu wählen.

Gestaltung mit CSS

Wenn man das input type="number"-Element im Inspektor im Chrome untersucht, kann man im Shadow DOM mehrere divs erkennen. Diese können mit CSS ausgeblendet werden:

    input[type="number"]::-webkit-outer-spin-button, 
    input[type="number"]::-webkit-inner-spin-button {
        -webkit-appearance: none;
        margin: 0
    }

    input[type="number"] {
        -moz-appearance: textfield
    }

Exkurs Zahlen vs Ziffern

Es gibt viele Dinge, die umgangssprachlich als Zahlen bezeichnet werden, eigentlich aber keine Zahlen sind und mit Zahlen nur das gemeinsam haben, dass sie zum Teil oder ganz aus Ziffern bestehen. So gibt es …

  • Hausnummern, die nicht nur Ziffern, sondern auch Buchstaben enthalten, z.B. 17A oder sogar Hausnamen
  • Postleitzahlen, die eine führende Null enthalten, wie z.B. 01099 Dresden, die aber eben nicht gestrichen werden kann.
    Im UK bestehen die post codes eh aus Buchstaben- und Ziffernkombinationen.
  • Telefonnummern, die Bindestriche und Leerzeichen enthalten; international hat sich anstelle der 0041 ein vorangestelltes +41 durchgesetzt
  • Auch eine IBAN besteht aus einer Kombination von zwei Buchstaben und je nach Land unterschiedlich vielen Ziffern.
  • die Reisepassnummer mit Prüfziffer und Ländercode in Buchstaben

Hier wäre ein Texteingabefeld mit einem pattern die geeignetere Methode.

Fazit: Zahlen stellen eine Menge oder einen Wert dar, der auch negativ oder eine Dezimalzahl sein kann und mit dem gerechnet werden kann.

Um Online-Formulare übersichtlich zu gestalten, kann man Abstände zwischen Zahlengruppen einfügen. Damit diese aber auch mittels „copy & paste“ ausgefüllt werden können, sind die strukturierenden Leerzeichen lediglich mit CSS eingefügt:

Empfänger
SELFHTML e.V.
IBAN
DE78830654080004043154
BIC
GENODEF1SLR

SELFHTML:Verein/Spenden

type = "range"

Das Eingabefeld <input type="range"> definiert einen Schieberegler (slider), mit dem der Benutzer einen Wert aus einem vordefinierten Wertebereich auswählen soll, indem ein Schiebeknopf (engl. thumb) entlang einer Skala (auch Schiene, engl. track) verschoben wird.[2]

Anwendungsfälle sind Eingaben, bei denen …

  • die Genauigkeit nicht entscheidend ist und der Benutzer aus einem Wertebereich auswählen kann, z. B. beim Einstellen der Lautstärke, der Helligkeit oder einer anderen Einstellung, bei der ein ungefährer Wert ausreicht.
  • du visuelles Feedback bieten möchtest, welcher Wert ausgewählt ist.
  • die Eingabe auf einen bestimmten Bereich beschränkt ist.

Da der Wertebereich vom Entwickler festgelegt ist, kann der Nutzer keine falschen Werte eingeben.

Oft finden sich solche Schieberegler nicht in Formularen, sonder auf Webseiten, bei denen Benutzereingaben gleich verarbeitet werden:

Formulare/Eingaben mit JavaScript auswerten

Schieberegler

Dieses Beispiel zeigt einen einfachen Schieberegler, dessen Wert gleich von einem kleinen Script übernommen wird:

Einfacher Schieberegler für Graustufen ansehen …
<figure>
  <img id="image" src="Autumn_Leaf.jpg" alt="Autumn leaves">
  <label for="grayscale">Verändere die Graustufen</label>
  <input id="grayscale" type="range" 
        min="0" max="100" value="30">
</figure>

Innerhalb des figure-Elements befindet sich ein Bild und ein Schieberegler.

  • max: legt den Maximalwert fest. (Standardwert ist 100)
  • min: legt den Mindestwert fest. (Standardwert ist 0)
    Diese Attribute hätten in diesem Beispiel weggelassen werden können!
  • value: Vorbelegung mit einem bestimmten Wert, an dem der Schieberegler eingestellt ist.

Der Wert des Schiebereglers wird mit JavaScript ausgelesen und mit JavaScript als Wert für den grayscale() Graustufenfilter verwendet:

document.querySelector('#grayscale').addEventListener('input', grayscaleImage);

function grayscaleImage() {
	var imageElement = document.querySelector('#image');
	var grayscaleInputElement = document.querySelector('#grayscale');
	imageElement.style.filter = 'grayscale(' + parseInt(grayscaleInputElement.value) /
		parseInt(grayscaleInputElement.max) + ')';
	return false;
}

Der Schieberegler hat leider keine Anzeige des aktuellen Werts. Mit dem output-Element kann der aktuelle Wert z.B. in einer Sprechblase dargestellt werden.

Gestaltung mit CSS

Wie alle Eingabeelemente weicht die Darstellung der Schieberegler von Browser zu Browser mehr oder weniger stark ab. Das ist jedoch nicht weiter schlimm, da Nutzer ja nur das UI ihres Browsers kennen und im Allgemeinen nicht vergleichen. Deshalb ist der Versuch Cross-Browser-Schieberegler zu erstellen, oft nur ein Herumschrauben an letzten Details.[3] [4]

Mit accent-color kann die Skala der Schiebereglers sowie der Schiebeknopf (im Firefox nur im gedrückten Zustand) mit einem Handgriff eingefärbt werden.

<input type="range" style="accent-color:gold">

Dies ist einfacher als das Ausblenden der Schiene mit appearance: none und Einfärben des Hintergrunds, wie es hier im Farbwähler erfolgt ist.

Schieberegler mit Sprungmarken

Die Skala des Schiebereglers kann mit datalist vorgeschlagene Werte als Sprungmarken erhalten. Zusätzlich zur Position des Schiebeknopfs soll der eingegebene Wert visualisiert werden:

Bewertungsfunktion mit Ergebnisausgabe ansehen …
<label for="content">Inhalt</label>
<input type="range" id="content" name="content" min="0" max="5" step="1" list="rating">
<output id="contentOutput" aria-live="polite"></output>

<label for="layout">Layout</label>
<input type="range" id="layout" name="layout" min="0" max="5" step="1" list="rating" >
<output id="layoutOutput" aria-live="polite"></output>

<datalist id="rating" style="--list-length: 6;">
  <option value="0">
  <option value="1">
  <option value="2">
  <option value="3">
  <option value="4">
  <option value="5">
</datalist>
  • list: legt fest, welche datalist für Vorschläge eingebunden wird.
    Sie erhält als Wert die id der Liste
    Beide Schieberegler referenzieren eine datalist
  • step: legt fest, in welchen Stufen die Werte eingegeben werden dürfen.
    (Wenn als Minimalwert 0, als Maximalwert 1 und Step 1 eingegeben wird, hat man einen (zugegebenermaßen uneleganten) Kippschalter.)

Das output-Element erhält ein aria-live-Attribut, dessen Wert polite den Screenreader anweist, das Ergebnis bei der nächsten Gelegenheit anzugeben.

Der zweite Schieberegler erhält mit accent-color eine goldene Färbung.

Nicht so schön ist die fehlende Beschriftung an den Sprungmarken, die im nächsten Beispiel hinzugefügt werden soll.

Man kann den Inhalt der datalist - die Textinhalte der option-Elements mit display sichtbar machen. Allerdings werden nur die Sprungmarken direkt unterhalb des Schiebereglers dargestellt, die Werte befinden sich unten (in der Reihenfolge des Markups).

So geht's:

Bewertungsfunktion mit beschrifteten Sprungmarken ansehen …
<input type="range" id="content" name="content" min="0" max="5" step="1" list="rating">
<datalist id="rating" style="--list-length: 6;">	
  <option value="0" label="0"></option>
  <option value="1" label="1"></option>
  <option value="2" label="2"></option>
  ...
  <option value="4">4</option>
  <option value="5">5</option>
  <option value="6">6</option>
</datalist>

Jedes option-Element erhält ein weiteres label-Attribut, dessen Werte nun mit CSS entlang der Sprungmarken sichtbar gemacht werden. Im unteren Schieberegler werden - da kein label-Attribut vorhanden- die Textinhalte des option-Elements dargestellt:

datalist {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
}

Nachteil dieser Methode: Jeder Schieberegler muss nun eine eigene Datalist erhalten.

Ein vertikaler Schieberegler

Gerade bei Größen und Höhenangaben ist es oft attraktiv einen vertikalen Schieberegler zu haben. Bis 2023 war die dafür erforderliche Vorgehensweise nicht einheitlich. Chromium-Browser erwarteten die CSS-Angabe -webkit-appearance: slider-vertical, während Firefox das proprietäre HTML-Attribut orient="vertical" verlangte. Der Internet Explorer war nochmal anders, hier musste man im CSS writing-mode: bt-lr angeben.

Diskussionen über den Einfluss der Schreibrichtung auf Schieberegler und andere HTML Elemente führten dazu, dass im März 2024 die HTML-Spezifikation abgeändert wurde und im Mai 2024 mit Opera auch der letzte große Browserhersteller die CSS-Eigenschaft writing-mode:vertical-lr zum Erstellen vertikaler Schieberegler unterstützt.

Etwas, was Schieberegler nur begrenzt unterstützen, ist die Anzeige von Beschriftungen für die einstellbaren Werte. Hierfür muss man mehrere HTML Elemente kombinieren und wir werden das bei diesem Schieberegler mit betrachten.

vertikaler Schieberegler ansehen …
CSS:
.labelled-vertical-range input[type="range"] {
	writing-mode: vertical-lr;   /* Standard 2024 */
    direction: rtl;              /* Damit das Minimum unten ist */
}
HTML:
<form>
  <label for="groesse">Bitte geben Sie Ihre Körpergröße an:</label>
  <div id="groesse-widget" class="labelled-vertical-range">
    <input type="range" name="groesse" id="groesse" min="0" value="80" max="250" list="körpergröße">
    <datalist id="körpergröße">
      <option value="50">50 cm</option>
      ...
      <option value="250">250 cm</option>
    </datalist>
    <output for="groesse">80</output>
  </div></form>

Das Beispiel verwendet nur noch writing-mode: vertical-lr, um die vertikale Ausrichtung des Schiebereglers anzufordern. Nach Umfragen im asiatischen Raum hat sich herausgestellt, dass dort ein Schieberegler bevorzugt wird, der von unten nach oben verläuft - das setzt aber eine Schreibrichtung von rechts nach links voraus. Die europäische Schreibrichtung ltr lässt den Schieberegler von oben nach unten verlaufen, deshalb wird explizit die rtl-Schreibrichtung gesetzt.

Ein Schieberegler ist aber ohne Beschriftungen nicht gut zu gebrauchen. Das eigentliche Beispiel soll die Darstellung deshalb um mehrere Aspekte erweitern:

  • Durch ein list-Attribut wird der Schieberegler mit einem datalist-Element verknüpft und bekommt dadurch Markierungsstriche für Größenschritte. Es stellte sich jedoch heraus, dass diese Markierungsstriche die Eigenschaft haben, den Schieber einzufangen und sich dieses Verhalten nicht abstellen lässt, was für die Körpergröße unpraktisch ist. Deshalb haben wir die Verknüpfung wieder entfernt, das datalist-Element aber stehen gelassen. In Fällen, wo dieses Einfang-Verhalten erwünscht ist, können Sie dem input-Element die Eigenschaft list="körpergröße" (oder wie auch immer dann die id Ihrer Datenliste ist) hinzufügen.
  • Damit die Listenwerte angezeigt werden, wird das datalist-Element mittels eines Grids rechts neben den Schieberegler gesetzt. Das output-Element, das die eingestellte Höhe anzeigen soll, wird in einer dritten Grid-Spalte hinzugefügt.
  • Die Werteverbindung zwischen Schieberegler und output-Element erfolgt mittels JavaScript.

Schauen Sie sich das Beispiel per "Ausprobieren" Frickl oder im Quellcode an, um alle Einzelheiten zu studieren.

Beachten Sie dabei aber auch die Nachteile dieser Konstruktion. Die Werteliste muss über ihren Top- und Bottom-Margin so angepasst werden, dass der minimale und maximale Wert auf exakt der richtigen Höhe stehen, vor allem dann, wenn die Datenliste zugeordnet wird und Markierungsstriche sichtbar sind. Ist die von Ihnen eingestellte Schriftart auf dem Benutzercomputer nicht verfügbar, stehen sie möglicherweise falsch.

Custom-Element mit synchronisierten Range- und Number-Inputs

Für die Eingabe von Zahlen gibt es das Input-Element mit type="number" für exakte Werte und das Input-Element mit type="range" für die schnelle aber ungenaue Eingabe. Im Folgenden wird gezeigt, wie diese beiden Zahleingaben kombiniert werden können. Dazu werden zwei Input-Elemente mit type="range" und Type="number" in ein fieldset-Element gelegt. Dazu kommen noch ein legend- und ein label-Element.

Das HTML und das dazugehörige CSS sehen dann so aus:
fieldset { max-inline-size: fit-content; }
fieldset * { display: inline-block; vertical-align: top; margin: 0; padding: .1em}
input { font-size: .9em; }
<fieldset part="fieldset">
  <legend part="legend">Legende</legend>
  <label for="5050098864631646" part="label">Label</label>
  <input type="range" min="0" max="100" step="1" value="50" part="range">
  <input id="5050098864631646" type="number" min="0" max="100" step="1" value="50" part="number">
</fieldset>

Das fieldset bekommt dann noch einen Eventhandler für das input-Event, womit durch Event-Delegation die input-Events der beiden input-Elemente überwacht werden. Der Handler prüft dann, welches der beiden Inputs das Event ausgelöst hat, und überträgt dann seinen Wert (value) auf das andere:

Javascript zum Synchronisieren der Inputs
document.querySelector('fieldset').addEventListener('input', event => {
  if(event.target.type == "range") {
    const input_number = event.target.parentNode.querySelector("[type=number]");
    input_number.value = event.target.value;
  }
  else if(event.target.type == "number") {
    const input_range = event.target.parentNode.querySelector("[type=range]");
    input_range.value = event.target.value;
  }
});

Im Einsatz ist es allerdings nicht praktisch, für jedes Kombi-Input fünf HTML-Elemente plus CSS plus Javascript zu verwenden. Daher wird ein Custom Element definiert, das die kombinierte Eingabe einer Zahl durch Tastatur und Schieberegler ermöglicht und sich im Dokument ähnlich wie ein Input-Element verhält. Das Element wird <self-slider> genannt.

Wie ein Custom-Element erstellt wird, ist in diesem Artikel beschrieben: Web Components/custom elements

Aus dem Grundgerüst werden die Funktionen constructor, connectedCallback und attributeChangedCallback benötigt. Im constructor werden das Schatten-DOM und das benötigte CSS angelegt, und es werden die Defaultwerte für die Attribute festgelegt. Im connectedCallback wird dann das benötigte HTML definiert und ins Schatten-DOM eingehängt. Auch der Handler für das input-Event wird hier notiert.

Die Methode attributeChangedCallback reagiert auf das Setzen und Ändern von Attributen. Sie reagiert auf die Attribute, die mit

Javascript
static get observedAttributes() {
  return ['legend', 'label', 'min', 'max', 'step', 'value'];
}

festgelegt wurden.

Um aus dem Custom-Element <self-slider> jetzt noch ein Formularelement zu machen, sind zwei Zeilen nötig. Am Anfang der Klasse muss static formAssociated = true; gesetzt werden, und bei jeder Änderung des Input-Values muss dieser mit this.internals.setFormValue(this.currentValue); an das umgebende Formular übergeben werden.

Das fertige Custom Element sieht dann so aus:

Beispiel ansehen …



Schieberegler mit Mehrfacheingaben (multirange)

In HTML5.1 sollte neu ein Attribute multiple eingeführt werden, das Mehrfacheingaben ermöglicht.

Schieberegler mit zwei verschiebbaren Eingabepunkten
<input type="range" multiple value="10,80">

Lea Verou hat einen kleinen Polyfill programmiert, mit dem es jetzt schon ausprobiert werden kann.[5]

Dies wäre auch ein guter Use Case für ein Web Component.



Weblinks

  1. MDN: <input type="number">
  2. MDN: <input type="range">
  3. Creating A Custom Range Input That Looks Consistent Across All Browsers von Alyssa Holland, 23.12.2021 (smashing magazine)
  4. Styling Cross-Browser Compatible Range Inputs with CSS von Daniel Stern Jun 2, 2020 (css-tricks)
  5. Introducing Multirange: A tiny polyfill for HTML5.1 two-handle sliders (Lea Verou)