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.
Webtaktik
Bei dieser Komponentenexploration kombinierte ich einige wichtige Webplattformfunktionen:
- 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 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;
}
}
Speisekarten-Hintergrund
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.
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;
}
}
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
Links
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>
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
- @_developit mit benutzerdefinierten Elementen: Demo und Code
- @mayeedwin1 mit HTML/CSS/JS: Demo und Code
- @a_nurella mit einem Glitch-Remix: Demo und Code
- @EvroMalarkey mit HTML/CSS/JS: Demo und Code