Komponente „Einstellungen“ erstellen

Eine grundlegende Übersicht zum Erstellen einer Einstellungskomponente mit Schiebereglern und Kästchen.

In diesem Beitrag möchte ich meine Gedanken zum Erstellen einer responsiven, geräteübergreifenden und browserübergreifenden Einstellungskomponente für das Web teilen. Demo ansehen

Demo

Wenn du lieber ein Video oder eine UI/UX-Vorschau von dem siehst, was wir gerade entwickeln, findest du hier eine kürzere Demo auf YouTube:

Übersicht

Ich habe die Aspekte dieser Komponente in die folgenden Abschnitte unterteilt:

  1. Layouts
  2. Farbe
  3. Benutzerdefinierter Bereich
  4. Benutzerdefinierte Kästcheneingaben
  5. Aspekte der Barrierefreiheit
  6. JavaScript

Layouts

Dies ist die erste GUI-Challenge-Demo, die nur aus CSS-Grid besteht. Hier sind die einzelnen Raster mit den Chrome-Entwicklertools für Raster hervorgehoben:

Farbige Umrisse und Überlagerungen für Lücken, die alle Felder im Layout der Einstellungen zeigen

Nur für Lücke

Das gängigste Layout:

foo {
  display: grid;
  gap: var(--something);
}

Ich nenne dieses Layout „nur für Lücke“, weil es nur das Raster verwendet, um Lücken zwischen den Blöcken hinzuzufügen.

Bei fünf Layouts wird diese Strategie verwendet. Hier sind sie alle zu sehen:

Vertikale Rasterlayouts mit Umrissen und gefüllten Lücken

Das Element fieldset, das jede Eingabegruppe (.fieldset-item) enthält, verwendet gap: 1px, um die Haarstrichränder zwischen den Elementen zu erstellen. Keine komplizierte Lösung für Rahmen!

Geschlossene Lücke
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
Rahmentrick
.grid {
  display: grid;

  & > .fieldset-item {
    background: var(--bg-surface-2);

    &:not(:last-child) {
      border-bottom: 1px solid var(--bg-surface-1);
    }
  }
}

Natürlicher Rasterumbruch

Das komplexeste Layout war das Makro-Layout, das logische Layoutsystem zwischen <main> und <form>.

Umbruchinhalte zentrieren

Sowohl Flexbox als auch Grid bieten Funktionen für align-items oder align-content. Bei Elementen mit Umbruch wird der Platz durch content-Layoutausrichtungen als Gruppe unter den untergeordneten Elementen verteilt.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
}

Für das Hauptelement wird die place-content: center-Ausrichtungskurzschreibweise verwendet, damit die untergeordneten Elemente sowohl in einem einspaltigen als auch in einem zweispaltigen Layout vertikal und horizontal zentriert sind.

Im Video oben sehen Sie, dass der „Inhalt“ zentriert bleibt, auch wenn er umgebrochen wird.

Min/Max für automatische Anpassung wiederholen

Der <form> verwendet für jeden Abschnitt ein adaptives Rasterlayout. Bei diesem Layout wird je nach verfügbarem Platz zwischen einer und zwei Spalten gewechselt.

form {
  display: grid;
  gap: var(--space-xl) var(--space-xxl);
  grid-template-columns: repeat(auto-fit, minmax(min(10ch, 100%), 35ch));
  align-items: flex-start;
  max-width: 89vw;
}

Dieses Raster hat einen anderen Wert für row-gap (--space-xl) als für column-gap (--space-xxl), um dem responsiven Layout eine individuelle Note zu verleihen. Wenn die Spalten gestapelt sind, sollte ein großer Abstand vorhanden sein, aber nicht so groß wie bei einem Breitbild.

Für die Property grid-template-columns werden drei CSS-Funktionen verwendet: repeat(), minmax() und min(). Una Kravets hat einen tollen Blogpost zum Thema Layout, in dem sie es RAM nennt.

