Ein grundlegender Überblick darüber, wie Sie eine responsive und barrierefreie Switch-Komponente erstellen.
In diesem Beitrag möchte ich darüber sprechen, wie Switch-Komponenten aufgebaut werden können. Demo ansehen.
Falls du lieber ein Video hast, findest du hier eine YouTube-Version dieses Beitrags:
Überblick
Ein Switch funktioniert ähnlich wie ein Kästchen, stellt aber explizit einen booleschen Ein- und Aus-Zustand dar.
In dieser Demo wird für den Großteil der Funktionalität <input type="checkbox" role="switch">
verwendet. Dies hat den Vorteil, dass CSS oder JavaScript nicht erforderlich ist, um voll funktionsfähig und zugänglich zu sein. Wenn Sie CSS laden, werden nun auch Sprachen mit rechtsläufiger Schrift, Vertikalität, Animationen und mehr unterstützt. Durch das Laden von JavaScript wird der Schalter
ziehbar und greifbar.
Benutzerdefinierte Eigenschaften
Die folgenden Variablen stellen die verschiedenen Teile des Switches und ihre Optionen dar. Als übergeordnete Klasse enthält .gui-switch
benutzerdefinierte Eigenschaften, die in den untergeordneten Komponenten verwendet werden, sowie Einstiegspunkte für die zentralisierte Anpassung.
Verfolgen
Länge (--track-size
), Abstand und zwei Farben:
.gui-switch {
--track-size: calc(var(--thumb-size) * 2);
--track-padding: 2px;
--track-inactive: hsl(80 0% 80%);
--track-active: hsl(80 60% 45%);
--track-color-inactive: var(--track-inactive);
--track-color-active: var(--track-active);
@media (prefers-color-scheme: dark) {
--track-inactive: hsl(80 0% 35%);
--track-active: hsl(80 60% 60%);
}
}
Daumenschlag
Größe, Hintergrundfarbe und Interaktionsfarben:
.gui-switch {
--thumb-size: 2rem;
--thumb: hsl(0 0% 100%);
--thumb-highlight: hsl(0 0% 0% / 25%);
--thumb-color: var(--thumb);
--thumb-color-highlight: var(--thumb-highlight);
@media (prefers-color-scheme: dark) {
--thumb: hsl(0 0% 5%);
--thumb-highlight: hsl(0 0% 100% / 25%);
}
}
Reduzierte Bewegung
Um einen eindeutigen Alias hinzuzufügen und Wiederholungen zu reduzieren, kann eine Nutzermedienabfrage mit reduzierter Bewegungseinstellung mithilfe des PostCSS-Plug-ins in eine benutzerdefinierte Eigenschaft eingefügt werden, die auf dieser Spezifikationsentwurf in Medienabfragen 5 basiert:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
Markup
Ich habe mich dafür entschieden, mein <input type="checkbox" role="switch">
-Element mit einem <label>
zu umschließen und die Beziehung zu bündeln, um Mehrdeutigkeiten bei Kästchen- und Labelverknüpfungen zu vermeiden und dem Nutzer gleichzeitig die Möglichkeit zu geben, mit dem Label zu interagieren, um die Eingabe umzuschalten.
<label for="switch" class="gui-switch">
Label text
<input type="checkbox" role="switch" id="switch">
</label>
<input type="checkbox">
enthält eine API und einen state. Der Browser verwaltet das Attribut checked
und die Eingabeereignisse wie oninput
und onchanged
.
Layouts
Flexbox-, grid- und benutzerdefinierte Eigenschaften sind entscheidend für die Verwaltung der Stile dieser Komponente. Sie zentralisieren Werte, geben ansonsten mehrdeutigen Berechnungen oder Bereichen Namen und ermöglichen eine kleine API für benutzerdefinierte Eigenschaften für eine einfache Anpassung von Komponenten.
.gui-switch
Das Layout der obersten Ebene für den Schalter ist die Flexbox. Die Klasse .gui-switch
enthält die privaten und öffentlichen benutzerdefinierten Attribute, die die untergeordneten Elemente zum Berechnen ihrer Layouts verwenden.
.gui-switch {
display: flex;
align-items: center;
gap: 2ch;
justify-content: space-between;
}
Das Erweitern und Ändern des Flexbox-Layouts ist wie das Ändern eines Flexbox-Layouts.
So platzieren Sie beispielsweise Labels ober- oder unterhalb eines Switches oder ändern flex-direction
:
<label for="light-switch" class="gui-switch" style="flex-direction: column">
Default
<input type="checkbox" role="switch" id="light-switch">
</label>
Verfolgen
Die Kästcheneingabe wird als Schalterspur formatiert. Dabei wird das normale appearance: checkbox
entfernt und stattdessen seine eigene Größe angegeben:
.gui-switch > input {
appearance: none;
inline-size: var(--track-size);
block-size: var(--thumb-size);
padding: var(--track-padding);
flex-shrink: 0;
display: grid;
align-items: center;
grid: [track] 1fr / [track] 1fr;
}
Der Spur erstellt außerdem einen Rasterspurbereich mit einer einzelnen Zelle, den Sie per Daumen beanspruchen können.
Daumenschlag
Mit dem Stil appearance: none
wird auch das vom Browser bereitgestellte visuelle Häkchen entfernt. Diese Komponente verwendet ein Pseudoelement und die Pseudoklasse :checked
für die Eingabe, um diesen visuellen Indikator zu ersetzen.
Der Daumen ist ein untergeordnetes Pseudoelement, das an input[type="checkbox"]
angehängt ist. Es wird über dem Track gestapelt und nicht darunter, indem er den Rasterbereich track
beansprucht:
.gui-switch > input::before {
content: "";
grid-area: track;
inline-size: var(--thumb-size);
block-size: var(--thumb-size);
}
Stile
Benutzerdefinierte Eigenschaften ermöglichen eine vielseitige Schalterkomponente, die sich an Farbschemata, linksläufige Sprachen und Bewegungseinstellungen anpasst.
Touch-Interaktionsstile
Auf Mobilgeräten fügen Browser den Labels und Eingaben Funktionen zum Hervorheben von Berührungen und Textauswahl hinzu. Dies wirkten sich negativ auf das Feedback zu Stil und visuellen Interaktionen aus, das für diesen Wechsel erforderlich war. Mit ein paar CSS-Zeilen kann ich diese Effekte entfernen und meinen eigenen cursor: pointer
-Stil hinzufügen:
.gui-switch {
cursor: pointer;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
Es ist nicht immer ratsam, diese Stile zu entfernen, da sie wertvolles visuelles Interaktionsfeedback sein können. Achten Sie darauf, benutzerdefinierte Alternativen anzugeben, wenn Sie sie entfernen.
Verfolgen
Bei den Stilen dieses Elements geht es hauptsächlich um Form und Farbe, auf die es über die Kaskade vom übergeordneten .gui-switch
aus zugreift.
.gui-switch > input {
appearance: none;
border: none;
outline-offset: 5px;
box-sizing: content-box;
padding: var(--track-padding);
background: var(--track-color-inactive);
inline-size: var(--track-size);
block-size: var(--thumb-size);
border-radius: var(--track-size);
}
Aus vier benutzerdefinierten Eigenschaften stammen zahlreiche Anpassungsoptionen für die Schaltschiene. border: none
wird hinzugefügt, da appearance: none
die Rahmen nicht in allen Browsern aus dem Kästchen entfernt.
Daumenschlag
Das Daumenelement befindet sich bereits auf der rechten track
, erfordert aber Kreisstile:
.gui-switch > input::before {
background: var(--thumb-color);
border-radius: 50%;
}
Interaktion
Mit benutzerdefinierten Eigenschaften können Sie sich auf Interaktionen vorbereiten, bei denen sich Hervorhebungen und Änderungen der Daumenposition ändern. Die Präferenz des Nutzers wird außerdem überprüft, bevor die Stile für Bewegungs- oder Hover-Hervorhebungen umgestellt werden.
.gui-switch > input::before {
box-shadow: 0 0 0 var(--highlight-size) var(--thumb-color-highlight);
@media (--motionOK) { & {
transition:
transform var(--thumb-transition-duration) ease,
box-shadow .25s ease;
}}
}
Daumenposition
Benutzerdefinierte Eigenschaften bieten einen einzigen Quellmechanismus für die Positionierung des Daumens im Track. Wir haben Spur- und Daumengrößen zur Verfügung, die wir in Berechnungen verwenden, um für einen ausreichenden Abstand zwischen den Tracks innerhalb der Spur zu sorgen: 0%
und 100%
.
Das input
-Element besitzt die Positionsvariable --thumb-position
und das Thumbnail-Element verwendet diese als translateX
-Position:
.gui-switch > input {
--thumb-position: 0%;
}
.gui-switch > input::before {
transform: translateX(var(--thumb-position));
}
Wir können --thumb-position
jetzt kostenlos von CSS und den Pseudoklassen für Kästchenelemente ändern. Da wir transition: transform
var(--thumb-transition-duration) ease
zuvor für dieses Element bedingt festgelegt haben, können diese Änderungen animiert werden, wenn sie geändert werden:
/* positioned at the end of the track: track length - 100% (thumb width) */
.gui-switch > input:checked {
--thumb-position: calc(var(--track-size) - 100%);
}
/* positioned in the center of the track: half the track - half the thumb */
.gui-switch > input:indeterminate {
--thumb-position: calc(
(var(--track-size) / 2) - (var(--thumb-size) / 2)
);
}
Ich dachte, diese entkoppelte Orchestrierung hat gut funktioniert. Das Daumenelement betrifft nur einen Stil, die translateX
-Position. Die Eingabe kann die Komplexität
und die Berechnungen verwalten.
Vertikal
Unterstützt wurde die Modifikatorklasse -vertical
, die dem input
-Element eine Rotation mit CSS-Transformationen hinzufügt.
Ein in 3D gedrehtes Element ändert jedoch nicht die Gesamthöhe der Komponente, was das Blocklayout beeinträchtigen kann. Berücksichtigen Sie dies mit den Variablen --track-size
und --track-padding
. Berechnen Sie den erforderlichen Mindestabstand, damit eine vertikale Schaltfläche wie erwartet im Layout fließt:
.gui-switch.-vertical {
min-block-size: calc(var(--track-size) + calc(var(--track-padding) * 2));
& > input {
transform: rotate(-90deg);
}
}
(RTL) von rechts nach links
Ein CSS-Freund, Elad Schecter, und ich haben zusammen ein ausblendbares seitliches Menü mit CSS-Transformationen entwickelt, mit denen durch Umdrehen einer einzelnen Variablen Sprachen von rechts nach links verarbeitet werden. Zu diesem Zweck gibt es in CSS keine logischen Eigenschaftstransformationen. Elad hatte die Idee, einen benutzerdefinierten Eigenschaftswert zu verwenden, um Prozentsätze umzukehren, um die Verwaltung eines einzigen Standorts unserer eigenen benutzerdefinierten Logik für logische Transformationen zu ermöglichen. Ich habe dieselbe Technik beim Wechsel verwendet und denke, es hat super funktioniert:
.gui-switch {
--isLTR: 1;
&:dir(rtl) {
--isLTR: -1;
}
}
Eine benutzerdefinierte Eigenschaft namens --isLTR
enthält anfänglich den Wert 1
, d. h. true
, da unser Layout standardmäßig von links nach rechts verwendet wird. Dann wird mithilfe der CSS-Pseudoklasse :dir()
der Wert auf -1
gesetzt, wenn sich die Komponente in einem linksläufigen Layout befindet.
Setzen Sie --isLTR
in Aktion, indem Sie es innerhalb einer calc()
innerhalb einer Transformation verwenden:
.gui-switch.-vertical > input {
transform: rotate(-90deg);
transform: rotate(calc(90deg * var(--isLTR) * -1));
}
Jetzt berücksichtigt die Drehung des vertikalen Schalters die Position gegenüberliegender Seite, die für das Layout von rechts nach links erforderlich ist.
Die translateX
-Transformationen auf dem Thumbnail-Element müssen ebenfalls aktualisiert werden, um die Anforderung der gegenüberliegenden Seite zu berücksichtigen:
.gui-switch > input:checked {
--thumb-position: calc(var(--track-size) - 100%);
--thumb-position: calc((var(--track-size) - 100%) * var(--isLTR));
}
.gui-switch > input:indeterminate {
--thumb-position: calc(
(var(--track-size) / 2) - (var(--thumb-size) / 2)
);
--thumb-position: calc(
((var(--track-size) / 2) - (var(--thumb-size) / 2))
* var(--isLTR)
);
}
Dieser Ansatz eignet sich zwar nicht für alle Anforderungen an ein Konzept wie logische CSS-Transformationen, bietet aber einige DRY-Prinzipien für viele Anwendungsfälle.
Bundesstaaten
Die Verwendung des integrierten input[type="checkbox"]
wäre nicht vollständig, ohne die verschiedenen Status zu verarbeiten, in denen es sich befinden kann: :checked
, :disabled
, :indeterminate
und :hover
. :focus
wurde absichtlich unverändert gelassen und nur an seinem Versatz angepasst. Der Fokusring sah in Firefox und Safari toll aus:
Geprüft
<label for="switch-checked" class="gui-switch">
Default
<input type="checkbox" role="switch" id="switch-checked" checked="true">
</label>
Dieser Status stellt den Status on
dar. In diesem Status wird für den Eingabehintergrund die aktive Farbe und für die Daumenposition „das Ende“ festgelegt.
.gui-switch > input:checked {
background: var(--track-color-active);
--thumb-position: calc((var(--track-size) - 100%) * var(--isLTR));
}
Deaktiviert
<label for="switch-disabled" class="gui-switch">
Default
<input type="checkbox" role="switch" id="switch-disabled" disabled="true">
</label>
Eine :disabled
-Schaltfläche sieht nicht nur optisch anders aus, sondern sollte auch dafür sorgen, dass das Element unveränderlich wird. Die Unveränderlichkeit der Interaktion ist vom Browser nicht möglich. Für den visuellen Status sind jedoch aufgrund der Verwendung von appearance: none
Stile erforderlich.
.gui-switch > input:disabled {
cursor: not-allowed;
--thumb-color: transparent;
&::before {
cursor: not-allowed;
box-shadow: inset 0 0 0 2px hsl(0 0% 100% / 50%);
@media (prefers-color-scheme: dark) { & {
box-shadow: inset 0 0 0 2px hsl(0 0% 0% / 50%);
}}
}
}
Dieser Status ist schwierig, da er dunkles und helles Design mit deaktiviertem und aktiviertem Status benötigt. Für diese Stadien habe ich stilistisch minimale Stile gewählt, um die Verwaltung von Stilkombinationen zu vereinfachen.
Unklar
Ein häufig vergessener Status ist :indeterminate
, bei dem ein Kästchen weder aktiviert noch deaktiviert ist. Dieser Zustand ist unterhaltsam, einladend und unscheinbar. Denken Sie daran, dass boolesche Status heimlich zwischen Bundesstaaten erscheinen können.
Es ist schwierig, ein unbestimmtes Kontrollkästchen zu setzen, es kann nur von JavaScript gesetzt werden:
<label for="switch-indeterminate" class="gui-switch">
Indeterminate
<input type="checkbox" role="switch" id="switch-indeterminate">
<script>document.getElementById('switch-indeterminate').indeterminate = true</script>
</label>
Da der Bundesstaat für mich einfach und einladend ist, erschien es mir angebracht, die Position des Schaltknaufs in der Mitte zu platzieren:
.gui-switch > input:indeterminate {
--thumb-position: calc(
calc(calc(var(--track-size) / 2) - calc(var(--thumb-size) / 2))
* var(--isLTR)
);
}
Mauszeiger bewegen
Hover-Interaktionen sollten die verbundene UI visuell unterstützen und auch eine Richtung zur interaktiven UI vorgeben. Bei diesem Schalter wird der Daumen mit einem halbtransparenten Ring hervorgehoben, wenn der Mauszeiger auf Label oder Eingabe bewegt wird. Diese Hover-Animation zeigt dann die Richtung des interaktiven Daumenelements an.
Der „Hervorhebungseffekt“ wird mit box-shadow
ausgeführt. Wenn Sie den Mauszeiger auf eine nicht deaktivierte Eingabe bewegen, wird die Größe von --highlight-size
erhöht. Wenn der Nutzer mit Bewegungen einverstanden ist, übertragen wir box-shadow
und sehen, wie er größer wird. Wenn Bewegungen mit Bewegungen nicht einverstanden sind, wird die Hervorhebung sofort angezeigt:
.gui-switch > input::before {
box-shadow: 0 0 0 var(--highlight-size) var(--thumb-color-highlight);
@media (--motionOK) { & {
transition:
transform var(--thumb-transition-duration) ease,
box-shadow .25s ease;
}}
}
.gui-switch > input:not(:disabled):hover::before {
--highlight-size: .5rem;
}
JavaScript
Ich finde, eine Switch-Oberfläche kann einen etwas ungemütlichen Versuch anfühlen, eine physische Schnittstelle zu emulieren, insbesondere diese Art mit einem Kreis innerhalb einer Spur. iOS hat das mit dem Schalter richtig gemacht, man kann sie von einer Seite zur anderen ziehen und die Option ist sehr angenehm zu nutzen. Umgekehrt kann sich ein UI-Element als inaktiv anfühlen, wenn eine Ziehgeste versucht wird und nichts passiert.
Ziehbare Daumen
Das Pseudoelement „Daumen“ empfängt seine Position vom .gui-switch > input
-Bereich var(--thumb-position)
. JavaScript kann einen Wert für den Inline-Style in der Eingabe bereitstellen, um die Daumenposition dynamisch zu aktualisieren, sodass es so aussieht, als würde es der Zeigergeste folgen. Wenn der Mauszeiger freigegeben wird, entfernen Sie die Inline-Stile und stellen Sie mithilfe der benutzerdefinierten Eigenschaft --thumb-position
fest, ob der Ziehpunkt näher an der Position liegt. Dies ist das Herzstück der Lösung: Zeigerereignisse, die Zeigerpositionen bedingt verfolgen, um benutzerdefinierte CSS-Eigenschaften zu ändern.
Da die Komponente bereits zu 100% funktionsfähig war, bevor dieses Skript angezeigt wurde, ist es aufwendig, das bestehende Verhalten beizubehalten, z. B. das Anklicken eines Labels zum Umschalten der Eingabe. Unser JavaScript-Code sollte keine Funktionen auf Kosten vorhandener Funktionen hinzufügen.
touch-action
Das Ziehen ist eine benutzerdefinierte Geste, die besonders für touch-action
-Vorteile geeignet ist. In diesem Fall sollte unser Skript eine horizontale Geste ausführen oder eine vertikale Geste für die vertikale Schaltervariante. Mit touch-action
können wir dem Browser mitteilen, welche Gesten dieses Element verarbeiten soll, sodass ein Skript eine Geste ohne Konkurrenz verarbeiten kann.
Mit dem folgenden CSS wird der Browser angewiesen, vertikale Touch-Gesten, die innerhalb dieser Schalterspur beginnen, nicht mit horizontalen Gesten zu verarbeiten:
.gui-switch > input {
touch-action: pan-y;
}
Das gewünschte Ergebnis ist eine horizontale Geste, bei der die Seite nicht geschwenkt oder gescrollt wird. Mit einem Zeiger kann von der Eingabe aus ein vertikales Scrollen gestartet und die Seite gescrollt werden. Horizontale können jedoch angepasst werden.
Dienstprogramme im Pixel-Stil
Bei der Einrichtung und während des Ziehens müssen verschiedene berechnete Zahlenwerte von Elementen abgerufen werden. Die folgenden JavaScript-Funktionen geben bei einer CSS-Eigenschaft berechnete Pixelwerte zurück. Sie wird im Einrichtungsskript wie hier verwendet: getStyle(checkbox, 'padding-left')
.
const getStyle = (element, prop) => {
return parseInt(window.getComputedStyle(element).getPropertyValue(prop));
}
const getPseudoStyle = (element, prop) => {
return parseInt(window.getComputedStyle(element, ':before').getPropertyValue(prop));
}
export {
getStyle,
getPseudoStyle,
}
Beachten Sie, dass window.getComputedStyle()
ein zweites Argument akzeptiert, ein Pseudoelement. Sehr praktisch, dass JavaScript so viele Werte aus Elementen lesen kann, sogar aus Pseudoelementen.
dragging
Dies ist ein zentraler Moment für die Drag-Logik und es gibt einige Dinge aus dem Funktions-Event-Handler zu beachten:
const dragging = event => {
if (!state.activethumb) return
let {thumbsize, bounds, padding} = switches.get(state.activethumb.parentElement)
let directionality = getStyle(state.activethumb, '--isLTR')
let track = (directionality === -1)
? (state.activethumb.clientWidth * -1) + thumbsize + padding
: 0
let pos = Math.round(event.offsetX - thumbsize / 2)
if (pos < bounds.lower) pos = 0
if (pos > bounds.upper) pos = bounds.upper
state.activethumb.style.setProperty('--thumb-position', `${track + pos}px`)
}
Der Skript-Hero ist state.activethumb
, der kleine Kreis, den dieses Skript zusammen mit einem Mauszeiger positioniert. Das switches
-Objekt ist ein Map()
-Objekt, bei dem die Schlüssel .gui-switch
sind und die Werte im Cache gespeicherte Grenzen und Größen enthalten, damit das Skript effizient bleibt. Die Eingabe von rechts nach links wird mit derselben benutzerdefinierten Eigenschaft wie CSS --isLTR
verarbeitet. Damit kann Logik invertiert werden, sodass weiterhin RTL unterstützt wird. event.offsetX
ist ebenfalls hilfreich, da er einen Deltawert enthält, der für die Positionierung des Daumens nützlich ist.
state.activethumb.style.setProperty('--thumb-position', `${track + pos}px`)
In dieser letzten CSS-Zeile wird die benutzerdefinierte Eigenschaft festgelegt, die vom Element „thum“ verwendet wird. Ansonsten würde diese Wertzuweisung im Laufe der Zeit übergehen, aber durch ein früheres Zeigerereignis wurde --thumb-transition-duration
vorübergehend auf 0s
gesetzt, wodurch die bisher langsame Interaktion entfernt wurde.
dragEnd
Damit der Nutzer weit über den Schalter hinaus ziehen und ihn wieder loslassen kann, muss ein globales Fensterereignis registriert werden:
window.addEventListener('pointerup', event => {
if (!state.activethumb) return
dragEnd(event)
})
Ich denke, es ist sehr wichtig, dass der Nutzer die Freiheit hat, sich locker zu bewegen und die Benutzeroberfläche so intelligent zu gestalten, dass er dies berücksichtigt. Es war nicht viel für die Handhabung dieses Switches erforderlich, aber er musste während des Entwicklungsprozesses sorgfältig geprüft werden.
const dragEnd = event => {
if (!state.activethumb) return
state.activethumb.checked = determineChecked()
if (state.activethumb.indeterminate)
state.activethumb.indeterminate = false
state.activethumb.style.removeProperty('--thumb-transition-duration')
state.activethumb.style.removeProperty('--thumb-position')
state.activethumb.removeEventListener('pointermove', dragging)
state.activethumb = null
padRelease()
}
Die Interaktion mit dem Element ist abgeschlossen. Es wird Zeit, die aktivierte Eingabeeigenschaft festzulegen und alle Gestenereignisse zu entfernen. Das Kästchen wird mit state.activethumb.checked = determineChecked()
geändert.
determineChecked()
Diese von dragEnd
aufgerufene Funktion bestimmt, wo der Daumenstrom innerhalb der Grenzen des Tracks liegt, und gibt „true“ zurück, wenn er gleich oder über der Hälfte der Spur ist:
const determineChecked = () => {
let {bounds} = switches.get(state.activethumb.parentElement)
let curpos =
Math.abs(
parseInt(
state.activethumb.style.getPropertyValue('--thumb-position')))
if (!curpos) {
curpos = state.activethumb.checked
? bounds.lower
: bounds.upper
}
return curpos >= bounds.middle
}
Zusätzliche Gedanken
Bei der Drag-Geste war der Code etwas überschuldet, da die ursprüngliche HTML-Struktur ausgewählt wurde. Vor allem wurde die Eingabe in ein Label eingebunden. Da das Label ein übergeordnetes Element ist, erhält es nach der Eingabe Klickinteraktionen. Am Ende des dragEnd
-Ereignisses haben Sie padRelease()
möglicherweise als seltsam klingende Funktion bemerkt.
const padRelease = () => {
state.recentlyDragged = true
setTimeout(_ => {
state.recentlyDragged = false
}, 300)
}
Dadurch wird das Label berücksichtigt, das diesen späteren Klick erhält, da damit die Interaktion eines Nutzers deaktiviert oder überprüft wird.
Wenn ich das noch einmal machen müsste, könnte ich erwägen, während des UX-Upgrades DOM mit JavaScript anzupassen, um ein Element zu erstellen, das die Labelklicks selbst verarbeitet und das integrierte Verhalten nicht beeinträchtigt.
Ich schreibe am wenigsten für diese Art von JavaScript und ich möchte kein bedingtes Ereignis-Bubbling verwalten:
const preventBubbles = event => {
if (state.recentlyDragged)
event.preventDefault() && event.stopPropagation()
}
Fazit
Diese kurzweilige Switch-Komponente war bisher die meiste Arbeit aller GUI-Herausforderungen! Jetzt weißt du, wie ich es gemacht habe. Wie würdest du es erreichen? 🙂
Diversifizieren wir unsere Ansätze und lernen Sie alle Möglichkeiten kennen, wie wir das Web nutzen können. Erstelle eine Demo und twittere mich über Links, und ich füge sie unten zum Abschnitt über Community-Remixe hinzu.
Community-Remixe
- @KonstantinRouda mit einem benutzerdefinierten Element: Demo und Code
- @jhvanderschee mit einer Schaltfläche: Codepen.
Ressourcen
Suchen Sie den Quellcode von .gui-switch
auf GitHub.