JavaScript mit dem debugger Keyword pausieren lassen

Dieser Blogbeitrag soll keine grundlegende Einführung in das Debugging mit JavaScript sein. Wir könnten wahrscheinlich einen ganzen Adventskalender mit allen Aspekten füllen. Aber ich möchte ein kleines Schlüsselwort für eure Debugging-Toolbox vorstellen.

Einen Breakpoint im Browser setzen

Wenn ihr einen JavaScript-Code debuggen wollt, dann setzt ihr wahrscheinlich irgendwann einen Breakpoint in eurem Code. Wenn ihr eine kleine JavaScript-Datei habt, die schön formatiert ist, sieht sie in Chrome vielleicht so aus:

Chrome Entwicklertools mit einem manuellen gesetzten Breakpoint, der den Browser an dieser Zeile pausieren lässt.

Ihr öffnet dazu die Entwicklertools, navigieren auf der Registerkarte „Quellcode“ („Sources“) zur JavaScript-Datei, setzen einen Breakpoint und laden die Seite neu. Chrome hält dann an der Zeile an, und ihr könnt euren Code debuggen.

Das Problem mit kompiliertem JavaScript-Code

Diejenigen unter euch, die Code mit React, Vue usw. entwickeln und Webpack oder ähnliche Tools zum Kompilieren eures Codes verwenden, die erhalten keinen so schön formatierten Code, der auch noch leicht zu lesen ist. Fügen wir unseren Code von oben in den Kompilierungs-Workflow aus dem Paket @wordpress/scripts ein und kompilieren ihn:

npm run build

Jetzt erhalten wir eine kompilierte „Produktions-Datei“, und unser schön formatierter Code ist jetzt nur noch eine einzige Zeile in dieser kompilierten Datei:

Chrome Entwicklertools, die eine minifizierte Datei anzeigen.

Wie setzen wir jetzt einen Breakpoint? Wenn ihr einen Breakpoint in einer „einzeiligen JavaScript-Datei“ setzen wollt, gibt es eine kleine Funktion, die ihr verwenden können. Klickt dazu einfach auf das „{}“ Symbol („Quelltextformatierung“) unten links in der mittleren Spalte, und ihr erhaltet etwas wie im folgenden Screenshot. Hier könnt ihr nun einen Haltepunkt in der „virtuellen Zeile“ setzen:

Chrome dev tools "pretty printing" the one-line JavaScript file and a manual break point set on a prettified line.

Das funktioniert einigermaßen. Aber wenn ihr den Aufruf von console.log() am Ende der Datei debuggen wollt, dann stehen sie immer noch in einer Zeile und auch noch zusätzlich in einem ternären Operator.

Verwendung des debugger Keywords für einen „erzwungenen Breakpoint“

Nach dieser kurzen Einführung kommen wir nun zu dem Keyword, über das ich heute sprechen wollte. Während ihr euren Code entwickelt, können ihr das debugger Keyword an eine beliebige Zeile eures Codes einfügen, wodurch der Browser gezwungen wird, an dieser Stelle zu pausieren. Verwenden wir es also in der kompilierten Version, um den „if“-Teil des ternären Operators zu debuggen. Wir verwenden nun einen anderen Befehl, um die „Entwicklungsversion“ zu erhalten, der auch einen Watcher startet und den Code kompiliert, sobald wir etwas ändern:

npm run start

In unserem JavaScript-Code fügen wir außerdem das debugger Keyword wie folgt am Ende des if/else ein:

if (found) {
    debugger;
    console.log(`there is a 4 in array ${found}'`);
} else {
    console.log("There is no 4 in the array");
}

Wenn wir den Browser jetzt aktualisieren, wird er bei diesem Keyword in Zeile 17 anhalten. Wir müssen hier keinen Breakpoint setzen:

Chrome dev tool showing a JavaScript file stopped at the "debugger" keyword.

Oben rechts seht ihr „Debugger paused“ und das Skript ist angehalten, genau wie bei einem von uns manuell gesetzten Breakpoint in dieser Ansicht. Wir können nun mit unserem Debugging fortfahren.

Verwendung des debugger Keywords in minifizierten Dateien

Eine Anmerkung vorweg: ihr solltet das wahrscheinlich nicht tun. Wenn ihr das „build“-Skript verwendet, dann erstellt ihr normalerweise Dateien für den produktiven Einsatz und diese sollten kein debugger Keyaord enthalten. Aus diesem Grund entfernt das Webpack-Minifizierungs-Plugin dieses Keyword automatisch. Wenn ihr, aus welchen Gründen auch immer, das debugger Keyword in den kompilierten Dateien haben wollt, müsst ihr eine eigene webpack.config.js Webpack-Konfigurationsdatei schreiben:

const defaultConfig = require('@wordpress/scripts/config/webpack.config');
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
    ...defaultConfig,
    optimization: {
        ...defaultConfig.optimization,
        minimize: true,
        minimizer: [
            new TerserPlugin({
                terserOptions: {
                    compress: {
                        drop_debugger: false,
                    },
                },
            }),
        ],
    },
};

Wenn wir jetzt npm run build ausführen und den Browser aktualisieren, sehen wir das Keyword und der Browser bleibt dort stehen:

Chrome dev tool showing a JavaScript file stopped at the "debugger" keyword in a "prettified" minified code.

Dies würde auch automatisch das „Quelltextformatierung“-Symbol unten links aktivieren und euren Code wie oben zeigen.

Fazit

Es kann manchmal schwierig sein, einen Breakpoint manuell zu setzen, besonders wenn eure JavaScript-Dateien kompiliert, kombiniert und sogar minifiziert wird und ihr keine Ahnung haben, wo eine Zeile, die ihr gerade geschrieben habt, am Ende zu finden ist. Ihr können das debugger Keyword auch nur vorübergehend setzen, und sobald das Skript angehalten wurde, einen regulären Haltepunkt setzen, um das Schlüsselwort dann sofort zu entfernen, damit ihr nicht versehentlich Code mit dem Keyword darin veröffentlicht.

Das HTML meter Element und wie es funktioniert

Dieser Blogbeitrag behandelt ein Element, das dem progress Element aus einem vorherigen Blogbeitrag sehr ähnlich ist. Es wird verwendet, um eine Art „Füllstand“ wie bei einer Batterie oder eine „Score“ (Punktzahl) wie bei einem Online-Test anzuzeigen. Diese Visualisierungen werden in der Regel durch einen Minimal- und Maximalwert definiert.

Ein einfaches Beispiel für das meter Element

Beginnen wir mit einem sehr einfachen Beispiel, mit nur den Attributen, die mindestens notwendig sind. Die folgenden müssen wir implementieren:

<label for="score">Score:</label>
<meter id="score" value="0.5">50%</meter>