Im Vergleich zu Unas Layout gibt es drei besondere Ergänzungen in unserem Layout:

  • Wir übergeben eine zusätzliche min()-Funktion.
  • Wir geben align-items: flex-start an.
  • Es gibt einen max-width: 89vw-Stil.

Die zusätzliche min()-Funktion wird von Evan Minto in seinem Blog im Beitrag Intrinsically Responsive CSS Grid with minmax() and min() gut beschrieben. Ich empfehle Ihnen, ihn zu lesen. Mit der flex-start-Ausrichtungskorrektur wird der Standard-Dehnungseffekt entfernt, sodass die untergeordneten Elemente dieses Layouts nicht dieselbe Höhe haben müssen, sondern eine natürliche, inhärente Höhe haben können. Im YouTube-Video wird diese neue Ausrichtung kurz erläutert.

max-width: 89vw ist in diesem Beitrag einen kleinen Ausflug wert. Hier sehen Sie das Layout mit und ohne angewendeten Stil:

Was ist passiert? Wenn max-width angegeben ist, liefert es Kontext, explizite Größen oder eindeutige Größen für den auto-fitLayoutalgorithmus, damit dieser weiß, wie viele Wiederholungen in den Bereich passen. Es mag zwar offensichtlich erscheinen, dass der Bereich „volle Breite“ hat, aber gemäß der CSS-Rasterspezifikation muss eine bestimmte Größe oder eine maximale Größe angegeben werden. Ich habe eine maximale Größe angegeben.

Warum also 89vw? Weil es für mein Layout „funktioniert“ hat. Ich und einige andere Chrome-Mitarbeiter untersuchen, warum ein vernünftigerer Wert wie 100vw nicht ausreicht, und ob es sich tatsächlich um einen Fehler handelt.

Abstand

Der Großteil der Harmonie dieses Layouts beruht auf einer begrenzten Palette von Abständen, genauer gesagt auf sieben.

:root {
  --space-xxs: .25rem;
  --space-xs:  .5rem;
  --space-sm:  1rem;
  --space-md:  1.5rem;
  --space-lg:  2rem;
  --space-xl:  3rem;
  --space-xxl: 6rem;
}

Diese Abläufe eignen sich hervorragend für das Raster, CSS @nest und die Syntax der Stufe 5 von @media. Hier ein Beispiel für den vollständigen Satz von Stilen für das <main>-Layout.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
  padding: var(--space-sm);

  @media (width >= 540px) {
    & {
      padding: var(--space-lg);
    }
  }

  @media (width >= 800px) {
    & {
      padding: var(--space-xl);
    }
  }
}

Ein Raster mit zentrierten Inhalten, die standardmäßig mäßig eingerückt sind (wie auf Mobilgeräten). Wenn jedoch mehr Viewport-Raum verfügbar ist, wird er durch ein größeres Padding verteilt. Das CSS für 2021 sieht ziemlich gut aus.

Erinnern Sie sich an das vorherige Layout, „nur für Lücke“? Hier sehen Sie eine vollständigere Version, wie sie in dieser Komponente aussehen:

header {
  display: grid;
  gap: var(--space-xxs);
}

section {
  display: grid;
  gap: var(--space-md);
}

Farbe

Durch die kontrollierte Verwendung von Farbe hebt sich dieses Design als ausdrucksstark und gleichzeitig minimalistisch hervor. Ich mache es so:

:root {
  --surface1: lch(10 0 0);
  --surface2: lch(15 0 0);
  --surface3: lch(20 0 0);
  --surface4: lch(25 0 0);

  --text1: lch(95 0 0);
  --text2: lch(75 0 0);
}

Ich benenne meine Oberflächen- und Textfarben mit Zahlen, anstatt sie wie surface-dark und surface-darker zu benennen, da ich sie in einer Medienabfrage umkehren werde und „hell“ und „dunkel“ dann keinen Sinn mehr ergeben.

Ich wende sie in einer Abfrage für bevorzugte Medien so an:

:root {
  ...

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --surface2: lch(100 0 0);
      --surface3: lch(98 0 0);
      --surface4: lch(85 0 0);

      --text1: lch(20 0 0);
      --text2: lch(40 0 0);
    }
  }
}

