Grundlegende Übersicht zum Erstellen einer responsiven Slide-Out-Side-Navigation
In diesem Beitrag möchte ich Ihnen zeigen, wie ich einen 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 Sie Videos bevorzugen, finden Sie hier eine YouTube-Version dieses Beitrags:
Überblick
Es ist nicht einfach, ein reaktionsschnelles Navigationssystem zu entwickeln. Einige Nutzer arbeiten mit einer Tastatur, andere haben einen leistungsstarken Desktop-Computer und wieder andere nutzen ein kleines Mobilgerät. Alle Besucher sollten das Menü öffnen und schließen können.
Webtaktik
In dieser explorativen Datenanalyse habe ich einige wichtige Webplattformfunktionen kombiniert:
- Preisvergleichsportal
:target
- CSS-Raster
- CSS-transforms
- CSS-Medienabfragen für Darstellungsbereich und Nutzereinstellungen
- JS für
focus
UX-Verbesserungen
Meine Lösung hat eine Seitenleiste und kann nur umgeschaltet werden, wenn sie sich in einem mobilen Darstellungsbereich von 540px
oder weniger befindet.
540px
ist unser Haltepunkt für den Wechsel zwischen dem interaktiven Layout für Mobilgeräte und dem statischen Desktop-Layout.
CSS-:target
-Pseudoklasse
Ein <a>
-Link setzt den URL-Hash auf #sidenav-open
und der andere auf leer (''
).
Schließlich verfügt ein Element über die id
, die 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 Sie auf jeden dieser Links klicken, ändert sich der Hash-Status der Seiten-URL. Mit einer Pseudoklasse blende ich die Sidenav ein und aus:
@media (max-width: 540px) {
#sidenav-open {
visibility: hidden;
}
#sidenav-open:target {
visibility: visible;
}
}
CSS-Raster
Früher habe ich nur absolute oder feste
SideNav-Layouts und -Komponenten verwendet. Mit „Grid“ können wir mit seiner grid-area
-Syntax derselben Zeile oder Spalte mehrere Elemente zuweisen.
Stapel
Das primäre Layoutelement #sidenav-container
ist ein Raster, das eine Zeile und zwei Spalten erstellt, von denen jeweils eine den Namen stack
hat. Wenn der Platz beschränkt ist, weist CSS alle untergeordneten Elemente des <main>
-Elements demselben Rasternamen zu. Dadurch werden alle Elemente im selben Bereich platziert und es wird ein Stapel erstellt.
#sidenav-container {
display: grid;
grid: [stack] 1fr / min-content [stack] 1fr;
min-height: 100vh;
}
@media (max-width: 540px) {
#sidenav-container > * {
grid-area: stack;
}
}
Menühintergrund
<aside>
ist das Animationselement, das die seitliche Navigationsleiste enthält. Sie hat zwei untergeordnete Elemente: den Navigationscontainer <nav>
namens [nav]
und einen Hintergrund-<a>
namens [escape]
, mit dem das Menü geschlossen wird.
#sidenav-open {
display: grid;
grid-template-columns: [nav] 2fr [escape] 1fr;
}
Passe 2fr
und 1fr
an, um das gewünschte Seitenverhältnis für das Menü-Overlay und die Schließen-Schaltfläche mit Negativraum festzulegen.
CSS-3D-Transformationen und -Übergänge
Unser Layout ist jetzt für die Größe eines mobilen Darstellungsbereichs gestapelt. Bis ich neue Stile hinzugefügt habe, überlagert es standardmäßig unseren Artikel. Hier sind einige UX-Designs, auf die ich im nächsten Abschnitt stehe:
- Öffnen und Schließen animieren
- Nur mit Bewegung animieren, wenn der Nutzer damit einverstanden ist
- Animieren Sie „
visibility
“, damit der Tastaturfokus nicht in das nicht sichtbare Element eindringt
Wenn ich mit der Implementierung von Bewegungsanimationen beginne, steht die Barrierefreiheit an erster Stelle.
Barrierefreie Bewegung
Nicht jeder wünscht sich eine rutschende Bewegung. In unserer Lösung wird diese Einstellung angewendet, indem die CSS-Variable --duration
in einer Medienabfrage angepasst wird. Dieser Medienabfragewert repräsentiert die Betriebssystempräferenz eines Nutzers für Bewegung (falls verfügbar).
#sidenav-open {
--duration: .6s;
}
@media (prefers-reduced-motion: reduce) {
#sidenav-open {
--duration: 1ms;
}
}
Wenn die seitliche Navigationsleiste geöffnet und geschlossen wird und ein Nutzer eine geringere Bewegung vorzieht, verschiebe ich das Element sofort in den sichtbaren Zustand. Der Zustand bleibt ohne Bewegung erhalten.
Übergang, Transformieren, Übersetzen
Seitliche Navigationsleiste (Standard)
Um den Standardstatus der Sidenav-Navigation auf Mobilgeräten zu deaktivieren, platziere ich das Element mit transform: translateX(-110vw)
.
Hinweis: Ich habe dem typischen Off-Screen-Code von -100vw
ein weiteres 10vw
hinzugefügt, damit die box-shadow
der seitlichen Navigationsleiste nicht in den Hauptdarstellungsbereich eingeblendet wird, wenn dieser 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);
}
}
Sidenav in
Wenn das #sidenav
-Element mit :target
übereinstimmt, legen Sie die translateX()
-Position auf die Homebase 0
fest und beobachten Sie, wie CSS das Element von seiner Außenposition von -110vw
zu seiner "In"-Position von 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
Das Ziel ist nun, das Menü vor Screenreadern zu verbergen, wenn es außer Haus ist, damit Systeme den Fokus nicht auf ein nicht sichtbares Menü fokussieren. Dazu lege ich einen Sichtbarkeitsübergang fest, wenn sich :target
ändert.
- Beim Eingehen sollte keine Übergangssichtbarkeit erfolgen. Sie sollten sofort sichtbar sein, damit ich sehen kann, dass sich das Element öffnet und der Fokus akzeptiert wird.
- Beim Ausgehen wird der Übergang mit der Sichtbarkeit verzögert, sodass er am Ende des Übergangs zu
hidden
wechselt.
UX-Verbesserungen der Barrierefreiheit
Links
Diese Lösung stützt sich auf das Ändern der URL, damit der Status verwaltet wird.
Natürlich sollte hier das Element <a>
verwendet werden, das einige nützliche Bedienungshilfen kostenlos erhält. Wir zeichnen unsere interaktiven Elemente mit Beschriftungen aus, die die Absicht klar artikulieren.
<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>
Jetzt geben unsere primären Interaktionsschaltflächen sowohl für die Maus als auch für die Tastatur klar ihre Absicht an.
:is(:hover, :focus)
Mit diesem praktischen CSS-Funktions-Pseudoselektor können wir unsere Hover-Stile schnell einbeziehen, indem wir sie auch mit Fokus teilen.
.hamburger:is(:hover, :focus) svg > line {
stroke: hsl(var(--brandHSL));
}
JavaScript verwenden
Zum Schließen escape
drücken
Mit der Taste „Escape
“ 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
Damit beim Öffnen und Schließen nicht mehrere Einträge im Browserverlauf gestapelt werden, fügen Sie der Schließen-Schaltfläche folgenden JavaScript-Code inline hinzu:
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu" onchange="history.go(-1)"></a>
Dadurch wird der URL-Verlauf beim Schließen entfernt, sodass es so aussieht, als wäre das Menü nie geöffnet worden.
Fokus auf UX legen
Mit dem nächsten Snippet wird der Fokus auf die Öffnen- und Schließen-Schaltflächen gelegt. Ich möchte das Wechseln einfach machen.
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 Schaltfläche zum Schließen. Wenn die seitliche Navigationsleiste geschlossen wird,
fokussieren Sie die Schaltfläche zum Öffnen. Dazu rufe ich in JavaScript focus()
für das Element auf.
Fazit
Jetzt, da du weißt, wie ich das gemacht habe, wie würdest du es tun?! So entsteht eine unterhaltsame Komponentenarchitektur! Wer erstellt die erste Version mit Slots? 🙂
Lassen Sie uns unsere Ansätze diversifizieren und alle Möglichkeiten kennenlernen, wie wir das Web entwickeln können. Erstelle einen Glitch, twittere mir deine Version und füge sie dem Abschnitt Community-Remixe unten hinzu.
Community-Remixe
- @_developit mit benutzerdefinierten Elementen: Demo und Code
- @mayeedwin1 mit HTML/CSS/JS: Demo und Code
- @a_nurella mit Glitch-Remix: Demo und Code
- @EvroMalarkey mit HTML/CSS/JS: Demo und Code