OK, das zugehörige <label> ist optional. Aber vermutlich habe ihr mittlerweile bemerkt, dass ich immer versuche Beispiele zu geben, bei denen die Barrierefreiheit beachtet wird.

Das Element hat ein min Attribut, das standardmäßig auf 0 gesetzt wird, wenn es nicht definiert wurde, während max auf 1 gesetzt wird. Wenn wir sie also nicht definieren, würden wir einen Wertebereich zwischen 0 und 1 verwenden und damit würde unser Wert von 0,5 dann 50% auf dem Zähler darstellen. Das Ergebnis würde dann so aussehen:

A label "Score" followed by the meter element that is half "filled" with a green background.

Ähnlich wie beim <progress> Element sehen wir den „Textknoten“, auf dem „50%“ steht, nicht. Dieser wird nur angezeigt, wenn das Element vom Browser nicht unterstützt wird.

Verwendung der zusätzlichen Attribute, um das Element noch nützlicher zu machen

Beim <progress> Element gab es nur ein max und value Attribut. Das <meter> Element hat viel mehr Attribute und sie machen den großen Unterschied zwischen den beiden Elementen aus. Hier ist ein Beispiel mit allen Attributen, die wir verwenden können:

<meter min="-20" max="100" low="10" high="40" optimum="25" value="10">10°C</meter>

Wir können die Attribute min und max explizit angeben. Das min Attribut ist auch nicht auf 0 festgelegt, sondern kann jeden beliebigen Wert annehmen, auch einen negativen, z. B. für eine Temperaturskala mit Minusgraden. So würde das für verschiedene Temperaturwerte aussehen:

Seven meter elements ranging from -20°C to 100°C with the temperature 10°C, 25°C and 40°C with a green background, the other ones with a yellow background.

Wenn wir einen optimum Wert zwischen dem min und dem max Attributwert festlegen (der Wert kann zwischen 10 und 40 liegen), wird dieser Bereich mit einem grünen Hintergrund dargestellt. Jeder Bereich, der unter dem min Wert oder über dem max Wert liegt, wird gelb dargestellt.

Ein meter Element mit drei verschiedenen Farben

Nehmen wir ein weiteres Beispiel mit einem Test-Score. Wir würden den Test als „bestanden“ definieren, wenn wir 50 % oder mehr erreichen und er wäre „gut“, wenn wir 80 % oder mehr schaffen. Diese Elemente würden unterschiedliche Punktzahlen darstellen:

<meter min="0" max="100" low="50" high="80" optimum="100" value="0">    0%</meter>
<meter min="0" max="100" low="50" high="80" optimum="100" value="10">  10%</meter>
<meter min="0" max="100" low="50" high="80" optimum="100" value="20">  20%</meter>
<meter min="0" max="100" low="50" high="80" optimum="100" value="30">  30%</meter>
<meter min="0" max="100" low="50" high="80" optimum="100" value="40">  40%</meter>
<meter min="0" max="100" low="50" high="80" optimum="100" value="50">  50%</meter>
<meter min="0" max="100" low="50" high="80" optimum="100" value="60">  60%</meter>
<meter min="0" max="100" low="50" high="80" optimum="100" value="70">  70%</meter>
<meter min="0" max="100" low="50" high="80" optimum="100" value="80">  80%</meter>
<meter min="0" max="100" low="50" high="80" optimum="100" value="90">  90%</meter>
<meter min="0" max="100" low="50" high="80" optimum="100" value="100">100%</meter>

In diesem Codebeispiel liegt unser optimum Wert zwischen high und max. Wenn der Wert von optimum größer ist als der Wert von max (wir haben ihn einfach auf 100 gesetzt), erhalten wir drei verschiedene Hintergrundfarben:

Eleven meter elements ranging from 0% to 100%. The background at 0% is not visible and values 10% to 40% have a green red background. Values 50% to 70% have a yellow and values 80% to 100% have a green background.

Das spiegelt unsere Definition der Punktzahl perfekt wider, oder nicht? Wenn ihr euch sich nicht sicher seid, wie ihr die Werte für die Attribute festlegen müsst, schaut in der Dokumentation nach und testet verschiedene Werte in verschiedenen Browsern.

Styling des Elements

Es gibt nur wenige CSS-Eigenschaften, die wir in WebKit-Browsern verwenden können. Safari benötigen sogar einen JavaScript-Hack, damit sie funktionieren. Ihr findet sie im Abschnitt „See more“ der Dokumentation verlinkt.

In Chrome können wir sie mit einem Attributselektor kombinieren, um die Hintergrundfarbe des genauen „optimalen Werts“ für das Temperaturbeispiel wie folgt zu ändern:

meter[value="25"]::-webkit-meter-optimum-value {
	background-color: blue;
}