Es ist wichtig, sich einen Überblick über das Gesamtbild und die Strategie zu verschaffen, bevor wir uns mit den Details der Farbsyntax befassen. Aber da ich etwas vorgegriffen habe, möchte ich noch einmal von vorn beginnen.

LCH?

Ohne zu sehr in die Farbtheorie einzutauchen: LCH ist eine menschenorientierte Syntax, die sich darauf konzentriert, wie wir Farbe wahrnehmen, nicht wie wir Farbe mathematisch messen (z. B. 255). Das hat einen entscheidenden Vorteil, da Menschen sie leichter schreiben können und andere Menschen mit diesen Anpassungen vertraut sind.

Ein Screenshot der Webseite pod.link/csspodcast mit der Folge „Farbe 2: Wahrnehmung“
Informationen zu Farbempfinden und mehr im CSS-Podcast

In dieser Demo konzentrieren wir uns auf die Syntax und die Werte, die ich umkehre, um Licht und Dunkelheit zu erzeugen. Sehen wir uns eine Oberfläche und eine Textfarbe an:

:root {
  --surface1: lch(10 0 0);
  --text1:    lch(95 0 0);

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --text1:    lch(40 0 0);
    }
  }
}

--surface1: lch(10 0 0) entspricht einer Helligkeit von 10%, einer Farbsättigung von 0 und einem Farbton von 0: ein sehr dunkles, farbloses Grau. In der Medienabfrage für den hellen Modus wird die Helligkeit dann mit --surface1: lch(90 0 0); auf 90% umgestellt. Das ist der Kern der Strategie. Ändern Sie zuerst nur die Helligkeit zwischen den beiden Themen, wobei Sie die vom Design geforderten oder für die Barrierefreiheit erforderlichen Kontrastverhältnisse beibehalten.

Der Vorteil von lch() ist, dass Leichtigkeit auf Menschen ausgerichtet ist. Wir können uns also sicher sein, dass eine %-Änderung wahrgenommen wird und sich konsistent % unterscheidet. hsl() ist beispielsweise nicht so zuverlässig.

Wenn Sie mehr über Farbräume und lch() erfahren möchten, finden Sie hier weitere Informationen. Es ist bald soweit!

CSS kann derzeit nicht auf diese Farben zugreifen. Noch einmal: Wir haben keinen Zugriff auf ein Drittel der Farben auf den meisten modernen Monitoren. Und das sind nicht irgendwelche Farben, sondern die lebendigste Farbe, die das Display darstellen kann. Unsere Websites sind ausgebleicht, weil sich die Monitorhardware schneller weiterentwickelt hat als die CSS-Spezifikationen und Browserimplementierungen.

Lea Verou

Anpassbare Formularsteuerelemente mit Farbschema

Viele Browser bieten Steuerelemente für dunkle Themen, derzeit Safari und Chromium. Sie müssen jedoch in CSS oder HTML angeben, dass Ihr Design diese verwendet.

Oben sehen Sie die Wirkung der Property im Bereich „Styles“ der DevTools. In der Demo wird das HTML-Tag verwendet, was meiner Meinung nach generell eine bessere Lösung ist:

<meta name="color-scheme" content="dark light">

Weitere Informationen finden Sie color-schemein diesem Artikel von Thomas Steiner. Es gibt noch viel mehr zu gewinnen als dunkle Kästcheneingaben.

Preisvergleichsportal accent-color

Es gab in letzter Zeit Aktivitäten im Zusammenhang mit accent-color für Formularelemente. Dabei handelt es sich um einen einzelnen CSS-Stil, mit dem die Tönung der Farbe geändert werden kann, die im Eingabeelement des Browsers verwendet wird. Weitere Informationen dazu auf GitHub Ich habe ihn in meine Stile für diese Komponente aufgenommen. Da die Browser dies unterstützen, werden meine Kästchen mit den rosa und lila Farbakzenten besser zum Thema passen.

