Ein grundlegender Überblick über die Erstellung einer responsiven und barrierefreien Schalterkomponente.
In diesem Beitrag möchte ich auf meine Gedanken zum Erstellen von Switch-Komponenten eingehen. Demo ansehen.
<ph type="x-smartling-placeholder">Falls Sie Videos bevorzugen, finden Sie hier eine YouTube-Version dieses Beitrags:
Übersicht
Ein Schalter funktioniert ähnlich wie ein Kästchen. stellt aber explizit boolesche Ein- und Ausschaltstatus dar.
In dieser Demo wird <input type="checkbox" role="switch">
für den Großteil der
Diese Funktion hat den Vorteil, dass CSS oder JavaScript
voll funktionsfähig und barrierefrei zugänglich ist. Durch das Laden von CSS wird die linksläufige Schreibrichtung unterstützt.
Sprachen, Vertikalität, Animation und mehr. Wenn JavaScript geladen wird,
ziehbar und greifbar.
Benutzerdefinierte Eigenschaften
Die folgenden Variablen repräsentieren die verschiedenen Teile des Switches und ihre
Optionen. Als Klasse der obersten Ebene enthält .gui-switch
benutzerdefinierte Eigenschaften, die verwendet werden.
in allen untergeordneten Komponenten und Einstiegspunkte für zentralisierte
Personalisierung.
Verfolgen
Die Länge (--track-size
), der 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%);
}
}
Thumbnails
Größe, Hintergrundfarbe und Hervorhebungsfarben für Interaktionen:
.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 Bewegungsfreiheit
Um einen eindeutigen Alias hinzuzufügen und Wiederholungen zu reduzieren, wurde die Bewegungseinstellung für Nutzer reduziert. können Sie mit der Funktion PostCSS Plug-in auf Basis dieses Entwurfs Spezifikation in Medienabfragen 5:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
Markup
Ich habe mich entschieden, mein <input type="checkbox" role="switch">
-Element mit einem
<label>
, die Beziehung wird gebündelt, um eine Verknüpfung von Kästchen und Labels zu vermeiden
und den Nutzenden die Möglichkeit geben, mit dem Label zu interagieren,
um den Eingang ein-/auszuschalten.
<label for="switch" class="gui-switch">
Label text
<input type="checkbox" role="switch" id="switch">
</label>
In <input type="checkbox">
ist bereits Folgendes vorinstalliert:
API
und state. Die
der Browser verwaltet
checked
und Eingaben
Veranstaltungen
wie oninput
und onchanged
.
Layouts
Flexbox grid und custom Properties die Stile dieser Komponente beibehalten. Sie zentralisieren Werte, geben Namen auf ansonsten mehrdeutige Berechnungen oder Flächen API für einfache Komponentenanpassungen
.gui-switch
Das Layout der obersten Ebene für den Schalter ist Flexbox. Die Klasse .gui-switch
enthält
Die privaten und öffentlichen benutzerdefinierten Eigenschaften, mit denen die untergeordneten Elemente ihre
Layouts.
.gui-switch {
display: flex;
align-items: center;
gap: 2ch;
justify-content: space-between;
}
Das Erweitern und Ändern des Flexbox-Layouts entspricht dem Ändern eines beliebigen Flexbox-Layouts.
Zum Beispiel, um Labels über oder unter einem Schalter zu platzieren oder um den
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 wie eine Schaltspur dargestellt, indem die normale
appearance: checkbox
und stellt stattdessen seine eigene Größe bereit:
.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 Track erstellt außerdem einen Raster-Trackbereich mit einer einzelnen Zelle, den Sie mit dem Daumen Anspruch erheben.
Thumbnails
Mit dem Stil appearance: none
wird auch das visuelle Häkchen des
Browser. Diese Komponente verwendet ein
Pseudoelement und :checked
pseudo-class bei der Eingabe
können Sie diesen visuellen Indikator ersetzen.
Der „thumb“ ist ein untergeordnetes Pseudoelement, das mit input[type="checkbox"]
verknüpft ist.
über dem Track statt darunter stapeln, indem Sie den Rasterbereich beanspruchen
track
:
.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 Farben anpasst linksläufige Sprachen und Bewegungseinstellungen.
Berührungs-Interaktionsstile
Auf Mobilgeräten fügen Browser Tipphervorhebungen und Textauswahlfunktionen zu Labels und
Eingaben. Dies beeinträchtigte den Stil und das visuelle Interaktionsfeedback,
dieser Schalter erforderlich war. Mit ein paar CSS-Zeilen kann ich diese Effekte entfernen
Mein eigener cursor: pointer
-Stil:
.gui-switch {
cursor: pointer;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
Es ist nicht immer ratsam, diese Stile zu entfernen, da sie visuell wertvoll sein können Interaktions-Feedback. Geben Sie unbedingt benutzerdefinierte Alternativen an, wenn Sie diese entfernen.
Verfolgen
Bei den Stilen dieses Elements geht es hauptsächlich um seine Form und Farbe, auf die es zugreift
vom übergeordneten Element .gui-switch
über die
Cascade.
.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);
}
Es gibt vier Anpassungsoptionen
benutzerdefinierten Eigenschaften. border: none
wurde hinzugefügt, da appearance: none
dies nicht
entfernen Sie die Rahmen in allen Browsern aus dem Kontrollkästchen.
Thumbnails
Das „thumb“-Element befindet sich bereits auf der rechten Seite track
, benötigt jedoch einen Kreisstil:
.gui-switch > input::before {
background: var(--thumb-color);
border-radius: 50%;
}
Interaktion
Benutzerdefinierte Eigenschaften verwenden, um Interaktionen vorzubereiten, bei denen der Mauszeiger darauf bewegt wird und Änderungen der Daumenposition. Die Präferenz des Nutzers ist ebenfalls ausgewählt, bevor Sie den oder den Mauszeiger darauf bewegen.
.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 eine einzige Quelle für die Positionierung des „Mag ich“-Effekts in
den Titel. Wir bieten Ihnen die Track- und Thumbnail-Größen, die wir in
um den Daumen mit Abstand und zwischen den Tracks zu verschieben:
0%
und 100%
.
Das Element input
besitzt die Positionsvariable --thumb-position
und das „thumb“-Element
wird es vom Pseudoelement als translateX
-Position verwendet:
.gui-switch > input {
--thumb-position: 0%;
}
.gui-switch > input::before {
transform: translateX(var(--thumb-position));
}
Wir können --thumb-position
jetzt frei von CSS und den Pseudoklassen ändern.
für Kästchenelemente. Da wir zuvor für dieses Element transition: transform
var(--thumb-transition-duration) ease
bedingt festgelegt haben, ändern sich diese Änderungen
kann bei Änderung animiert 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 fand, dass diese entkoppelte Orchestrierung gut funktioniert hat. Das „thumb“-Element ist
betrifft nur ein Design, eine translateX
-Position. Die Eingabe kann alle
Komplexität und Berechnungen.
Branche
Die Unterstützung wurde mit der Modifikatorklasse -vertical
durchgeführt, die eine Rotation mit
CSS-Transformationen werden in das input
-Element umgewandelt.
Ein 3D-Drehelement ändert jedoch nicht die Gesamthöhe der Komponente,
was das Block-Layout durcheinanderbringen kann. Berücksichtigen Sie dies mithilfe von --track-size
und
--track-padding
Variablen. Berechnen Sie den minimalen Speicherplatz, der für
eine vertikale Schaltfläche, um wie erwartet im Layout zu verlaufen:
.gui-switch.-vertical {
min-block-size: calc(var(--track-size) + calc(var(--track-padding) * 2));
& > input {
transform: rotate(-90deg);
}
}
Rechts-nach-links (RTL)
Ein Freund von CSS, Elad Schecter, und ich haben einen Prototyp ein Seitenmenü mit CSS-Transformationen, die von rechts nach links bewegt wurden, Sprachen durch Umdrehen eines einzelnen . Wir haben dies getan, weil es in CSS keine logischen Eigenschaftstransformationen gibt. und die werden es vielleicht nie geben. Elad hatte die Idee, einen Wert für eine benutzerdefinierte Eigenschaft zu verwenden. Prozentsätze umkehren, um die Verwaltung von benutzerdefinierten Logik für logische Transformationen. Ich habe diese Technik auch bei diesem Schalter verwendet. fanden, dass es gut funktioniert hat:
.gui-switch {
--isLTR: 1;
&:dir(rtl) {
--isLTR: -1;
}
}
Eine benutzerdefinierte Eigenschaft namens --isLTR
hat anfangs den Wert 1
. Es ist also
true
, da das Layout standardmäßig von links nach rechts ist. Dann können Sie mit dem CSS-Code
Pseudoklasse :dir()
wird der Wert auf -1
gesetzt, wenn sich die Komponente in einem linksläufigen Layout befindet.
Setzen Sie --isLTR
in Aktion um, indem Sie es innerhalb einer calc()
innerhalb einer Transformation verwenden:
.gui-switch.-vertical > input {
transform: rotate(-90deg);
transform: rotate(calc(90deg * var(--isLTR) * -1));
}
Durch die Drehung des vertikalen Schalters wird die Position der gegenüberliegenden Seite berücksichtigt. die für das Rechts-nach-links-Layout erforderlich sind.
Das translateX
-Element im Pseudoelement für den Daumen muss ebenfalls so geändert werden, dass es
Anforderung der Gegenseite 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 nicht, um alle Anforderungen an ein Konzept wie logisches CSS zu erfüllen. bietet es einige DRY-Prinzipien für viele Anwendungsfälle.
Bundesstaaten
Ohne die integrierte input[type="checkbox"]
-Lösung
die möglichen Statusangaben verarbeiten: :checked
, :disabled
,
:indeterminate
und :hover
. :focus
wurde absichtlich in Angriff genommen, mit einem
Anpassungen nur an ihrem Offset; sah der Fokusring in Firefox und
Safari:
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 die Eingabe
der Hintergrund auf die aktive Farbe gesetzt ist und die Daumenposition auf
end".
.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
-Element unveränderlich.Die Unveränderlichkeit der Interaktion ist vom Browser kostenlos, aber die Eigenschaft
Für visuelle Zustände sind 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 Zustand ist schwierig, da dunkle und helle Designs erforderlich sind, bei denen sowohl deaktivierte als auch geprüften Status. Ich habe für diese Staaten stilistisch minimale Stile ausgewählt, den Verwaltungsaufwand der Stilkombinationen.
Unklar
Ein häufig vergessener Status ist :indeterminate
, wobei ein Kästchen keine von beiden
aktiviert oder deaktiviert ist. Das macht Spaß, ist einladend und unscheinbar. Eine gute
zur Erinnerung, dass boolesche Zustände
zwischen den Zuständen versteckt sein können.
Es ist schwierig, ein Kästchen auf „Unbestimmt“ festzulegen. Nur JavaScript kann es setzen:
<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 unaufdringlich und einladend ist, fühlte es sich an, Schalter-Daumenposition in der Mitte:
.gui-switch > input:indeterminate {
--thumb-position: calc(
calc(calc(var(--track-size) / 2) - calc(var(--thumb-size) / 2))
* var(--isLTR)
);
}
Mauszeiger hierher bewegen
Interaktionen über den Mauszeiger sollten die verbundene Benutzeroberfläche visuell unterstützen Richtung der interaktiven Benutzeroberfläche. Dieser Schalter hebt den Daumen mit ein halbtransparenter Ring, wenn der Mauszeiger auf das Label oder die Eingabe bewegt wird. Diese Mausbewegung gibt die Animation die Richtung des interaktiven Thumbnail-Elements vor.
Das „Highlight“ wird mit box-shadow
vorgenommen. Wenn der Mauszeiger auf eine nicht deaktivierte Eingabe bewegt wird, wird die Größe von --highlight-size
erhöht. Wenn der Nutzer mit Bewegung einverstanden ist, wechseln wir den box-shadow
und sehen, wie er größer wird. Ist Bewegung nicht akzeptabel, wird die Markierung 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 es unheimlich, wenn eine Switch-Oberfläche eine physische insbesondere diese mit einem Kreis innerhalb der Spur. iOS hat das richtig gemacht können Sie sie von einer Seite zur anderen ziehen. die Möglichkeit haben. Umgekehrt kann sich ein UI-Element als inaktiv anfühlen, wenn eine Ziehgeste und es passiert nichts.
Ziehbare Daumen
Das Pseudoelement für den Daumen erhält seine Position vom .gui-switch > input
.
mit Geltungsbereich var(--thumb-position)
, kann JavaScript einen Inline-Style-Wert für
Die Eingabe, um die Daumenposition dynamisch zu aktualisieren, sodass sie dem Anschein nach zu folgen
die Zeiger-Geste verwenden. Wenn der Zeiger losgelassen wird, entfernen Sie die Inline-Stile und
Ermitteln, ob der Ziehpunkt näher an „Aus“ oder „An“ lag, indem die benutzerdefinierte Eigenschaft verwendet wird
--thumb-position
Dies ist das Rückgrat der Lösung: Zeigerereignisse
Zeigerpositionen bedingt erfassen, um benutzerdefinierte CSS-Eigenschaften zu ändern.
Da die Komponente bereits zu 100% funktionsfähig war, bevor dieses Skript angezeigt wird, ist es ziemlich aufwendig, das bestehende Verhalten aufrechtzuerhalten, Klicken Sie auf ein Label, um die Eingabe zu wechseln. Unser JavaScript sollte keine Funktionen unter und die Kosten vorhandener Funktionen.
touch-action
Das Ziehen ist eine benutzerdefinierte Geste und eignet sich daher gut für
Vorteile von touch-action
. Bei diesem Schalter sollte eine horizontale Geste
vom Script verarbeitet werden, oder eine vertikale Geste, die für den vertikalen Wechsel erfasst wurde
Variante. Mit touch-action
können wir dem Browser mitteilen, welche Gesten auf
damit das Skript eine Geste ohne Konkurrenz verarbeiten kann.
Mit dem folgenden CSS-Code wird der Browser angewiesen, in diesem Schalter-Track, vertikale Gesten verarbeiten, nichts mit horizontalen Gesten machen eins:
.gui-switch > input {
touch-action: pan-y;
}
Das gewünschte Ergebnis ist eine horizontale Bewegung, bei der die Seite. Ein Zeiger kann vertikal scrollen, beginnend innerhalb der Eingabe und scrollt Seiten, aber horizontale werden benutzerdefiniert bearbeitet.
Dienstprogramme für den Stil von Pixel-Werten
Bei der Einrichtung und während des Ziehens müssen verschiedene berechnete Zahlenwerte erfasst werden.
aus Elementen zu extrahieren. Die folgenden JavaScript-Funktionen geben berechnete Pixelwerte zurück
CSS-Eigenschaft angegeben werden. Er wird im Einrichtungsskript wie folgt 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, wie window.getComputedStyle()
ein zweites Argument annimmt, ein Pseudoelement. Ziemlich praktisch, dass JavaScript so viele Werte aus Elementen lesen kann, auch aus Pseudoelementen.
dragging
Dies ist ein zentraler Moment der Drag-Logik und es gibt einige Dinge, aus dem Event-Handler der Funktion:
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 Held des Skripts ist state.activethumb
, der kleine Kreis, in dem das Skript zu sehen ist
mit einem Zeiger positioniert werden. Das switches
-Objekt ist ein Map()
, bei dem der
Schlüssel sind .gui-switch
-Schlüssel und die Werte sind zwischengespeicherte Grenzen und Größen, die
das Skript effizient zu gestalten. Linksläufig wird die gleiche benutzerdefinierte Eigenschaft verwendet.
dass der CSS-Code --isLTR
ist und damit die Logik umkehren und fortfahren
mit RTL. Auch event.offsetX
ist hilfreich, da es ein Delta enthält.
-Wert, der für die Positionierung des Daumens nützlich ist.
state.activethumb.style.setProperty('--thumb-position', `${track + pos}px`)
Mit dieser letzten CSS-Zeile wird die vom thumb-Element verwendete benutzerdefinierte Eigenschaft festgelegt. Dieses
würde die Wertezuweisung mit der Zeit
übergangen werden, aber ein vorheriger Zeiger
Für dieses Ereignis wurde „--thumb-transition-duration
“ vorübergehend auf 0s
gesetzt. Dabei wird Folgendes entfernt:
nur sehr schleppend gewesen wäre.
dragEnd
Damit der Nutzer weit aus dem Schalter heraus ziehen und loslassen kann, Erforderliches globales Fensterereignis registriert:
window.addEventListener('pointerup', event => {
if (!state.activethumb) return
dragEnd(event)
})
Ich denke, es ist sehr wichtig, dass Nutzende die Freiheit haben, Benutzeroberfläche so intelligent sein, dass sie das berücksichtigt. Es hat nicht viel gedauert, um damit umzugehen diese Umstellung erforderte aber sorgfältige Überlegungen. .
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()
}
Interaktion mit dem Element ist abgeschlossen, Zeit zum Festlegen der Eingabe ist aktiviert
und entfernen Sie alle Bewegungsereignisse. Das Kästchen wird geändert mit
state.activethumb.checked = determineChecked()
determineChecked()
Diese von dragEnd
aufgerufene Funktion bestimmt, wo der Daumenstrom
innerhalb der Grenzen des Tracks liegt und gibt "true" zurück, wenn der Wert gleich oder darüber ist
auf der Hälfte der Strecke:
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
Durch die Drag-Geste entstanden aufgrund der anfänglichen HTML-Struktur einige Code-Altlasten.
vor allem das Einbinden der Eingabe
in ein Label. Das Label als übergeordnetes Element
-Elements nach der Eingabe Klickinteraktionen erhalten. Am Ende des
dragEnd
-Ereignis, hast du vielleicht schon bemerkt, dass padRelease()
seltsam klingt
.
const padRelease = () => {
state.recentlyDragged = true
setTimeout(_ => {
state.recentlyDragged = false
}, 300)
}
Damit wird das Label berücksichtigt, das diesen späteren Klick erhält, da es das Häkchen die Interaktion eines Nutzers.
In diesem Fall könnte ich das DOM mit JavaScript anpassen. während des UX-Upgrades, z. B. um ein Element zu erstellen, das Labelklicks selbst verarbeitet. und kämpft nicht mit dem integrierten Verhalten.
Diese Art von JavaScript schreibe ich am liebsten, bedingtes Ereignis-Bubbling:
const preventBubbles = event => {
if (state.recentlyDragged)
event.preventDefault() && event.stopPropagation()
}
Fazit
Diese teeny-Switch-Komponente war die meiste Arbeit in allen GUI-Challenges. soweit! Jetzt, wo du weißt, wie ich es gemacht habe, wie würdest du... ‽ 🙂
Lassen Sie uns unsere Herangehensweisen diversifizieren und alle Möglichkeiten kennenlernen, wie wir das Web entwickeln können. Erstelle eine Demo, twittere mir Links und ich füge sie hinzu im Abschnitt „Community-Remixe“ weiter unten.
Community-Remixe
- @KonstantinRouda mit einem benutzerdefinierten Element: demo und code
- @jhvanderschee durch eine Schaltfläche: Codepen.
Ressourcen
Den Quellcode von .gui-switch
finden Sie auf
GitHub