Komponente „Sidenav“ erstellen

Eine grundlegende Übersicht zum Erstellen einer responsiven ausblendbaren seitlichen Navigationsleiste

In diesem Beitrag möchte ich Ihnen zeigen, wie ich den Prototyp einer Sidenav-Komponente für das Web entwickelt habe, die responsiv, zustandsorientiert ist, die Tastaturnavigation unterstützt, mit und ohne JavaScript funktioniert und browserübergreifend funktioniert. Demo ansehen

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

Überblick

Es ist schwierig, ein responsives Navigationssystem zu entwickeln. Einige Nutzende verwenden eine Tastatur, andere leistungsstarke Desktops und andere ein kleines Mobilgerät. Jeder Besucher sollte das Menü öffnen und schließen können.

Responsives Layout von Computer zu Mobilgerät – Demo
Helles und dunkles Design für iOS und Android verringern

Webtaktik

Bei dieser Komponentenexploration kombinierte ich einige wichtige Webplattformfunktionen:

  1. Preisvergleichsportal :target
  2. CSS-Raster
  3. CSS-transforms
  4. CSS-Medienabfragen für Darstellungsbereich und Nutzereinstellungen
  5. JS für focus UX-Verbesserungen

Meine Lösung hat eine Seitenleiste und kann nur bei einem mobilen Darstellungsbereich von 540px oder weniger ein- und ausgeschaltet werden. 540px ist der Haltepunkt für den Wechsel zwischen dem interaktiven Layout für Mobilgeräte und dem statischen Desktop-Layout.

Pseudoklasse „:target“ für CSS

Ein <a>-Link setzt den URL-Hash auf #sidenav-open und den anderen auf leer (''). Schließlich enthält ein Element id, das mit dem Hash übereinstimmt:

<a href="#sidenav-open" id="sidenav-button" title="Open Menu" aria-label="Open Menu">

<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>

<aside id="sidenav-open">
  …
</aside>

Wenn ich auf jeden dieser Links klicke, ändert sich der Hash-Status unserer Seiten-URL. Mit einer Pseudoklasse blende ich dann die Sidenavigation ein und aus:

@media (max-width: 540px) {
  #sidenav-open {
    visibility: hidden;
  }

  #sidenav-open:target {
    visibility: visible;
  }
}

CSS-Raster

Früher habe ich nur Layouts und Komponenten mit absoluter oder fester Position verwendet. Mit der Syntax „ Grid“ mit seiner grid-area-Syntax können wir derselben Zeile oder Spalte mehrere Elemente zuweisen.

Stapel

Das primäre Layoutelement #sidenav-container ist ein Raster, das 1 Zeile und 2 Spalten erstellt, von denen eine den Namen stack hat. Bei begrenztem Platz ordnet CSS alle untergeordneten Elemente des <main>-Elements demselben Rasternamen zu. Alle Elemente werden dabei im selben Bereich platziert, wodurch ein Stapel entsteht.

#sidenav-container {
  display: grid;
  grid: [stack] 1fr / min-content [stack] 1fr;
  min-height: 100vh;
}

@media (max-width: 540px) {
  #sidenav-container > * {
    grid-area: stack;
  }
}

Das <aside> ist das animierte Element, das die seitliche Navigation enthält. Es hat zwei untergeordnete Elemente: den Navigationscontainer <nav> namens [nav] und einen Hintergrund-<a> mit dem Namen [escape], der zum Schließen des Menüs verwendet wird.

#sidenav-open {
  display: grid;
  grid-template-columns: [nav] 2fr [escape] 1fr;
}

Passen Sie 2fr und 1fr an, um das gewünschte Seitenverhältnis für das Menü-Overlay und die Schließen-Schaltfläche mit Negativraum zu finden.

Eine Demo dazu, was passiert, wenn Sie das Verhältnis ändern.

CSS-3D-Transformationen und -Übergänge

Unser Layout ist jetzt in der Größe eines mobilen Darstellungsbereichs gestapelt. Bis ich neue Stile hinzufüge, wird standardmäßig unser Artikel eingeblendet. Hier ist ein Teil der UX, auf die ich im nächsten Abschnitt fokussiere:

  • Öffnen und Schließen animieren
  • Animationen nur mit Bewegung dürfen nur dann animiert werden, wenn der Nutzer damit einverstanden ist.
  • visibility“ wird animiert, damit der Tastaturfokus nicht im Hintergrundelement zu sehen ist

Wenn ich mit der Implementierung von Bewegungsanimationen beginne, möchte ich mit der Barrierefreiheit beginnen.

Barrierefreie Bewegung

Nicht jeder wünscht sich ein Slide-out-Motion-Erlebnis. In unserer Lösung wird diese Einstellung angewendet, indem die CSS-Variable --duration in einer Medienabfrage angepasst wird. Dieser Medienabfragewert gibt an, wie ein Nutzer die Bewegung im Betriebssystem bevorzugt (falls verfügbar).

#sidenav-open {
  --duration: .6s;
}

@media (prefers-reduced-motion: reduce) {
  #sidenav-open {
    --duration: 1ms;
  }
}
Demo der Interaktion mit und ohne Anwendung der Dauer.