input[type="checkbox"] {
  accent-color: var(--brand);
}

Ein Screenshot von rosa Kästchen in Chromium unter Linux

Color Pop-Fotos mit festen Farbverläufen und Fokus nach innen

Farben kommen am besten zur Geltung, wenn sie sparsam verwendet werden. Eine Möglichkeit, dies zu erreichen, sind farbenfrohe UI-Interaktionen.

Im obigen Video gibt es viele Ebenen von UI-Feedback und Interaktion, die der Interaktion Persönlichkeit verleihen:

  • Kontext hervorheben
  • Feedback zur „Auslastung“ des Werts im Bereich
  • Feedback zur Benutzeroberfläche geben, dass ein Feld Eingaben akzeptiert

Um Feedback zu geben, wenn mit einem Element interagiert wird, verwendet CSS die Pseudoklasse :focus-within, um das Aussehen verschiedener Elemente zu ändern. Sehen wir uns die .fieldset-item genauer an:

.fieldset-item {
  ...

  &:focus-within {
    background: var(--surface2);

    & svg {
      fill: white;
    }

    & picture {
      clip-path: circle(50%);
      background: var(--brand-bg-gradient) fixed;
    }
  }
}

Wenn eines der untergeordneten Elemente dieses Elements den Fokus hat:

  1. Dem .fieldset-item-Hintergrund wird eine kontrastreichere Oberflächenfarbe zugewiesen.
  2. Das verschachtelte svg ist für einen höheren Kontrast weiß gefüllt.
  3. Das verschachtelte <picture> clip-path wird zu einem vollständigen Kreis und der Hintergrund wird mit dem hellen festen Farbverlauf gefüllt.

Benutzerdefinierter Zeitraum

Ich zeige Ihnen anhand des folgenden HTML-Eingabeelements, wie ich das Erscheinungsbild angepasst habe:

<input type="range">

An diesem Element müssen wir drei Teile anpassen:

  1. Bereichselement / -container
  2. Track
  3. Daumen

Stile für Bereichselemente

input[type="range"] {
  /* style setting variables */
  --track-height: .5ex;
  --track-fill: 0%;
  --thumb-size: 3ex;
  --thumb-offset: -1.25ex;
  --thumb-highlight-size: 0px;

  appearance: none;         /* clear styles, make way for mine */
  display: block;
  inline-size: 100%;        /* fill container */
  margin: 1ex 0;            /* ensure thumb isn't colliding with sibling content */
  background: transparent;  /* bg is in the track */
  outline-offset: 5px;      /* focus styles have space */
}

Die ersten Zeilen des CSS sind die benutzerdefinierten Teile der Stile. Ich hoffe, dass es hilfreich ist, sie klar zu kennzeichnen. Die übrigen Stile sind größtenteils zurückgesetzte Stile, um eine einheitliche Grundlage für die Erstellung der schwierigen Teile der Komponente zu schaffen.

Titelstile

input[type="range"]::-webkit-slider-runnable-track {
  appearance: none; /* clear styles, make way for mine */
  block-size: var(--track-height);
  border-radius: 5ex;
  background:
    /* hard stop gradient:
        - half transparent (where colorful fill we be)
        - half dark track fill
        - 1st background image is on top
    */
    linear-gradient(
      to right,
      transparent var(--track-fill),
      var(--surface1) 0%
    ),
    /* colorful fill effect, behind track surface fill */
    var(--brand-bg-gradient) fixed;
}

Der Trick besteht darin, die leuchtende Füllungsfarbe „hervorzuheben“. Dazu wird oben der Farbverlauf mit dem harten Farbstopp verwendet. Der Farbverlauf ist bis zum Füllprozentsatz transparent. Danach wird die Farbe der nicht belegten Streckenoberfläche verwendet. Hinter dieser nicht ausgefüllten Fläche befindet sich eine Farbe in voller Breite, die durch Transparenz sichtbar wird.

Füllstil für Titel

