Komponente für unverankerte Aktionsschaltflächen erstellen

Ein grundlegender Überblick über die Erstellung von farbanpassungsfähigen, responsiv und barrierefrei zugänglichen FAB-Komponenten.

In diesem Beitrag möchte ich meine Gedanken zum Erstellen von farbanpassungsfähigen, reaktionsschnellen und barrierefreien FAB-Komponenten teilen. Probieren Sie die Demo aus und sehen Sie sich den Quellcode an.

Falls du lieber ein Video hast, findest du hier eine YouTube-Version dieses Beitrags:

Überblick

FABs sind auf Mobilgeräten häufiger als auf Computern zu finden, kommen aber in beiden Szenarien vor. Sie behalten die wichtigsten Aktionen im Blick und sind daher praktisch und allgegenwärtig. Dieser Stil wurde durch Material UI bekannt gemacht. Die Vorschläge zur Verwendung und Platzierung finden Sie hier.

Elemente und Stile

Der HTML-Code für diese Steuerelemente umfasst ein Containerelement und eine oder mehrere Schaltflächen. Der Container positioniert die FABs im Darstellungsbereich und verwaltet eine Lücke zwischen den Schaltflächen. Es gibt Mini- oder Standardschaltflächen, die für eine gute Abwechslung zwischen primären und sekundären Aktionen sorgen.

UAS-Container

Dieses Element kann ein reguläres <div>-Element sein. Wir wollen unseren nicht gesehenen Nutzern aber einen Gefallen tun und es mit nützlichen Attributen kennzeichnen, um den Zweck und den Inhalt dieses Containers zu erläutern.

UAS-Markup

Beginnen Sie mit einer .fabs-Klasse, in die CSS eingebunden werden kann, um den Stil zu verknüpfen. Fügen Sie dann role="group" und aria-label hinzu, damit es nicht nur ein generischer Container ist, sondern auch benannt und zielgerichtet ist.

<div class="fabs" role="group" aria-label="Floating action buttons">
  <!-- buttons will go here -->
</div>

FAB-Stil

Damit FABs immer praktisch sind, bleiben sie immer im Darstellungsbereich. Dies ist ein guter Anwendungsfall für die Position fixed. Innerhalb dieser Position des Darstellungsbereichs habe ich inset-block und inset-inline verwendet, damit die Position den Dokumentmodus des Nutzers ergänzt, z. B. von rechts nach links oder von links nach rechts. Benutzerdefinierte Eigenschaften werden auch verwendet, um Wiederholungen zu vermeiden und für einen gleichmäßigen Abstand von den unteren und seitlichen Rändern des Darstellungsbereichs zu sorgen:

.fabs {
  --_viewport-margin: 2.5vmin;

  position: fixed;
  z-index: var(--layer-1);

  inset-block: auto var(--_viewport-margin);
  inset-inline: auto var(--_viewport-margin);
}

Als Nächstes gebe ich dem Containerdisplay flex an und ändere die Layoutrichtung in column-reverse. Dadurch werden die untergeordneten Elemente übereinander (Spalte) gestapelt und auch ihre visuelle Reihenfolge umgekehrt. Dadurch wird das erste fokussierbare Element zum unteren und nicht zum oberen Element, wo der Fokus normalerweise im HTML-Dokument liegt. Durch das Umkehren der visuellen Reihenfolge wird das Erlebnis für sehende Nutzer und Tastaturnutzer vereinigt, da sehende Nutzer erkennen können, dass es sich um eine primäre Aktion handelt.

Es sind zwei „Fab“-Schaltflächen zu sehen, bei denen die Entwicklertools über ihr Rasterlayout gelegt sind. Zeigt den Abstand zwischen ihnen mit einem gestreiften Muster sowie die berechnete Höhe und Breite an.

.fabs {
  …

  display: flex;
  flex-direction: column-reverse;
  place-items: center;
  gap: var(--_viewport-margin);
}

Die Zentrierung erfolgt mit place-items und gap fügt Platz zwischen den im Container platzierten UAS-Schaltflächen hinzu.

UAS-Schaltflächen

Zeit, einige Schaltflächen so zu gestalten, dass sie so aussehen, als würden sie über alles schwebend aussehen.

Standard-FAB

Die erste zu formatierende Schaltfläche ist die Standardschaltfläche. Diese dient als Grundlage für alle FAB-Schaltflächen. Später erstellen wir eine Variante, die eine alternative Darstellung erzielt und dabei so wenig dieser Basisstile wie möglich anpasst.