In Firefox hätte dies jedoch keine Auswirkung. Sobald ihr den Hintergrund des Elements ändern, sieht es völlig anders aus (genau als wenn ihr "appearance: none“ darauf anwendet). Ich euch empfehlen, einfach mal ein wenig mit dem Element zu experimentieren.

Fazit

Das <meter> Element ist wahrscheinlich eines der weniger bekannten Elemente, aber es kann eine nette Ergänzung für eure Benutzeroberfläche sein, um Zahlen besser zu visualisieren. Für das <progress> Element hatten wir die ProgressBar-Komponente für WordPress, aber für <meter> gibt es leider keine Komponente in WordPress.

Bessere Lesbarkeit mit reduzierter Transparenz

Heute möchte ich über eine CSS-Funktion schreiben, die noch experimentell ist. Aber sie kann einen Unterschied für alle machen, die Schwierigkeiten haben, Text auf transparenten Elementen zu lesen.

Auf vielen Websites finden wir Elemente, die Text auf einem Bild platzieren. Dies ist oft ein großes Problem für die Lesbarkeit des Textes.

Text auf einem Bild

Sehen wir uns hierzu ein kleines Beispiel an. WordPress bietet den „Cover“-Block an. Wenn wir ihn verwenden, wird das Bild zu einem Hintergrundbild. Der Block verfügt über ein Steuerelement für die „Overlay-Deckkraft“. Wenn die Deckkraft auf einen Wert von 21 oder weniger eingestellt ist, wird der Text standardmäßig schwarz angezeigt. Wenn der Wert auf 22 oder höher gesetzt ist, wird die Textfarbe auf Weiß umgestellt.

Cliffs in the archipelago of Åland with stones coverd in lichen in the front and the sea (blurred) in the back.

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

Wie wir im obigen Beispiel sehen können, ist der Text im oberen Teil schwer zu lesen, selbst wenn man normalerweise keine Probleme mit dem Lesen von Text auf Bildern hat. Für mich als Legastheniker kann das extrem frustrierend sein, Text so zu lesen.

Verwendung einer Präferenz zur Verringerung der Transparenz

Die neue CSS-Eigenschaft, über die ich heute schreiben möchte, heißt prefers-reduced-transparency und verwendet genau wie die Präferenz für reduzierte Bewegungen den Wert reduce. Hier ist ein Beispiel für den Cover-Block:

@media (prefers-reduced-transparency: reduce) {
    .has-background-dim {
        opacity: .7;
    }
}

In einem früheren Blogbeitrag habe ich erklärt, wie man Präferenzen im Browser simulieren kann. Wenn ihr die Rendering-Einstellung bei euch simuliert, dann würde der Cover-Block nach der Änderung der Deckkraft so aussehen:

Cliffs in the archipelago of Åland with stones coverd in lichen in the front and the sea (blurred) in the back.

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

Ist das nicht viel besser zu lesen? Die Deckkraft zu ändern, wenn jemand eine geringere Transparenz bevorzugt, ist ziemlich einleuchtend. Aber wie bei jeder anderen Media-Query könnt ihr auch hier beliebige CSS-Eigenschaften verwenden. Anstatt also die Deckkraft zu ändern, könntet ihr auch das Element ändern.

Wie wäre es z.B. damit, den Text unterhalb des Bildes ohne Transparenz und mit schwarzem Text auf weißem Hintergrund zu platzieren? Oder wir richten den Text neben dem Bild aus. Seid kreativ und macht eure Inhalte für Menschen mit unterschiedlichen Präferenzen und Bedürfnissen besser lesbar.

Fazit

Es gibt so viele CSS-Eigenschaften, die unbekannt oder noch nicht weit verbreitet sind. Diese spezielle Eigenschaft kann bereits in Chromium-Browsern verwendet werden und Firefox-Benutzer können ein Flag setzen, um sie zu verwenden. Wenn ihr Windows 10/11, macOS oder iOS verwenden, können ihr diese Präferenz ebenfalls bereits einstellen, wie in der Dokumentation erklärt wird. Angesichts der bereits guten Betriebssystem-Unterstützung würde es mich überraschen, wenn diese neue Media-Query noch lange experimentell bleiben würde.

Natürliche Sortierung in JavaScript

Wenn ihr in eurem Code nur mit englischen Strings zu tun habt, dann können ihr jetzt aufhören weiter zu lesen. Es sei denn, ihr sind neugierig und wollt etwas Neues lernen, dann bleiben bitte dran. 😉

In Sprachen wie Deutsch gibt es Zeichen, die im englischen Alphabet nicht vorkommen. Manche sehen anderen Zeichen ähnlich, aber manche sind extra. Und im Deutschen haben wir nur 4 davon, andere Sprachen haben viele mehr.

Wie Strings normalerweise sortiert werden

Wenn ihre ein Array von Strings habt, gibt es verschiedene Möglichkeiten, wie sie sortiert werden. Schauen wir uns einige Beispiele an:

console.log(['c', 'b', 'a', 'B', 'A', 'C'].sort())
// (6) ['A', 'B', 'C', 'a', 'b', 'c']

Diejenigen von euch, die schon einmal Code geschrieben und mit einer einfachen Sortierfunktion ein Array von Strings sortiert haben, ist vielleicht aufgefallen, dass viele dieser Funktionen die Reihenfolge der Zeichen in der ASCII-Tabelle verwenden. Deshalb sehen wir zuerst die Großbuchstaben, gefolgt von den Kleinbuchstaben.

Das mag für Englisch genau das sein, was wir erwarten und wollen. Aber was passiert, wenn wir ein paar deutsche Umlaute in das Array einfügen:

console.log(['ä', 'b', 'a', 'B', 'Ä', 'A'].sort())
// (6) ['A', 'B', 'a', 'b', 'Ä', 'ä']

Hm, das große „Ä“ kommt nach allen anderen Kleinbuchstaben, das hätten wir selbst eher nicht so sortiert. Da die Umlaute nicht Teil der ASCII-Tabelle sind (wie die meisten Buchstaben, die nicht in „Basic Latin“ enthalten sind), verwendet JavaScript die UTF-16 Codes, um sie zu sortieren. Diese stellen jedes Zeichen mit einer Zahl dar. Der Buchstabe „Ä“ zum Beispiel hat den numerischen Wert 228, während „z“ den Wert 122 hat, und deshalb ist er wie oben vor dem „Ä“ angeordnet.

Einsatz des Intl.Collator Objekts für die natürliche Sortierung

Die Lösung für dieses Problem ist wirklich sehr einfach. Die sort() Funktion für ein Array kann eine Callback-Funktion als Parameter übergeben bekommen. Dieser Funktion werden zwei Werte des Arrays übergeben. Sie soll eine negative Zahl zurückgeben, wenn der erste Wert kleiner ist als der zweite, eine positive Zahl, wenn das Gegenteil der Fall ist, oder 0, wenn beide den gleichen Wert haben.

Aber wir müssen eine solche Callback-Funktion nicht für jede Sprache selbst schreiben. Stattdessen können wir das Intl.Collator Objekt verwenden. Für unser Beispiel mit den deutschen Umlauten würde der Code wie folgt aussehen:

console.log(['ä', 'b', 'a', 'B', 'Ä', 'A'].sort(new Intl.Collator('de').compare));
// (6) ['a', 'A', 'ä', 'Ä', 'b', 'B']

Jetzt haben wir nicht nur unsere Umlaute neben den ähnlich aussehenden Buchstaben, sondern wir erhalten auch jeden Kleinbuchstaben gefolgt von seinem Großbuchstaben. Das ist auch das, was man von einer „Wörterbuchsortierung“ erwarten würde.

Direkte Verwendung der Vergleichsfunktion

Wie bereits erwähnt, erwartet die Funktion sort() eine Callback-Funktion, der eine negative oder positive Zahl oder eine 0 zurückgibt. Und genau das tut die Funktion auch. Wir können diese Funktion direkt aufrufen (und nicht nur auf ihren Namen übergeben) und zwei Buchstaben zum Vergleich übergeben:

new Intl.Collator('de').compare('ä', 'a')
// 1
new Intl.Collator('de').compare('a', 'ä')
// -1
new Intl.Collator('de').compare('a', 'a')
// 0

Um zu zeigen, dass diese Funktion nicht einfach eine statische Liste von Zahlen für jedes Zeichen verwendet, sondern wirklich nach einer bestimmten Sprache sortiert, habe ich hier ein gutes Beispiel dafür:

new Intl.Collator('de').compare('ä', 'z')
// -1
new Intl.Collator('sv').compare('ä', 'z')
// 1

Die schwedische Sprache, die ich gerade versuche zu lernen, hat auch den Buchstaben „ä“. Er ist jedoch anders sortiert als ein deutscher Umlaut, und man findet Wörter, die mit „ä“ beginnen, in einem schwedischen Wörterbuch fast am Ende (erst danach folgen Wörter, die mit „ö“ beginnen).

Erweiterte Optionen verwenden

Es gibt einige Optionen, die ihre zusätzlich als ein Objekt an die Funktion sort() übergeben könnt, wie in diesem Beispiel, wenn ihr die Großbuchstaben zuerst haben möchtet:

console.log(
	['ä', 'b', 'a', 'B', 'Ä', 'A'].sort(
		new Intl.Collator(
			'de', 
			{
				caseFirst: 'upper'
			}
		).compare
	)
);
// (6) ['A', 'a', 'Ä', 'ä', 'B', 'b']

Weitere Optionen finden ihr auf der Dokumentationsseite oder eine vollständige Liste in der ECMA-Spezifikation. Es gibt sogar einige wilde „Sprachen“ wie"de-u-co-phonebk„, um ein Array so anzuordnen, wie es in einem deutschen Telefonbuch stehen würde – falls ihr wisst, wovon ich rede. 😁

Bonus: Zahlenreihen sortieren

Ich möchte nicht über alle Optionen schreiben, aber eine könnte in eurem Code wirklich hilfreich sein. Wenn ihr schon einmal ein Array mit Zahlen als Strings sortiert habt, dann wissen ihr bestimmt, dass die alphanumerische Sortierung hier nicht funktioniert:

console.log(['1', '2', '11', '101', '3'].sort());
// (5) ['1', '101', '11', '2', '3']

Aber mit der Option numeric erhält man eine Sortierung, die man erwarten würde (der erste Parameter „Sprache“ ist hier vermutlich nicht so wichtig):

console.log(
	['1', '2', '11', '101', '3'].sort(
		new Intl.Collator(
			'en',
			{
				numeric: true
			}
		).compare
	)
);
// (5) ['1', '2', '3', '11', '101']

Genau das, was wir haben wollten. 😊

Fazit

Die Sortierung von Strings nach ihrer natürlichen Reihenfolge in einer bestimmten Sprache kann wirklich einen großen Unterschied in Bezug auf die Nutzbarkeit eures Codes machen (oder sogar dazu führen, dass der Code kaputt ist, wenn falsch sortiert wird). Mit dem Intl.Collator Objekt ist das in JavaScript auch recht einfach möglich. Andere Programmiersprachen bieten oft kein so mächtiges Werkzeug an.

Präferenzen im Browser simulieren

Bevor wir uns mit einigen weiteren Themen im Adventskalenders beschäftigen, müssen wir etwas über eine Browserfunktion erfahren, die wir dazu brauchen werden. Deshalb habe ich die Reihenfolge meiner geplanten Themen zum Debugging ein wenig umgestellt, um dieses Thema früher zu behandeln.

In einigen meiner nächsten Blog-Beiträge werde ich über ein paar CSS-Funktionen sprechen, die bestimmten Personen zugutekommen können, die eure Website besuchen. Vor fast 5 Jahren habe ich in einem Blog-Beitrag beschrieben, wieso man „Bewegungen auf einer Webseite für eine bessere Barrierefreiheit reduzieren“ sollte. In diesem Blogbeitrag habe ich erklärt, wie ihr die Einstellungen in Windows 10 oder Android 9 ändern könnt, um die Präferenz für reduzierte Bewegungen zu simulieren. Aber vielleicht verwendet ihr ein anderes Betriebssystem (wie ich z.B. Manjaro Linux für die Arbeit), bei dem es keine Schnelleinstellung gibt. Oder aber, ihr möchtet die Einstellung schneller umschalten können. Glücklicherweise gibt es bei einigen Browsern einen solchen Umschalter für euch.

Einstellungen in Chrome vornehmen

In Chrome (und anderen auf dem Chromium-Projekt basierenden Browsern wie Edge) finden ihr die meisten Einstellungen, indem ihr auf die drei vertikalen Punkte oben rechts klicken, dann „Weitere Tools“ auswählt und dort die „Rendering“ Einstellungen anklickt:

Screenshot, wie man die "Weitere Tools > Rendering" Einstellungen öffnet.

Dadurch öffnet sich ein weiteres Panel in den Entwicklertools. Wenn ihr ein wenig nach unten scrollt, finden ihr dort diese Einstellungen, mit denen ihr verschiedene Vorlieben simulieren könnt. In diesem Beispiel setze ich prefers-reduced-motion auf reduce:

Screenshot mit den diversen Rendering Einstellungen und der "prefers-reduced-motion" Einstellung geöffnet.

Der einzige Nachteil dieser Einstellung: sobald ihr die Entwicklertools schließt, wird die Einstellung auf ihren Standardwert zurückgesetzt. Wenn ihr also eine Website testen möchten, auf der mehr vertikaler Platz zur Verfügung stehen soll (da die beiden Panels viel Höhe beanspruchen), würde ich vorschlagen, die Entwicklertools in einem separaten Fenster anzuzeigen.

Wir werden diese Einstellungen für die kommenden Themen benötigen. Aber es gibt noch mehr Möglichkeiten, Einstellungen zu simulieren, die das Verhalten und das Aussehen eurer Website verändern. Wenn ihr beispielsweise eure Website schnell mal mit einem dunklen Farbschema anzeigen lassen möchtet, dann müssen ihr nicht euer Betriebssystem auf ein dunkles Farbschema umstellen oder die Rendering-Einstellungen öffnen. Stattdessen finden ihr im Abschnitt „Stile“ eine nette Umschaltfunktion. Klickt einfach auf das „Pinsel“-Symbol und wechselt hier zu dem Farbschema, das ihr testen möchtet.

Screenshot des geöffneten Umschalters für die "prefers-color-scheme" Einstellung.

Leider wird das Farbschema, genau wie beim Rendering-Panel, wieder auf den Standardwert zurückgesetzt, sobald ihr die Entwicklertools schließen.

Einstellungen in Edge vornehmen

Obwohl Edge auf Chromium basiert und viele Entwicklertools genau gleich aussehen, finden ihr in Edge nicht das Panel „Weitere Tools > Rendering“. Stattdessen öffnen ihr hierzu erst die Entwicklertools. Auf Panels wie „Elements“ seht ihr im unteren Teil die „Konsole“ und „Probleme“. Hier klickt ihr dann auf das „+“-Symbol und wählt die „Rendering Schnellansicht“. Nach dem Öffnen sieht sie den Einstellungen in Chrome sehr ähnlich.

Screenshot des geöffneten "Tools zur Schnellansicht hinzufügen" Panels in Edge.

Auch in Edge können ihr das Farbschema mit einem „Pinsel“-Symbol schnell umschalten, genau wie in Chrome.

Einstellungen in Firefox vornehmen

In Firefox sind die Einstellungen nicht leicht zugänglich. Außerdem befinden sie sich an verschiedenen Stellen. Wenn ihr prefers-reduced-motion einstellen möchtet, müsst ihr zur URL about:config navigieren, dann nach ui.prefersReducedMotion suchen, einen booleschen Wert hinzufügen und ihn auf false setzen. Für prefers-reduced-transparency müsste ihr hingegen nach layout.css.prefers-reduced-transparency.enabled suchen und diesen Wert auf true setzen. Das ist alles sehr inkonsistent und ärgerlicherweise nicht an einem Ort.

Wenn wir das Farbschema umschalten wollen, haben wir mehr Glück. Firefox bietet zwei Schaltflächen an. Mit dem „Sonnensymbol“ können ihr den hellen Farbmodus und mit dem „Mondsichelsymbol“ den dunklen Farbmodus erzwingen.

Screenshots des Buttons zur Simulation des dunkeln Farbschemas in Firefox.

Wenn ihr eine der beiden Schaltflächen aktiviert, wird automatisch die andere deaktiviert. Wenn ihr beide deaktiviert, wird wider der Standardmodus verwendet.

Bonus: schnelleres Umschalten der Einstellungen in Chromium-Browsern

Ich kann euch leider nicht sagen, wie ihr die Einstellungen in Safari ändern könnt, da ich keinen Mac benutze (oder Safari nicht oft genug simuliere). Aber ich habe einen netten kleinen Bonus-Tipp für euch. Wenn ihr eine dieser Einstellungen schnell ändern möchtet, können ihr die Funktion „Befehl ausführen“ in Chromium-Browsern verwenden.

Drücken hierzu bei geöffneten Entwicklertools die Tastenkombination „Strg + Umschalt + P“ (oder „Cmd + Umschalt + P“ auf einem Mac) und sucht dann nach der Einstellung, die ihr umschalten möchten:

Screenshot vom "Ausführen" Dialog in Chrome.

Ich habe keine entsprechende Funktion in Firefox gefunden, aber vielleicht kennt sie ja jemand von euch?

Fazit

Wenn ihr eine Website entwickelt, die sich je nach Einstellungen des Betriebssystems anders verhält oder anders gerendert wird, sollten ihr dies immer testen. Aber ihr müssen dazu nicht die Einstellungen eures Betriebssystems ändern. Browser haben normalerweise Optionen, um diese zu emulieren.

Wenn jemand von euch bessere Optionen für diese Einstellungen in Firefox oder eine Erweiterung kennt, mit der man diese einfacher umstellen kann, dann teilt den Tipp bitte in den Kommentaren.

Einen Fortschrittsbalken auf eurer Website anzeigen

Wenn Sie eine Webanwendung programmiert, bei der die Anzeige des aktuellen Fortschritts die UX verbessern würde, kann ein netter kleiner Fortschrittsbalken helfen. Und es gibt eine einfache Möglichkeit, einen hinzuzufügen. In der Vergangenheit haben wir dazu etwas wie jQuery UI Progressbar verwendet. Heute können wir jetzt ein natives HTML-Element verwenden.

Das progress HTML-Element

Stellt euch vor, ihr müsst ein Element zur Visualisierung eines Fortschritts auf einer Website erfinden. Wenn ihr überlegt, wie es aussehen würde und welche Attribute es haben sollte, dann kommt ihr vielleicht auf etwas Ähnliches wie das Range-Input, über das ich in einem früheren Beitrag geschrieben habe. Aber das Element ist viel einfacher:

<label for="progress-bar">Progress:</label>
<progress id="progress-bar" value="30" max="100">30 %</progress>

So sieht das native <progress> HTML-Element in Chrome mit dem obigen Code aus:

A label "Progress:" followed by the progress element with a 30% progress.

Wie ihr sehen könnt, ist das Element inline. Und fällt euch etwas auf? Obwohl es sich nicht um ein Formularelement handelt, wurde es mit einem Label kombiniert. Das verbessert seine Barrierefreiheit. Wenn ihr den Wert als Text-Kind-Element hinzufügen, wird dieser Text im Browser nicht angezeigt, wenn das Element unterstützt wird. Es ist also nur notwendig, wenn ihr es mit einem wirklich alten Browser zu tun habt, der das Element nicht unterstützt. Dann wird stattdessen dieser Text inline angezeigt.

Fortgeschrittene Verwendung des Elements

Ist euch aufgefallen, dass wir in dem Beispiel kein min Attribut gesetzt haben? Dieses Attribut ist nicht einmal verfügbar, denn der Standardwert für min ist immer 0.

Aber wussten ihr auch, dass ihr sogar auf das value Attribut verzichten könnt und was dann passieren würde? Vermutlich würde man nicht sofort vermuten, dass das hier passiert:

Ganz richtig! Ihr würdt einen animierten Fortschrittsbalken erhalten. Kein JavaScript, keine CSS-Animation, nur ein <progress> Element ohne Wert. Und um es noch toller zu machen, könnt ihr es mit einigen zusätzlichen Attributen zu einer barrierefreien Fortschrittsanzeige für einen anderen Bereich der Website machen. Hier ist ein Beispiel aus der Dokumentationsseite:

<div aria-busy="true" aria-describedby="progress-bar">
  <!-- content is for this region is loading -->
</div>

<!-- ... -->

<progress id="progress-bar" aria-label="Content loading…"></progress>

Wenn ihr in einem WordPress-Projekt seid, können ihr auch die ProgressBar-Komponente verwenden. Im WordPress-Core scheint sie nur für einen Fortschrittsbalken mit „Ladeanimation“, wie oben gezeigt, verwendet zu werden. Sie verwendet zwar ebenfalls das <progress> Element, aber auch hier wird die Standarddarstellung des Browsers durch benutzerdefiniertes HTML-Markup ersetzt, damit sie in allen Browsern das gleiche Design hat.

Fazit

Ein Fortschrittsbalken kann die UX einer Webanwendung wirklich verbessern. Wenn ihr einen braucht, sollten ihr euch für das native Element entscheiden. Ihr könnt es auch ein wenig stylen. Mehr dazu finden ihr auf den verlinkten Dokumentationsseiten. Wenn ihr ein <progress> Element hinzufügen, achten bitte darauf, dass es auch ein Label bekommt. Das hilft nicht nur Nutzern mit assistiven Technologien. Die Angabe, wofür der Fortschritt steht, hilft allen das Element besser zu verstehen.

Verschachteltes CSS ohne Präprozessoren

Ich weiß nicht, wann ich angefangen habe, Sass zu verwenden. Mein erster Blogbeitrag zu diesem Thema stammt aus dem Jahr 2012. Es gibt viele Funktionen, für die ich an Sass liebe und eine von ihnen ist die Verschachtelung von Regeln.

Was ist Verschachtelung in Sass?

Ein typisches Beispiel dafür, wann Verschachtelung wirklich nützlich sind, ist der Umgang mit CSS-Selektoren von Elementen, die in der Regel Kinder von anderen Elementen sind. Ungeordnete Listen, die für Navigationsmenüs verwendet werden, sind hier ein gutes Beispiel:

nav {
	ul {
		list-style: none;

		ul {
			display: block;
		}
	}

	li {
		display: inline-block;
	}

	a {
		display: block;
		padding: 5px 10px;
	}
}

In diesem Code haben wir einige Kind- (oder Enkel-) Knoten eines <nav> Tags. Wenn wir nun einen Präprozessor wie Sass verwenden, erhalten wir für diese Verschachtelung das folgende Ergebnis im kompilierten CSS:

nav ul {
  list-style: none;
}
nav ul ul {
  display: block;
}
nav li {
  display: inline-block;
}
nav a {
  display: block;
  padding: 5px 10px;
}

Viele von euch werden wahrscheinlich zustimmen, dass der Sass-Code einfacher zu schreiben und zu ändern ist, da wir nicht den gesamten CSS-Selektor schreiben müssen. Das Umstellen der Verschachtelung ist wirklich einfach, verglichen mit dem Ersetzen der mittleren Teile von langen CSS-Selektoren. Die Selektoren, die ich oben ausgewählt habe, sind recht kurz. Das ist Absicht, denn ihr solltet nicht zu viel verschachteln, nur weil ihr es könnt, oder noch schlimmer, weil es euer HTML abbildet. Wahrscheinlich brauchen wir keinen CSS-Selektor wie „nav ul li a„, denn wenn wir nur jeden Link in der Navigation stylen wollen, reicht es aus etwas wie „nav a“ zu haben.

Wie kann man Verschachtelungen ohne Präprozessor verwenden?

Wenn wir versuchen, diesen schön verschachtelten Code in einer .css-Datei zu verwenden, könnte es einfach funktionieren. Ganz ohne einen Präprozessor zu verwenden. Viele aktuelle Browser unterstützen die oben gezeigt Syntax.

Wenn ihr aber noch einen Browser unterstützen müsst, der diese neue Spezifikation nicht implementiert hat und diese Syntax nicht versteht, dann müsst ihr den Code etwas abändern. Bei diesen Browsern müsst ihr nur ein & vor jedem verschachtelten Selektor hinzufügen. Der obige Code sieht dann folgendermaßen aus:

nav {
	& ul {
		list-style: none;

		& ul {
			display: block;
		}
	}

	& li {
		display: inline-block;
	}

	& a {
		display: block;
		padding: 5px 10px;
	}
}

Glücklicherweise haben alle großen Browser diese neue Spezifikation implementiert, bei der ihr das & nicht vor den verschachtelten Selektoren hinzufügen müssen. Sie unterstützen aber auch die alte Syntax. Wenn ihr also auf Nummer sicher gehen wollt, können ihr noch für einige Zeit die alte Syntax verwenden. Ich kann auch sehr empfehlen, in der Dokumentation ein wenig mehr über CSS-Verschachtelungen nachzulesen.

Fazit

Das war’s! Verwenden einfach Verschachtelungen wie in Sass, Less und anderen Präprozessoren und moderne Browser werden euren Code problemlos verstehen. Wenn ihr noch zusätzlich einen Präprozessor für andere Dinge wie Variablen verwenden, wird dieser diese Syntax trotzdem in die normalen „langen CSS-Selektoren“ kompilieren.

Mit den CSS Custom Properties (Variablen) und der Verschachtelung sind nun zwei von drei Funktionen nativ in CSS enthalten, die ich in Sass häufig verwende. Die letzte ist das „Templating“ mit mehreren Dateien für verschiedene Teile/Komponenten. Der Rest wie Mixins sind mehr „nice to have“ für mich, aber nicht wirklich wichtig.

Dynamische Parameter in JavaScript

Viele Programmiersprachen verfügen über diese Möglichkeit. Anstatt alle Parameter für eine Funktion zu definieren, können ihr eine beliebige Anzahl von Parametern an eine Funktion übergeben und dann mit ihnen arbeiten.

Funktionen mit statischen Parametern

Bevor wir uns mit dynamischen Parametern beschäftigen, führen wir erst einmal eine Funktion ein, mit der wir dann anschließend arbeiten können. Wie wäre es mit einer, die zwei Zahlen addiert?

function sum( a, b ) {
    return a + b;
}
 
console.log( sum( 4, 5 ) ); // 9

Nichts Besonderes hier, oder? Aber was würde passieren, wenn wir dem Funktionsaufruf einfach weitere Parameter hinzufügen?

console.log( sum( 4, 5, 6 ) ); // 9

Es würde nichts passieren, da die Funktion nur die ersten beiden Parameter verwendet. Wir erhalten aber auch keine Fehlermeldung. JavaScript verwendet den dritten Parameter einfach nicht.

Das arguments Objekt

Auch wenn wir den dritten Parameter nicht verwenden, ist er immer noch verfügbar. Aber wie können wir ihn verwenden, wenn wir keinen Parameternamen für ihn haben? Wir können das arguments Objekt verwenden, um alle Parameter zu erhalten, selbst dann, wenn wir überhaupt keine Parameter definiert haben:

function sum() {
  let total = 0;
  for (const number of arguments) {
    total += number;
  }
  return total;
}
 
console.log( sum( 4, 5 ) ); // 9
console.log( sum( 4, 5, 6 ) ); // 15

Das arguments Objekt funktioniert ähnlich wie ein Array. Ihr können mit arguments[0] auf den ersten Parameter zugreifen usw. In unserer Funktion sum() haben wir überhaupt keine Argumente, wie zuvor erwähnt. Aber man kann auch definierte Parameter mit zusätzlichen kombinieren:

function someFunction( a, b ) {
    console.log( a ); // 4
    console.log( b ); // 5
    console.log( arguments ); // [4, 5, 'a string', Array(2), ...]
}
 
someFunction( 4, 5, 'a string', [ 'an', 'array' ] );

Das arguments-Objekt enthält immer alle Parameter, die an die Funktion übergeben werden, auch solche mit einem Namen. Das Objekt hat noch einige andere Eigenschaften, über die ihr in der Dokumentation mehr erfahren könnt.

Der Rest-Parameter

Eine modernere Art, dynamische Parameter in JavaScript zu verwenden, ist der Rest -Parameter. Lasst uns wieder mit einem einfachen Beispiel beginnen. Wir implementieren unsere Funktion sum() und verwenden dieses Mal den Rest-Parameter:

function sum( ...numbers ) {
    let total = 0;
    for ( const number of numbers ) {
        total += number;
    }
    return total;
}
 
console.log( sum( 4, 5 ) ); // 9
console.log( sum( 4, 5, 6 ) ); // 15

Der einzige Parameter ist hier „...numbers“ und das ist der „Rest-Parameter“. Ein weiteres gutes Beispiel ist dieses:

function calc( operation, ...numbers ) {
    switch ( operation ) {
        case "sum":
            return numbers.reduce( ( total, num ) => total + num, 0 );
        case "multiply":
            return numbers.reduce( ( product, num ) => product * num, 1 );
        case "subtract":
            return numbers.reduce( ( difference, num ) => difference - num );
        case "divide":
            return numbers.reduce( ( quotient, num ) => quotient / num );
        default:
            console.error(`Invalid operation "${operation}"`);
            return;
    }
}
 
console.log( calc( "sum", 4, 5, 6 ) ); // 15
console.log( calc( "multiply", 4, 5, 6  ) ); // 120

Jetzt macht der „Rest“ Sinn, oder? Wir haben einige normale Parameter, gefolgt vom Rest-Parameter, der alle anderen Parameter enthält, eben einfach ausgedrückt, den „Rest“ der Parameter. Es kann immer nur einen Rest-Parameter geben, und dieser muss der letzte Parameter sein. Dieses Beispiel zeigt auch einen guten Anwendungsfall für die Funktion console.error() aus unserem letzten Blogbeitrag.

Bonus: das arguments Objekt verwendet als Rest-Parameter

In unserem ersten Beispiel für den Rest-Parameter bräuchten wir nicht einmal den Parameter ...numbers, da er der einzige Parameter ist. Wir hätten einfach das arguments Objekt in Kombination mit dem Spread-Operator wie folgt verwenden können:

function sum() {
  let total = 0;
  const numbers = [...arguments]; // Convert arguments object to a real array
  for (const number of numbers) {
    total += number;
  }
  return total;
}

Diese Umwandlung in Zeile 3 ist eigentlich nicht notwendig, da sich das arguments Objekt sehr ähnlich zu einem Array verhält, aber man kann es trotzdem tun, je nach eigenem Anwendungsfall dafür. Sobald ihr aber mehr (benannte) Parameter habt, würde das wahrscheinlich nicht mehr funktionieren.

Fazit

Eine Funktion mit einer festen Anzahl von Argumenten kann zu unflexibel sein, vor allem, wenn man mit Arrays oder Listen arbeitet. In diesen Fällen kann der Rest-Parameter oder das arguments Objekt helfen, einige schöne und kurze Funktionen zu schreiben.

Fortgeschrittenes JavaScript-Debugging

Im ersten Blogbeitrag des Adventskalenders in diesem Jahr habe ich euch „Erste Schritte beim JavaScript-Debugging“ gezeigt. Heute möchte ich einige fortgeschrittene Techniken vorstellen, die ihr zum Debuggen eures Codes verwenden können.

Verschiedene Logging-Typen

Im ersten Blogbeitrag haben wir nur console.log() verwendet, aber es gibt noch weitere Funktionen des console Objekts, die ihr verwenden könnt:

console.debug('debug message');
console.info('info message');
console.log('log message');
console.error('error message');
console.warn('warn message');

Und so würden sie in der Chrome-Konsole aussehen:

The Chrome Console with the output of the four debugging methods info, log, error and warning.

Die Methoden info und log erzeugen eine ähnliche Ausgabe. Die error und warn Methoden sind jedoch auffälliger gestaltet. Einige von euch haben vielleicht bemerkt, dass wir hier nur 4 Zeilen sehen. Wo ist die Ausgabe für das debug Logging? Diese wird möglicherweise (standardmäßig) in eurem Browser nicht angezeigt. In Chrome müsst ihr auf das Dropdown-Menü „Default levels“ klicken. Hier könnt ihr dann auch „Verbose“ aktivieren, um die debug Nachrichten zu sehen:

The Chrome Console with the output of debug method as well, after activating the "Verbose" debug level.

Da die debug Ausgabe (in Chrome) ebenfalls ähnlich ist, brauchen ihr sie vielleicht nicht wirklich. Ich würde wahrscheinlich hauptsächlich log, warn und error verwenden.

Verwendung von Format-Strings und Styling in Debugging-Ausgaben

Die Debugging-Funktion akzeptiert mehr als einen Parameter. Wenn ihr einfach mehrere Strings, Zahlen, Objekte usw. übergebt, wird jede dieser Parameter in einer Zeile, durch Leerzeichen getrennt (für skalare Typen) oder untereinander (für Objekte) ausgegeben. Ihr können aber auch zusätzliche Parameter für Format-Strings und sogar für die Styling-Angaben verwenden.

Beginnen wir mit einem Format-Strings. Ein Beispiel mit einem einzelnen %s Platzhalter für einen String könnte so aussehen:

const code = 'Code';
console.log('%s is Poetry.', code);

Die Ausgabe wäre Code is Poetry, wie wir es erwarten würden. Neben dem üblichen Format-String-Platzhalter könnt ihr aber auch den %c Platzhalter verwenden. Der nächste Parameter wäre ein CSS-String, mit dem der darauf folgende Text gestylt werden würde. Einfach so:

console.log(
	'This is %csome green text, followed by %csome red and italic text.',
	'color: green;',
	'color: red; font-style: italic;',
);

Wenn ihr mehrere %c Platzhalter habt, wechseln die Styles zum nächsten Parameter und gestalten jeden dann folgenden Text mit diesen neuen Styles. Die Ausgabe des obigen Codes sieht wie folgt aus:

Sie können die %c-Platzhalter auch mit jedem anderen üblichen Platzhalter kombinieren. Probiert es doch einfach mal in eurer aktuellen Browser-Konsole aus. Aber ihr dürft nicht zu verrückt werden. Es gibt nur ein paar CSS-Eigenschaften und -Werte, die ihr in Firefox und Chrome verwenden könnt.

Weitere nützliche Debugging-Funktionen für die Konsole

Wenn ihr viele Meldungen protokollieren möchtet, dann können ihr sie gruppieren. Ihr fangt eine neue Gruppe an, indem ihr die Funktion console.group() verwendet (mit einem optionalen Label) und schließt die Gruppe mit console.groupEnd(). Ihr können sogar Gruppen in Gruppen verschachteln und somit eine Art „Baumstruktur“ erstellen.

Es gibt noch einige andere Instanzmethoden, die für eure Debugging-Aufgaben nützlich sein können, aber eine davon ist wirklich cool!

Zeitmessung in der Konsole

Das console Objekt verfügt über einige Zeitmessfunktionen, die ihr für einfache Performanceanalyse verwenden könnt. Hier ist ein Beispiel, das die Funktion console.time() verwendet:

console.time("a timer label");
slowFunction(1000);
console.timeEnd("a timer label");

function slowFunction(milliseconds) {
	const start = Date.now();
	while (Date.now() - start < milliseconds) {
		// Simulating a long-running function
	}
}

Die Funktion „wartet eine Sekunde lang“ innerhalb der while-Schleife. Die Ausgabe in Chrome sieht wie folgt aus:

a timer label: 999.2578125 ms

Mit dem optionalen „label“ als erstem Parameter können ihr mehrere Timer laufen lassen. Wenn ihr die Zeiten dazwischen messen möchten, können ihr console.timeLog() (mit dem optional passenden Label) verwenden, um „Zwischenzeiten“ zu protokollieren.

Fazit

Beim Entwickeln oder Analysieren von Code kann es sehr hilfreich sein, Dinge in der Browser-Konsole zu protokollieren. Wenn ihr bisher nur console.log() verwendet habt, machen euch mal mit den anderen nützlichen Methoden vertraut.

Ihr solltet aber natürlich immer darauf achten, diese Debugging-Methoden zu entfernen, bevor ihr euren Code fertigstellt. Einige JavaScript-Compiler machen das sogar automatisch, wenn ihr diese für „Production“ bauen lasst.

Das native HTML-Range-Input-Element

Viele von uns haben ihn schon gesehen und verwendet. Im WordPress-Block-Editor ist er für Dinge wie die Schriftgröße verschiedener Blöcke verfügbar. So sieht es z.B. sie für den core/paragraph Block aus:

Die „Typografie“-Einstellungen für die Schriftgröße eines Absatzblocks, mit einer Zahleneingabe auf der linken Seite und einer Bereichseingabe auf der rechten Seite, mit dem numerischen Wert in einem Tooltip darunter.

Wenn ihr den Input verwendet, wird der aktuelle Wert unter dem „Anfasser“ angezeigt und auch im Zahlenfeld links davon aktualisiert.

Optionen für den Input

Die beiden wichtigsten Attribute für diesen Eingabetyp sind wahrscheinlich die Attribute min und max. Hier also ein einfaches Beispiel:

<input type="range" id="font-size" name="font-size" min="16" max="96" />
<label for="font-size">font size</label>

Vergesst wie immer nicht, ein <label> für eure Eingabefelder zu verwenden. Wenn ihr min nicht festlegen, ist der Standardwert 0 und für max ist er 100.

Ein weiteres Attribut, das ihr vielleicht verwenden möchten, ist step. Das kann ein Dezimal- oder Gleitkommawert sein, wie in diesem Beispiel:

<input type="range" id="font-size" name="font-size" min="16" max="96" step="4" />
<label for="font-size">font size</label>
<input type="range" id=">line-height" name="line-height" min="0" max="10" step="0.1" />
<label for="line-height">line height</label>

Aus irgendeinem Grund verwendet WordPress keinen Range-Input, sondern nur ein Zahlenfeld. Aber auch hier wird eine Schrittweite von „0,1“ verwendet.

Auf der Dokumentationsseite finden ihr auch ein ziemlich verrücktes Beispiel für das step Attribut und das sieht so aus:

<input id="pi_input" type="range" min="0" max="3.14" step="any" />

Wenn ihr den Wert „any“ verwendet, nimmt das Input wirklich „jeden beliebigen Fließkommawert“ zwischen min und max an. Interessanterweise erhaltet ihr 100 diskrete Werte, wenn ihr mit der Tastatur zum Feld navigiert und dann mit den Cursortasten links/rechts den Anfasser bewegt. Wenn ihr aber die Maus verwendet, dann erhalten ihr wirklich zufällige und wilde Zahlen dazwischen.

Verwendung des list Attributs

Im letzten Blogbeitrag zum Thema HTML haben wir bereits das list Attribut kennengelernt und auch das Range-Input unterstützt es. Einige normale und kreative Beispiele finden ihr in der Dokumentation. In Chrome lässt die Verwendung eines list Attributs den Anfasser an den <option> Werten der <datalist> „einrasten“. Ihr könnt aber auch einen Wert dazwischen einstellen. Meiner Meinung nach kann man das list Attribute am besten mit step kombinieren. In diesem Fall sind dann nur die Auswahl von Optionen in der <datalist> erlaubt:

<label for="temp">Choose a comfortable temperature:</label><br />
<input type="range" id="temp" name="temp" list="markers" step="25" />

<datalist id="markers">
  <option value="0"></option>
  <option value="25"></option>
  <option value="50"></option>
  <option value="75"></option>
  <option value="100"></option>
</datalist>

Dieser Codeschnipsel zeigt einen Range-Input ohne min/max Werte, aber mit einem zusätzlichen step="25" Attribut. Schauen euch dazu auch das Beispiel mit den Labels an.

Styling des Inputs

Das Styling würde je nach Browser oder Betriebssystem sehr unterschiedlich aussehen. Auch wenn WordPress einen solchen Input verwendet, ist das, was ihr seht, nicht das Input selbst. Es wird „transparent“ stattdessen gemacht und liegt über einem benutzerdefinierten HTML-Element, das mehrere <span> Elemente verwendet, um ein UI-Element zu schaffen, das in allen Browsern gleich aussieht. Wenn ihr genau dieses Element haben möchten, könnt ihr die RangeControl Komponente in eurem JavaScript-Code verwenden.

Aber auch wenn ihr das Range-Input nicht exakt gleich gestalten könnt, gibt es doch einige Optionen, wie etwa für das Ändern der Farbe des Balkens und des Anfassers:

input[type='range'] {
  height: 30px;
}
input[type='range'],
input[type='range']::-webkit-slider-runnable-track,
input[type='range']::-webkit-slider-thumb {
  -webkit-appearance: none;
}
input[type='range']::-webkit-slider-runnable-track {
  height: 10px;
  background: red;
}
input[type='range']::-webkit-slider-thumb {
  position: relative;
  height: 30px;
  width: 30px;
  margin-top: -10px;
  background: green;
  border-radius: 50%;
}

Dies ist nur ein Beispiel für Chrome/Webkit. Es ist wichtig, viele Dinge auf appearance: none zu setzen, da sonst die anderen Styling-Änderungen keine Wirkung haben würden. Diese Stile würden zu dieser Darstellung führen:

A label "Choose a comfortable temperature" with a range input below it. The input has a red background color (the range bar) and a green "thumb" (a circle to change the value).

Ihr wisst alle, dass ich kein Designer bin, aber ich hoffe, dass dies das Styling ein wenig illustriert. Wenn ihr wirklich kreativ werden wollt, schauen euch sich die Blogbeiträge von CSS-Tricks, Smashing Magazine oder W3Schools an.

Fazit

Range-Inputs können die UX einer Online-Anwendung wirklich verbessern, da Zahleneingaben in manchen Fällen nicht so „responsive“ sind. Und wenn ihr nicht in die WordPress-JavaScript-Bibliotheken einsetzt, ist die Verwendung des nativen Range-Inputs vielleicht alles, was ihr braucht.