Für mein Design ist JavaScript erforderlich, um den Füllungsstil beizubehalten. Es gibt CSS-Strategien, bei denen das Vorschauelement jedoch dieselbe Höhe wie der Titel haben muss. Ich konnte innerhalb dieser Grenzen keine Harmonie finden.

/* grab sliders on page */
const sliders = document.querySelectorAll('input[type="range"]')

/* take a slider element, return a percentage string for use in CSS */
const rangeToPercent = slider => {
  const max = slider.getAttribute('max') || 10;
  const percent = slider.value / max * 100;

  return `${parseInt(percent)}%`;
};

/* on page load, set the fill amount */
sliders.forEach(slider => {
  slider.style.setProperty('--track-fill', rangeToPercent(slider));

  /* when a slider changes, update the fill prop */
  slider.addEventListener('input', e => {
    e.target.style.setProperty('--track-fill', rangeToPercent(e.target));
  })
})

Ich denke, das ist eine schöne visuelle Verbesserung. Der Schieberegler funktioniert auch ohne JavaScript. Das --track-fill-Attribut ist nicht erforderlich. Wenn es nicht vorhanden ist, hat der Schieberegler einfach keinen Füllstil. Wenn JavaScript verfügbar ist, füllen Sie die benutzerdefinierte Property aus und beobachten Sie gleichzeitig alle Nutzeränderungen. Synchronisieren Sie die benutzerdefinierte Property dann mit dem Wert.

In diesem tollen Artikel zu CSS-Tricks von Ana Tudor wird eine reine CSS-Lösung für die Track-Füllung veranschaulicht. Auch dieses range-Element hat mich sehr inspiriert.

Stil für Vorschaubilder

input[type="range"]::-webkit-slider-thumb {
  appearance: none; /* clear styles, make way for mine */
  cursor: ew-resize; /* cursor style to support drag direction */
  border: 3px solid var(--surface3);
  block-size: var(--thumb-size);
  inline-size: var(--thumb-size);
  margin-top: var(--thumb-offset);
  border-radius: 50%;
  background: var(--brand-bg-gradient) fixed;
}

Die meisten dieser Stile dienen dazu, einen schönen Kreis zu zeichnen. Auch hier sehen Sie den festen Hintergrundverlauf, der die dynamischen Farben der Miniaturansichten, Titel und zugehörigen SVG-Elemente vereint. Ich habe die Stile für die Interaktion getrennt, um die box-shadow-Methode für die Hover-Hervorhebung zu isolieren:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

::-webkit-slider-thumb {
  

  /* shadow spread is initally 0 */
  box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);

  /* if motion is OK, transition the box-shadow change */
  @media (--motionOK) {
    & {
      transition: box-shadow .1s ease;
    }
  }

  /* on hover/active state of parent, increase size prop */
  @nest input[type="range"]:is(:hover,:active) & {
    --thumb-highlight-size: 10px;
  }
}

Ziel war es, ein einfach zu verwaltendes und animiertes visuelles Highlight für das Nutzerfeedback zu schaffen. Mit einem Schatten kann ich vermeiden, dass der Effekt das Layout auslöst. Dazu erstelle ich einen Schatten, der nicht verschwommen ist und der kreisförmigen Form des Vorschauelements entspricht. Dann ändere ich die Größe des Auszugs beim Hovern.

Wenn es nur so einfach wäre, Kästchen hervorzuheben…

Browserübergreifende Auswahl

Ich habe festgestellt, dass ich diese -webkit-- und -moz--Auswahlen benötige, um für alle Browser eine einheitliche Darstellung zu erreichen:

input[type="range"] {
  &::-webkit-slider-runnable-track {}
  &::-moz-range-track {}
  &::-webkit-slider-thumb {}
  &::-moz-range-thumb {}
}

Benutzerdefiniertes Kästchen

Ich zeige Ihnen anhand des folgenden HTML-Eingabeelements, wie ich das Erscheinungsbild angepasst habe:

<input type="checkbox">

An diesem Element müssen wir drei Teile anpassen:

  1. Kästchenelement
  2. Verknüpfte Labels
  3. Hervorhebungseffekt

