In diesem Codelab erfahren Sie, wie Sie eine responsive, ausziehbare Navigationsleiste im Web erstellen. Wir erstellen die Komponente nach und nach, beginnend mit HTML, dann CSS und zuletzt JavaScript.
In meinem Blogpost Building a Sidenav component (Eine Seitenleiste erstellen) erfahren Sie mehr über die Funktionen der CSS-Webplattform, die für die Erstellung dieser Komponente ausgewählt wurden.
Einrichtung
- Klicke auf Remix zum Bearbeiten, um das Projekt bearbeitbar zu machen.
- Öffnen Sie
app/index.html
.
HTML
Machen Sie sich zuerst mit den Grundlagen der HTML-Einrichtung vertraut, damit Sie Inhalte und Felder zum Arbeiten haben.
Fügen Sie den folgenden HTML-Code in das <body>
-Tag ein.
<aside></aside>
<main></main>
Das <aside>
enthält das Navigationsmenü als ergänzendes Element zu <main>
, das den Hauptinhalt der Seite enthält.
Als Nächstes füllen wir diese semantischen Elemente mit dem Rest des Seiteninhalts aus.
Fügen Sie dem <aside>
-Element ein Navigationselement, einige Navigationslinks und einen Schließen-Link hinzu.
<aside>
<nav>
<h4>My</h4>
<a href="#">Dashboard</a>
<a href="#">Profile</a>
<a href="#">Preferences</a>
<a href="#">Archive</a>
<h4>Settings</h4>
<a href="#">Accessibility</a>
<a href="#">Theme</a>
<a href="#">Admin</a>
</nav>
<a href="#"></a>
</aside>
Links eignen sich hervorragend für <nav>
-Elemente und <nav>
-Elemente für <aside>
-Seitenleisten.
Es gibt aber noch Verbesserungsmöglichkeiten.
Fügen Sie dem Hauptinhaltselement eine Überschrift und einen Artikel hinzu, um den Layoutinhalt semantisch zu speichern.
<main>
<header>
<a href="#sidenav-open" class="hamburger">
<svg viewBox="0 0 50 40">
<line x1="0" x2="100%" y1="10%" y2="10%" />
<line x1="0" x2="100%" y1="50%" y2="50%" />
<line x1="0" x2="100%" y1="90%" y2="90%" />
</svg>
</a>
<h1>Site Title</h1>
</header>
<article>
{put some placeholder content here}
</article>
</main>
In der Überschrift befindet sich der Link zum Öffnen des Menüs. In der Seitenleiste befindet sich die Schaltfläche „Schließen“. Bald werden Elemente basierend auf der Größe des Darstellungsbereichs angezeigt und ausgeblendet.
Im <article>
-Element haben wir einen Platzhaltersatz eingefügt. Ersetzen Sie „“ durch Ihre eigenen Inhalte oder fügen Sie das unten stehende Lorem ipsum ein:
<h2>Totam Header</h2>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cum consectetur, necessitatibus velit officia ut impedit veritatis temporibus soluta? Totam odit cupiditate facilis nisi sunt hic necessitatibus voluptatem nihil doloribus! Enim.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<h3>Subhead Totam Odit</h3>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<h3>Subhead</h3>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
Diese Inhalte und ihre Länge führen dazu, dass die Seite scrollbar ist, wenn sie die Höhe des Darstellungsbereichs überschreitet.
Bisher haben Sie ein Seitenelement mit einer Navigationsleiste, Links und einer Möglichkeit zum Schließen der Seitenleiste hinzugefügt. Außerdem haben Sie dem Hauptelement eine Überschrift, eine Möglichkeit zum Öffnen der Seitenleiste und einen Artikel hinzugefügt. Das Design ist bereits klar, semantisch und ziemlich zeitlos, aber wir können es für alle noch übersichtlicher und klarer gestalten. Der geöffnete Link in der Seitenleiste könnte deutlicher gekennzeichnet werden.
Fügen Sie dem Element „header open link“ die Attribute title
und aria-label
hinzu:
<a href="#sidenav-open" class="hamburger">
<a href="#sidenav-open" title="Open Menu" aria-label="Open Menu" class="hamburger">
Das Symbol für geöffnete SVG-Dateien könnte auch deutlicher gekennzeichnet sein. Fügen Sie dem SVG innerhalb des Elements „open link“ die folgenden Attribute hinzu:
<svg viewBox="0 0 50 40">
<svg viewBox="0 0 50 40" role="presentation" focusable="false" aria-label="trigram for heaven symbol">
Der Link zum Schließen in der Seitenleiste könnte deutlicher gekennzeichnet sein.
Fügen Sie dem Link-Element zum Schließen der Seitenleiste die Attribute title
und aria-label
hinzu:
<a href="#"></a>
<a href="#" title="Close Menu" aria-label="Close Menu"></a>
CSS
Jetzt ist es an der Zeit, die Elemente anzuordnen. Der Hauptinhalt und die Seitenleiste sind direkt untergeordnet und daher ein guter Ausgangspunkt.<body>
Fügen Sie css/sidenav.css
das folgende CSS hinzu, damit die untergeordneten Elemente vom <body>
-Element angeordnet werden.
body {
display: grid;
grid: [stack] 1fr / min-content [stack] 1fr;
@media (max-width: 540px) {
& > :matches(aside, main) {
grid-area: stack;
}
}
}
Dieses Layout bedeutet im Wesentlichen: Erstellen Sie eine benannte Zeile stack
mit allen Inhalten und zwei Spalten in dieser Zeile, von denen die zweite ebenfalls stack
heißt. Die Größe der ersten Spalte sollte an den minimalen Inhaltsanforderungen ausgerichtet sein. Die zweite Spalte kann den Rest einnehmen.
Wenn der Darstellungsbereich auf 540px
oder weniger begrenzt ist, platzieren Sie die Elemente der Seitenleiste und des Hauptinhalts in derselben Zeile und Spalte, sodass sie sich in einem 1 × 1-Raster überschneiden.
Auf dieser responsiven Stapelfunktion aufbauend können wir jetzt den Status der URL-Leiste nutzen, um die Sichtbarkeit und den Übergangsstil der Seitenleiste umzuschalten.
Aktualisieren Sie das <aside>
-Element in app/index.html
:
<aside>
<aside id="sidenav-open">
So kann CSS ein Element und den URL-Hash miteinander abgleichen. Das ist wichtig für die Nutzung von :target
.
Jetzt kann die ID des Elements mit dem URL-Hash übereinstimmen, den wir mit <a>
-Tags festlegen.
Fügen Sie außerdem für ein einfacheres JavaScript-Targeting IDs für wichtige Elemente hinzu, die die Seitenleiste steuern. Fügen Sie zuerst dem Link zum Öffnen der Seitenleiste eine ID hinzu:
<a href="#sidenav-open" class="hamburger" title="Open Menu" aria-label="Open Menu">
<a href="#sidenav-open" id="sidenav-button" class="hamburger" title="Open Menu" aria-label="Open Menu">
Fügen Sie als Nächstes dem Link zum Schließen der Seitenleiste eine ID hinzu:
<a href="#" title="Close Menu" aria-label="Close Menu"></a>
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>
Damit ist das responsive Stapellayout für das Makro <body>
abgeschlossen und wir sind wieder bei der URL-Leiste.
Weiter geht's!
Auch das <aside>
hat ein schönes Layout. Es hat zwei untergeordnete Elemente: ein <nav>
, die papierartige Komponente, die herausgeschoben wird, und ein schließendes <a>
-Linkelement, das die URL auf #
festlegt.
Der Link ist rechts neben der ausziehbaren Navigationsleiste nicht sichtbar. So können Nutzer die visuelle Komponente „ausklicken“, um sie zu schließen.
Fügen Sie css/sidenav.css
das folgende CSS hinzu:
#sidenav-open {
display: grid;
grid-template-columns: [nav] 2fr [escape] 1fr;
}
Ich fand das Verhältnis und die Namen hier sehr gelungen, da das Raster hier gut zur Geltung kommt und dem Designer viel Kontrolle bietet.
Als Nächstes muss ich den Hauptinhalt bedingt überlagern und meine Position beim Scrollen im Dokument beibehalten. Das ist eine tolle Stelle für position: sticky
und ein bisschen overscroll-behavior
.
Fügen Sie die folgenden Stile für die Seitenleiste hinzu:
#sidenav-open {
display: grid;
grid-template-columns: [nav] 2fr [escape] 1fr;
@media (max-width: 540px) {
position: sticky;
top: 0;
max-height: 100vh;
overflow: hidden auto;
overscroll-behavior: contain;
visibility: hidden; /* not keyboard accessible when closed */
}
}
Diese Stile sorgen dafür, dass die Seitenleiste die Höhe des Darstellungsbereichs hat, vertikal scrollt und das Scrollen enthält. Das Element wird ausgeblendet. Wenn der Darstellungsbereich 540px
oder kleiner ist, wird die Seitenleiste standardmäßig ausgeblendet. Es sei denn…
Fügen Sie dem Element #sidenav-open
einen :target
-Pseudoselektor hinzu:
#sidenav-open {
@media (max-width: 540px) {
&:target {
visibility: visible;
}
}
}
Wenn die ID dieses Elements mit der URL-Leiste übereinstimmt, setzen Sie visibility
auf visible
. Öffnen Sie das seitliche Menü, nachdem Sie auf der Seite gescrollt haben, oder scrollen Sie auf der Seite, während die Seitenleiste geöffnet ist. Was ist Ihre Meinung dazu?
Fügen Sie unten in app/sidenav.css
das folgende CSS hinzu:
#sidenav-button,
#sidenav-close {
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
user-select: none;
touch-action: manipulation;
@media (min-width: 540px) {
display: none;
}
}
Diese Stile sind auf unsere Schaltflächen zum Öffnen und Schließen ausgerichtet, geben ihre Tipp- und Touch-Stile an und blenden sie aus, wenn die Ansichten 540px
oder größer sind.
Fügen wir für etwas Flair CSS-Transformationen mit Berücksichtigung der Barrierefreiheit hinzu.
Fügen Sie css/sidenav.css
das folgende CSS hinzu:
#sidenav-open {
--easeOutExpo: cubic-bezier(0.16, 1, 0.3, 1);
--duration: .6s;
...
@media (max-width: 540px) {
...
transform: translateX(-110vw);
will-change: transform;
transition:
transform var(--duration) var(--easeOutExpo),
visibility 0s linear var(--duration);
&:target {
visibility: visible;
transform: translateX(0);
transition: transform var(--duration) var(--easeOutExpo);
}
}
@media (prefers-reduced-motion: reduce) {
--duration: 1ms;
}
}
Ein bisschen JavaScript
Mit der Taste Escape
sollte das Menü geschlossen werden. Fügen Sie js/index.js
dieses JS hinzu:
const sidenav = document.querySelector('#sidenav-open');
sidenav.addEventListener('keyup', e => {
if (e.code === 'Escape') {
document.location.hash = '';
}
});
Hier wird auf ein Schlüsselereignis im Sidenav-Element gewartet.
Wenn der Wert Escape
ist, wird der URL-Hash auf leer gesetzt, wodurch die Seitenleiste ausgeblendet wird.
Der nächste Teil von UX JS ist die Fokusverwaltung. Ich möchte das Öffnen und Schließen so einfach wie möglich gestalten. Deshalb warte ich, bis die Seitenleiste eine Art Übergang abgeschlossen hat, und prüfe dann anhand des URL-Hashes, ob sie eingeblendet oder ausgeblendet ist. Anschließend verwende ich JavaScript, um den Fokus auf die Schaltfläche zu legen, die dem Nutzer gerade angezeigt wurde.
Fügen Sie js/index.js
das folgende JavaScript hinzu:
const closenav = document.querySelector('#sidenav-close');
const opennav = document.querySelector('#sidenav-button');
sidenav.addEventListener('transitionend', e => {
if (e.propertyName !== 'transform') {
return;
}
const isOpen = document.location.hash === '#sidenav-open';
isOpen
? closenav.focus()
: opennav.focus();
});
Jetzt ausprobieren
- Wenn Sie sich eine Vorschau der Website ansehen möchten, drücken Sie App ansehen und dann Vollbild .
Fazit
Das war es mit meinen Anforderungen an die Komponente. Du kannst sie gerne erweitern, mit JavaScript-Status anstelle der URL ausführen und sie im Allgemeinen nach deinen Wünschen anpassen. Es gibt immer mehr zu ergänzen oder weitere Anwendungsfälle zu behandeln.
Öffnen Sie css/brandnav.css
, um sich die nicht layoutbezogenen Stile anzusehen, die ich auf diese Komponente angewendet habe. Ich fand es für die Funktionen, auf die ich mich konzentrierte, nicht wichtig und hoffte, dass die Trennung von Stilen und Layout das Kopieren und Einfügen fördern würde. Dort gibt es möglicherweise noch mehr zu lernen.
Wie erstelle ich ausziehbare responsive Seitenleisten? Haben Sie manchmal mehr als eine, z. B. eine auf beiden Seiten? Ich würde deine Lösung gerne in einem YouTube-Video vorstellen. Tweete mir einfach deinen Code oder kommentiere ihn in einem YouTube-Video. Das hilft uns allen weiter.