UAS-Markup

Das <button>-Element ist die richtige Wahl. Wir beginnen damit, weil es eine hervorragende User Experience bietet, z. B. mit Maus, Touch und Tastatur. Am wichtigsten bei diesem Markup ist es, das Symbol für Nutzer von Screenreadern mit aria-hidden="true" auszublenden und den erforderlichen Labeltext zum <button>-Markup selbst hinzuzufügen. Wenn ich in diesen Fällen Labels hinzufüge, füge ich auch gerne title hinzu, damit Mausnutzer Informationen darüber erhalten können, was das Symbol kommunizieren soll.

<button data-icon="plus" class="fab" title="Add new action" aria-label="Add new action">
  <svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24">...</svg>
</button>

UAS-Stil

Wandeln wir die Schaltfläche zuerst in eine gepolsterte runde Schaltfläche mit einem starken Schatten um, da dies die ersten Elemente der Schaltfläche sind:

.fab {
  --_size: 2rem;

  padding: calc(var(--_size) / 2);
  border-radius: var(--radius-round);
  aspect-ratio: 1;
  box-shadow: var(--shadow-4);
}

Als Nächstes fügen wir Farbe hinzu. Wir verwenden eine Strategie, die wir bereits bei GUI-Herausforderungen genutzt haben. Erstellen Sie einen klar benannten Satz benutzerdefinierter Eigenschaften, die statisch die hellen und dunklen Farben enthalten, und dann eine adaptive benutzerdefinierte Eigenschaft, für die je nach Systempräferenz des Nutzers für Farben entweder die hellen oder die dunklen Variablen festgelegt werden:

.fab {
  …

  /* light button and button hover */
  --_light-bg: var(--pink-6);
  --_light-bg-hover: var(--pink-7);

  /* dark button and button hover */
  --_dark-bg: var(--pink-4);
  --_dark-bg-hover: var(--pink-3);

  /* adaptive variables set to light by default */
  --_bg: var(--_light-bg);

  /* static icon colors set to the adaptive foreground variable */
  --_light-fg: white;
  --_dark-fg: black;
  --_fg: var(--_light-fg);

  /* use the adaptive properties on some styles */
  background: var(--_bg);
  color: var(--_fg);

  &:is(:active, :hover, :focus-visible) {
    --_bg: var(--_light-bg-hover);

    @media (prefers-color-scheme: dark) {
      --_bg: var(--_dark-bg-hover);
    }
  }

  /* if users prefers dark, set adaptive props to dark */
  @media (prefers-color-scheme: dark) {
    --_bg: var(--_dark-bg);
    --_fg: var(--_dark-fg);
  }
}

Als Nächstes fügen Sie einige Stile hinzu, damit die SVG-Symbole in den Raum passen.

.fab {
  …

  & > svg {
    inline-size: var(--_size);
    block-size: var(--_size);
    stroke-width: 3px;
  }
}

Entfernen Sie zuletzt die Markierung beim Tippen aus der Schaltfläche, da wir eigenes visuelles Feedback für die Interaktion hinzugefügt haben:

.fab {
  -webkit-tap-highlight-color: transparent;
}

Mini-FAB

In diesem Bereich soll eine Variante für die UAS-Schaltfläche erstellt werden. Indem wir einige der FABs kleiner als die Standardaktion machen, können wir die Aktion fördern, die der Nutzer am häufigsten ausführt.

Mini-UAS-Markup

Der HTML-Code ist mit einem FAB identisch. Wir fügen jedoch eine „.mini“-Klasse hinzu, um CSS einen Hook für die Variante zu geben.

<button data-icon="heart" class="fab mini" title="Like action" aria-label="Like action">
  <svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24">...</svg>
</button>
Mini-FAB-Stil

Dank benutzerdefinierter Eigenschaften muss nur die Variable --_size angepasst werden.

.fab.mini {
  --_size: 1.25rem;
}

Ein Screenshot mit den beiden übereinander angeordneten Fab-Tasten, wobei die obere Taste kleiner ist als die untere.

Barrierefreiheit