Kästchenelement

input[type="checkbox"] {
  inline-size: var(--space-sm);   /* increase width */
  block-size: var(--space-sm);    /* increase height */
  outline-offset: 5px;            /* focus style enhancement */
  accent-color: var(--brand);     /* tint the input */
  position: relative;             /* prepare for an absolute pseudo element */
  transform-style: preserve-3d;   /* create a 3d z-space stacking context */
  margin: 0;
  cursor: pointer;
}

Die Stile transform-style und position bereiten das Pseudo-Element vor, das wir später vorstellen, um das Highlight zu formatieren. Ansonsten sind es meist kleinere, meinungsstarke Stilelemente von mir. Ich mag den Cursor als Zeiger, ich mag die Umriss-Abstände, die Standardkästchen sind zu klein und wenn accent-color unterstützt wird, sollten diese Kästchen in das Farbschema der Marke passen.

Kästchenlabels

Es ist aus zwei Gründen wichtig, Labels für Kästchen anzugeben. Erstens: Sie müssen angeben, wofür der Kästchenwert verwendet wird, um die Frage „Was wird aktiviert oder deaktiviert?“ zu beantworten. Zweitens: Webnutzer sind es gewohnt, über die zugehörigen Labels mit Kästchen zu interagieren.

Eingabe
<input
  type="checkbox"
  id="text-notifications"
  name="text-notifications"
>
Label
<label for="text-notifications">
  <h3>Text Messages</h3>
  <small>Get notified about all text messages sent to your device</small>
</label>

Fügen Sie Ihrem Label das Attribut for hinzu, das auf ein Kästchen mit der ID <label for="text-notifications"> verweist. Geben Sie sowohl den Namen als auch die ID doppelt in das Kästchen ein, damit es mit verschiedenen Tools und Technologien gefunden werden kann, z. B. mit einer Maus oder einem Screenreader: <input type="checkbox" id="text-notifications" name="text-notifications">. :hover, :active und mehr sind im Lieferumfang der Verbindung enthalten. So können Nutzer mit Ihrem Formular noch mehr Interaktionen ausführen.

Kästchen hervorheben

Ich möchte meine Benutzeroberflächen einheitlich gestalten. Das Schiebereglerelement hat ein schönes Miniaturbild-Highlight, das ich für das Kästchen verwenden möchte. Für das Thumbnail konnte box-shadow und dessen Property spread verwendet werden, um einen Schatten zu vergrößern und zu verkleinern. Dieser Effekt funktioniert hier jedoch nicht, da unsere Kästchen und sollten quadratisch sein.

Ich konnte denselben visuellen Effekt mit einem Pseudoelement und einer unglücklichen Menge an kompliziertem CSS erzielen:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

input[type="checkbox"]::before {
  --thumb-scale: .01;                        /* initial scale of highlight */
  --thumb-highlight-size: var(--space-xl);

  content: "";
  inline-size: var(--thumb-highlight-size);
  block-size: var(--thumb-highlight-size);
  clip-path: circle(50%);                     /* circle shape */
  position: absolute;                         /* this is why position relative on parent */
  top: 50%;                                   /* pop and plop technique (https://web.dev/centering-in-css#5-pop-and-plop) */
  left: 50%;
  background: var(--thumb-highlight-color);
  transform-origin: center center;            /* goal is a centered scaling circle */
  transform:                                  /* order here matters!! */
    translateX(-50%)                          /* counter balances left: 50% */
    translateY(-50%)                          /* counter balances top: 50% */
    translateZ(-1px)                          /* PUTS IT BEHIND THE CHECKBOX */
    scale(var(--thumb-scale))                 /* value we toggle for animation */
  ;
  will-change: transform;

  @media (--motionOK) {                       /* transition only if motion is OK */
    & {
      transition: transform .2s ease;
    }
  }
}

/* on hover, set scale custom property to "in" state */
input[type="checkbox"]:hover::before {
  --thumb-scale: 1;
}

