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 Sie Videos bevorzugen oder eine UI/UX-Vorschau zu unseren Funktionen wünschen, finden Sie hier eine kürzere Schritt-für-Schritt-Anleitung 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. Überlegungen zur 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, die durch Umrisse hervorgehoben und Lücken ausgefüllt werden

Das fieldset-Element, das alle Eingabegruppen (.fieldset-item) enthält, verwendet gap: 1px, um die Haarlinien 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 auf die untergeordneten Elemente verteilt.

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

Für das Hauptelement wird die place-content: center Kurzschreibweise für die Ausrichtung 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.

Automatische Anpassung (Min/Max) wiederholen

Der <form> verwendet für jeden Abschnitt ein adaptives Rasterlayout. Dieses Layout wechselt je nach verfügbarem Platz von einer zu zwei Spalten.

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.

Es gibt drei spezielle Ergänzungen in unserem Layout, wenn Sie es mit Unas vergleichen:

  • 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, diese Funktion 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. Das YouTube-Video enthält eine kurze Aufschlüsselung dieser Ausrichtungszufügung.

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, werden Kontext, explizite Größenanpassung oder bestimmte Größenanpassung für den auto-fit-Layoutalgorithmus bereitgestellt, um zu wissen, 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 „geklappt 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-Nesting 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 zentriertem Inhalt, der standardmäßig (etwa auf Mobilgeräten) mäßig aufgefüllt ist. 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ücken“? Hier ist eine vollständigere Version davon, wie sie in dieser Komponente aussehen:

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

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

Farbe

Durch den kontrollierten Einsatz von Farben ist dieses Design ausdrucksstark und gleichzeitig minimal. Ich mache das 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 Präferenzabfrage für 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). Dies verleiht ihr einen deutlichen Vorteil, da sie von Menschen leichter geschrieben werden kann und andere Menschen auf diese Anpassungen abgestimmt werden können.

Screenshot der Webseite „pod.link/csspodcast“, auf dem die Folge „Farbe 2: Perception“ eingeblendet ist
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 Kontrastverhältnisse beibehalten oder die Barrierefreiheit aufrechterhalten.

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. Bald ist es so weit!

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 das dunkle Design, aktuell Safari und Chromium. Sie müssen jedoch in CSS oder HTML angeben, dass Ihr Design sie 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 als die Eingabe von dunklen Kästchen!

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 auf GitHub Ich habe ihn in meine Stile für diese Komponente aufgenommen. Wenn die Browser das unterstützen, werden meine Kästchen mit den rosa und lila Farbakzenten besser zum Thema passen.

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

Screenshot aus Chromium unter Linux mit pinken Kästchen

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 wird hervorgehoben.
  • Feedback zur „Auslastung“ des Werts im Bereich
  • UI-Feedback 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

Anhand des folgenden HTML-Eingabeelements zeige ich Ihnen, 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

Bereichselementstile

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 hilft, 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“. Dies geschieht mit dem Farbverlauf für die harten Stopps oben. 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 Strategien nur für CSS, aber dafür muss das Daumenelement dieselbe Höhe wie der Track haben, und 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 ein schönes visuelles Upgrade. 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 fand ich sehr inspirierend.

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. Wieder 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-Technik zu isolieren, die zum Hervorheben des Mauszeigers verwendet wird:

@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

Anhand des folgenden HTML-Eingabeelements zeige ich Ihnen, 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.

Labels für Kästchen

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.

Den gleichen visuellen Effekt konnte ich mit einem Pseudoelement erzielen – und das mit einigen komplizierten CSS:

@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;
}

Es ist ganz einfach, ein Kreis-Pseudoelement zu erstellen. Es war jedoch schwieriger, es hinter das 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 Skalierungstechnik für Animationen ist dieselbe, die wir auch an anderen Stellen verwendet haben. Wir legen einer benutzerdefinierten Property einen neuen Wert fest und lassen sie von CSS basierend auf den Bewegungseinstellungen übergehen. Die Hauptfunktion hier ist 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 von Maus, Tastatur und Screenreadern für diese Einstellungskomponente 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 das Symbol, das auf dem Weg zum nächsten Schieberegler war, ausgeblendet wurde. 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>

Darüber hinaus haben wir ausreichend eindeutig gekennzeichneten HTML-Code verwendet, sodass das Formular mit Maus, Tastatur, Videospiel-Controllern und Screenreadern wirklich gut getestet werden kann.

JavaScript

Wir haben bereits darüber gesprochen, wie die Track-Füllfarbe in JavaScript verwaltet wird. Sehen wir uns nun das <form>-bezogene JavaScript 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.

Community-Remixe

  • @tomayac durch den Stil in Bezug auf den Mouseoverbereich für die Kästchenlabels. In dieser Version gibt es keine Lücke zwischen den Elementen demo und source.