Der wichtigste Aspekt für die Barrierefreiheit bei FABs ist die Platzierung im Tastaturablauf der Seite. In dieser Demo werden nur die FABs verwendet. Es gibt nichts, mit dem in Bezug auf Tastaturreihenfolge und -ablauf konkurriert wird, was bedeutet, dass keine Gelegenheit besteht, einen sinnvollen Tastaturablauf zu zeigen. In einem Szenario, in dem es konkurrierende Elemente gibt, sollte ich gründlich überlegen, an welcher Stelle in diesem Ablauf ein Nutzer in den FAB-Schaltflächenablauf eintreten sollte.

Demonstration einer Tastaturinteraktion

Sobald sich der Nutzer auf den FAB-Container konzentriert hat, haben wir role="group" und aria-label="floating action buttons" hinzugefügt, um Nutzer von Screenreadern über die Inhalte zu informieren, auf die sie sich konzentrieren. Ich habe den Standard-FAB strategisch an erster Stelle platziert, damit Nutzende die primäre Aktion zuerst finden. Anschließend verwende ich flex-direction: column-reverse;, um die primäre Schaltfläche unten optisch in der Nähe der Finger der Nutzer zu ordnen, um den Zugriff zu erleichtern. Das ist ein netter Vorteil, da die Standardschaltfläche optisch hervorgehoben und für Tastaturnutzer an erster Stelle steht, sodass sie sich sehr ähnlich sehen.

Vergessen Sie nicht, Ihre Symbole vor Screenreader-Nutzern zu verbergen und ihnen ein Label für die Schaltfläche zu geben, damit dies kein Geheimnis bleibt. Dies wurde im HTML-Code bereits mit aria-hidden="true" bei den <svg> und aria-label="Some action" bei den <button>-Elementen durchgeführt.

Animation

Es können verschiedene Arten von Animationen hinzugefügt werden, um die User Experience zu verbessern. Wie bei anderen GUI-Herausforderungen werden auch hier einige benutzerdefinierte Eigenschaften eingerichtet, die sowohl eine reduzierte als auch eine vollständige Bewegungserfahrung enthalten. Standardmäßig wird bei den Stilen davon ausgegangen, dass der Nutzer eine reduzierte Bewegung wünscht. Mit der prefers-reduced-motion-Medienabfrage wird der Übergangswert dann in eine vollständige Bewegung geändert.

Strategie mit reduzierten Bewegungen mit benutzerdefinierten Eigenschaften

Im folgenden CSS werden drei benutzerdefinierte Eigenschaften erstellt: --_motion-reduced, --_motion-ok und --_transition. Für die ersten beiden gelten je nach Nutzereinstellung geeignete Übergänge. Die letzte Variable --_transition wird auf --_motion-reduced bzw. --_motion-ok gesetzt.

.fab {
  /* box-shadow and background-color can safely be transitioned for reduced motion users */
  --_motion-reduced:
    box-shadow .2s var(--ease-3),
    background-color .3s var(--ease-3);

  /* add transform and outline-offset for users ok with motion */
  --_motion-ok:
    var(--_motion-reduced),
    transform .2s var(--ease-3),
    outline-offset 145ms var(--ease-2);

  /* default the transition styles to reduced motion */
  --_transition: var(--_motion-reduced);

  /* set the transition to our adaptive transition custom property*/
  transition: var(--_transition);

  /* if motion is ok, update the adaptive prop to the respective transition prop */
  @media (prefers-reduced-motion: no-preference) {
    --_transition: var(--_motion-ok);
  }
}

Mit den oben genannten Änderungen können Änderungen an box-shadow, background-color, transform und outline-offset umgestellt werden. So erhält der Nutzer positives Feedback auf der Benutzeroberfläche, dass die Interaktion eingegangen ist.

Als Nächstes verleihen Sie dem :active-Status ein wenig mehr Flair. Passen Sie dafür translateY ein wenig an. So wirkt die Schaltfläche positiv:

.fab {
  …

  &:active {
    @media (prefers-reduced-motion: no-preference) {
      transform: translateY(2%);
    }
  }
}

Abschließend müssen Sie alle Änderungen an den SVG-Symbolen in den Schaltflächen vornehmen:

.fab {
  …

  &[data-icon="plus"]:hover > svg {
    transform: rotateZ(.25turn);
  }

  & > svg {
    @media (prefers-reduced-motion: no-preference) {
      will-change: transform;
      transition: transform .5s var(--ease-squish-3);
    }
  }
}

Fazit

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

Hier gibt es noch nichts zu sehen.

Ressourcen