Wenn sich die seitliche Navigationsleiste auf- und zuklappen lässt und Nutzende reduzierte Bewegungselemente bevorzugen, verschiebe ich das Element sofort ins Sichtfeld. Dabei behält ich den Zustand ohne Bewegung bei.

Übergang, Transformation, Übersetzen

Seitliche Navigationsleiste heraus (Standard)

Um den Standardstatus der seitlichen Navigationsleiste auf Mobilgeräten in einen nicht sichtbaren Zustand zu versetzen, positioniere ich das Element mit transform: translateX(-110vw).

Hinweis: Ich habe dem typischen Code für außerhalb des sichtbaren Bildschirmbereichs von -100vw eine weitere 10vw hinzugefügt, damit die box-shadow der seitlichen Navigationsleiste nicht in den Hauptdarstellungsbereich eindringt, wenn er ausgeblendet ist.

@media (max-width: 540px) {
  #sidenav-open {
    visibility: hidden;
    transform: translateX(-110vw);
    will-change: transform;
    transition:
      transform var(--duration) var(--easeOutExpo),
      visibility 0s linear var(--duration);
  }
}
Seitenleiste in

Wenn das #sidenav-Element als :target übereinstimmt, legen Sie die Position translateX() auf die Homebase 0 fest und beobachten Sie, wie CSS das Element von seiner äußeren Position von -110vw in seine „In“-Position 0 über var(--duration) verschiebt, wenn der URL-Hash geändert wird.

@media (max-width: 540px) {
  #sidenav-open:target {
    visibility: visible;
    transform: translateX(0);
    transition:
      transform var(--duration) var(--easeOutExpo);
  }
}

Sichtbarkeit der Umstellung

Ziel ist es nun, das Menü vor Screenreadern zu verbergen, wenn es außerhalb des Bildschirms verfügbar ist, damit die Systeme den Fokus nicht auf ein nicht sichtbares Menü legen. Dazu lege ich einen Sichtbarkeitsübergang fest, wenn sich :target ändert.

  • Achten Sie beim Herangehen nicht darauf, die Sichtbarkeit zu ändern, sondern sofort sichtbar zu sein, damit das Element rutschen und den Fokus annehmen kann.
  • Beim Verlassen wird die Sichtbarkeit des Übergangs verzögert, sodass am Ende des Übergangs wieder hidden angezeigt wird.

UX-Verbesserungen für Barrierefreiheit

Bei dieser Lösung muss die URL geändert werden, damit der Status verwaltet wird. Natürlich sollte hier das Element <a> verwendet werden und es erhält kostenlos einige nützliche Bedienungshilfen. Dekorieren wir nun unsere interaktiven Elemente mit Labels, die die Absicht deutlich formulieren.

<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>

<a href="#sidenav-open" id="sidenav-button" class="hamburger" title="Open Menu" aria-label="Open Menu">
  <svg>...</svg>
</a>
Demo der UX für Voiceover und Tastaturinteraktion.

Jetzt geben unsere primären Interaktionsschaltflächen klar ihre Absicht für die Maus und die Tastatur an.

:is(:hover, :focus)

Mit diesem praktischen, funktionalen CSS-Funktions-Pseudoselektor können wir unsere Hover-Stile schnell integrativ darstellen, indem wir sie auch fokussieren.

.hamburger:is(:hover, :focus) svg > line {
  stroke: hsl(var(--brandHSL));
}

JavaScript verteilen

Zum Schließen escape drücken

Mit der Escape-Taste auf deiner Tastatur sollte das Menü geschlossen werden. Ist das richtig? Verkabeln wir das jetzt.

const sidenav = document.querySelector('#sidenav-open');

sidenav.addEventListener('keyup', event => {
  if (event.code === 'Escape') document.location.hash = '';
});
Browserverlauf

Um zu verhindern, dass bei der Interaktion vom Typ „Öffnen“ und „Schließen“ mehrere Einträge im Browserverlauf gestapelt werden, fügen Sie der Schließen-Schaltfläche den folgenden JavaScript-Code inline hinzu:

<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu" onchange="history.go(-1)"></a>

Dadurch wird beim Schließen der URL-Verlaufseintrag entfernt, als ob das Menü nie geöffnet worden wäre.

Fokus auf UX

Das nächste Snippet hilft uns, den Fokus auf die Schaltflächen zum Öffnen und Schließen zu legen. Ich möchte das Wechseln erleichtern.

sidenav.addEventListener('transitionend', e => {
  const isOpen = document.location.hash === '#sidenav-open';

  isOpen
      ? document.querySelector('#sidenav-close').focus()
      : document.querySelector('#sidenav-button').focus();
})

Wenn die seitliche Navigationsleiste geöffnet wird, fokussieren Sie die Schließen-Schaltfläche. Wenn sich die Navigationsleiste schließt, fokussieren Sie die Schaltfläche „Öffnen“. Dazu rufe ich focus() für das Element in JavaScript auf.

Fazit

Jetzt, wo du weißt, wie ich es gemacht habe, wie würdest du es tun?! Das sorgt für eine unterhaltsame Komponentenarchitektur! Wer erstellt die erste Version mit Slots? 🙂

Vielfältige Ansätze und verschiedene Möglichkeiten für das Web kennenlernen. Erstelle einen Glitch, twittere mich über deine Version und ich füge sie unten zum Abschnitt Community-Remixe hinzu.

Community-Remixe