Das Erstellen eines Kreis-Pseudoelements ist einfach, aber es war schwieriger, es hinter dem Element zu platzieren, an das es angehängt ist. Hier ist ein Vorher-Nachher-Vergleich:

Es ist definitiv eine Mikrointeraktion, aber für mich ist es wichtig, die visuelle Einheitlichkeit beizubehalten. Die Animationsskalierungstechnik ist die gleiche wie an anderen Stellen. Wir legen einer benutzerdefinierten Property einen neuen Wert zu und lassen sie dann basierend auf den Bewegungseinstellungen über CSS übergehen. Der wichtigste Aspekt ist hier translateZ(-1px). Das übergeordnete Element hat einen 3D-Raum erstellt und dieses Pseudo-Element hat sich darauf bezogen, indem es sich im Z‑Raum etwas nach hinten platziert hat.

Bedienungshilfen

Im YouTube-Video werden die Interaktionen mit Maus, Tastatur und Screenreader für diese Einstellungskomponente anschaulich demonstriert. Ich erläutere hier einige Details.

HTML-Elemente

<form>
<header>
<fieldset>
<picture>
<label>
<input>

Jedes enthält Hinweise und Tipps zum Browser des Nutzers. Einige Elemente geben Hinweise zur Interaktion, andere verbinden Interaktivität und wieder andere tragen zum Baum der Barrierefreiheit bei, durch den ein Screenreader navigiert.

HTML-Attribute

Wir können Elemente ausblenden, die von Screenreadern nicht benötigt werden, in diesem Fall das Symbol neben dem Schieberegler:

<picture aria-hidden="true">

Im obigen Video wird die Bedienung des Screenreaders unter macOS veranschaulicht. Beachten Sie, dass der Eingabefokus direkt von einem Schieberegler zum nächsten wechselt. Das liegt daran, dass wir das Symbol ausgeblendet haben, das möglicherweise eine Zwischenstation auf dem Weg zum nächsten Schieberegler war. Ohne dieses Attribut müsste ein Nutzer anhalten, zuhören und das Bild, das er möglicherweise nicht sehen kann, überspringen.

Das SVG enthält eine Menge Mathematik. Fügen wir ein <title>-Element für einen Titel hinzu, der beim Bewegen der Maus erscheint, und einen visuell lesbaren Kommentar dazu, was die Mathematik erzeugt:

<svg viewBox="0 0 24 24">
  <title>A note icon</title>
  <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
</svg>

Außerdem haben wir ausreichend deutlich gekennzeichnetes HTML verwendet, sodass das Formular mit Maus, Tastatur, Gamecontrollern und Screenreadern sehr gut funktioniert.

JavaScript

Ich habe bereits beschrieben, wie die Füllfarbe des Titels über JavaScript verwaltet wird. Sehen wir uns nun das JavaScript für <form> an:

const form = document.querySelector('form');

form.addEventListener('input', event => {
  const formData = Object.fromEntries(new FormData(form));
  console.table(formData);
})

Jedes Mal, wenn mit dem Formular interagiert und es geändert wird, wird es in der Konsole als Objekt in einer Tabelle protokolliert, damit es vor dem Senden an einen Server noch einmal überprüft werden kann.

Ein Screenshot der Ergebnisse von console.table(), in dem die Formulardaten in einer Tabelle angezeigt werden

Fazit

Jetzt, da Sie wissen, wie ich das gemacht habe, wie würden Sie es machen? Das macht die Komponentenarchitektur interessant. Wer erstellt die erste Version mit Slots in seinem bevorzugten Framework? 🙂

Lassen Sie uns unsere Ansätze diversifizieren und alle Möglichkeiten kennenlernen, wie Sie im Web entwickeln können. Erstelle eine Demo, tweete mir Links und ich füge sie unten im Abschnitt Community-Remixe hinzu.

Remixe der Community

  • @tomayac für seinen Stil beim Hover-Bereich für die Kästchenlabels. In dieser Version gibt es keine Lücke zwischen den Elementen demo und source.