Questo codelab ti insegna a creare un componente di layout di navigazione laterale scorrevole adattabile sul web. Lo creeremo man mano, iniziando con HTML, poi CSS e infine JavaScript.
Dai un'occhiata al mio post del blog Creare un componente Sidenav per scoprire le funzionalità della piattaforma web CSS scelte per la creazione di questo componente.
Configurazione
- Fai clic su Remix per modificare per rendere il progetto modificabile.
- Apri
app/index.html
.
HTML
Innanzitutto, acquisisci le nozioni di base della configurazione HTML in modo da avere contenuti e alcune caselle con cui lavorare.
Inserisci il seguente codice HTML nel tag <body>
.
<aside></aside>
<main></main>
<aside>
contiene il menu di navigazione come elemento complementare a <main>
, che contiene i contenuti della pagina principale.
Successivamente, completeremo questi elementi semantici con il resto dei contenuti della pagina.
Aggiungi un elemento di navigazione, alcuni link di navigazione e un link di chiusura all'interno dell'elemento <aside>
.
<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>
I link sono ideali all'interno degli elementi <nav>
, mentre gli elementi <nav>
sono ideali nelle barre laterali <aside>
.
Tuttavia, possiamo fare di più per migliorare.
Nell'elemento di contenuto principale, aggiungi un'intestazione e un articolo per contenere semanticamente i contenuti del layout.
<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>
L'intestazione contiene il link per aprire il menu. Il riquadro contiene il pulsante di chiusura. A breve mostreremo e nasconderemo gli elementi in base alle dimensioni del viewport.
Nell'elemento <article>
abbiamo incollato una frase segnaposto. Sostituisci " con i tuoi contenuti o incolla il lorem fornito di seguito:
<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>
Questi contenuti e la loro lunghezza fanno sì che la pagina sia scorrevole quando supera l'altezza dell'area visibile.
Finora hai aggiunto un elemento aside, con un menu di navigazione, link e un modo per chiudere il riquadro di navigazione laterale. Hai anche aggiunto un'intestazione, un modo per aprire il riquadro laterale e un articolo all'elemento principale. È già pulito, semantico e piuttosto senza tempo, ma possiamo renderlo più pulito e chiaro per tutti. Il link aperto nel riquadro laterale potrebbe essere contrassegnato in modo più chiaro.
Aggiungi gli attributi title
e aria-label
all'elemento link di apertura dell'intestazione:
<a href="#sidenav-open" class="hamburger">
<a href="#sidenav-open" title="Open Menu" aria-label="Open Menu" class="hamburger">
Anche l'icona SVG aperta potrebbe essere contrassegnata in modo più chiaro. Aggiungi i seguenti attributi all'elemento SVG all'interno dell'elemento link aperto:
<svg viewBox="0 0 50 40">
<svg viewBox="0 0 50 40" role="presentation" focusable="false" aria-label="trigram for heaven symbol">
Il link di chiusura nel riquadro laterale potrebbe essere contrassegnato in modo più chiaro.
Aggiungi gli attributi title
e aria-label
all'elemento link di chiusura del riquadro laterale:
<a href="#"></a>
<a href="#" title="Close Menu" aria-label="Close Menu"></a>
CSS
È il momento di disporre gli elementi. I contenuti principali
e il riquadro laterale sono elementi secondari diretti del tag <body>
, quindi è un buon punto di partenza.
Aggiungi il seguente CSS a css/sidenav.css
in modo che l'elemento <body>
disponga gli elementi secondari.
body {
display: grid;
grid: [stack] 1fr / min-content [stack] 1fr;
@media (max-width: 540px) {
& > :matches(aside, main) {
grid-area: stack;
}
}
}
Questo layout indica essenzialmente: crea una riga denominata stack
con tutti gli elementi al suo interno e due colonne in quella riga, la seconda delle quali è denominata anche stack
. La prima colonna deve essere dimensionata in base alle esigenze minime dei contenuti e la seconda colonna può occupare il resto.
Se l'area visibile è limitata a 540px
o meno, inserisci il riquadro laterale e gli elementi dei contenuti principali nella stessa riga e colonna, in modo che si sovrappongano in una griglia 1x1.
Con questa funzionalità di accatastamento adattabile come base, ora possiamo sfruttare lo stato della barra degli URL per attivare/disattivare la visibilità e lo stile di transizione del riquadro laterale.
Aggiorna l'elemento <aside>
in app/index.html
:
<aside>
<aside id="sidenav-open">
In questo modo, il CSS può associare un elemento e l'hash dell'URL. Questo è importante per l'utilizzo di :target
.
Ora l'ID dell'elemento può corrispondere all'hash dell'URL che imposteremo con i tag <a>
.
Inoltre, per semplificare il targeting JavaScript, aggiungi gli ID per gli elementi chiave che controllano il riquadro laterale. Innanzitutto, aggiungi un ID al link di apertura del riquadro laterale:
<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">
Aggiungi un ID al link di chiusura del riquadro laterale:
<a href="#" title="Close Menu" aria-label="Close Menu"></a>
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>
Questo è il layout di impilaggio responsive della macro <body>
, che ci collega alla barra degli URL.
Andiamo avanti.
Anche il <aside>
ha un layout pulito. Ha due elementi secondari, un <nav>
, ovvero il componente simile a un foglio di carta che si estrae, e un elemento link di chiusura <a>
che imposta l'URL su #
.
Il link è invisibile a destra del menu a scomparsa di Carta; in questo modo gli utenti possono fare clic sul componente visivo per ignorarlo.
Aggiungi il seguente CSS a css/sidenav.css
:
#sidenav-open {
display: grid;
grid-template-columns: [nav] 2fr [escape] 1fr;
}
Il rapporto e i nomi sono stati un tocco davvero piacevole, in cui la griglia poteva dare il meglio di sé e offrire al designer un grande controllo.
Successivamente, devo sovrapporre condizionalmente i contenuti principali e mantenere la mia posizione
durante lo scorrimento del documento. È un'ottima opportunità per position: sticky
e alcuni overscroll-behavior
.
Aggiungi i seguenti stili per il riquadro laterale:
#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 */
}
}
Questi stili assicurano che la barra laterale abbia l'altezza dell'area visibile, scorra verticalmente
e contenga lo scorrimento. Molto importante, nasconde l'elemento. Per impostazione predefinita, nasconde il riquadro laterale quando l'area visibile è pari o inferiore a 540px
. A meno che!
Aggiungi un pseudo-selettore :target
all'elemento #sidenav-open
:
#sidenav-open {
@media (max-width: 540px) {
&:target {
visibility: visible;
}
}
}
Quando l'ID dell'elemento e della barra degli URL sono uguali, imposta visibility
su visible
. Apri il menu laterale dopo aver scorruto la pagina o prova a scorrere la pagina con il riquadro laterale aperto. Cosa ne pensi?
Aggiungi il seguente CSS alla parte inferiore di app/sidenav.css
:
#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;
}
}
Questi stili hanno come target i nostri pulsanti di apertura e chiusura, ne specificano gli stili di tocco e tap e li nascondono anche quando le visualizzazioni sono pari o superiori a 540px
.
Per un tocco in più, aggiungiamo le trasformazioni CSS con un'accessibilità rispettosa.
Aggiungi il seguente CSS a css/sidenav.css
:
#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;
}
}
Aggiungi un po' di JavaScript
Il tasto Escape
dovrebbe chiudere il menu. Aggiungi questo codice JS a js/index.js
:
const sidenav = document.querySelector('#sidenav-open');
sidenav.addEventListener('keyup', e => {
if (e.code === 'Escape') {
document.location.hash = '';
}
});
Questo ascolta un evento chiave nell'elemento sidenav.
Se è Escape
, l'hash dell'URL viene impostato su vuoto, facendo uscire la transizione del riquadro laterale.
Questo altro componente di UX JS è la gestione dell'attenzione. Voglio semplificare l'apertura e la chiusura, quindi aspetto fino a quando il riquadro laterale non ha completato una transizione di qualche tipo, poi lo controllo con l'hash dell'URL per determinare se è attivo o meno. Poi utilizzo JavaScript per impostare il focus sul pulsante complementare a quello appena premuto.
Aggiungi il seguente codice JavaScript a js/index.js
:
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();
});
Prova
- Per visualizzare l'anteprima del sito, premi Visualizza app, quindi premi A schermo intero .
Conclusione
Ecco un riepilogo delle mie esigenze relative al componente. Non esitare a svilupparlo, a gestirlo con lo stato JavaScript anziché con l'URL e, in generale, a personalizzarlo. C'è sempre qualcosa da aggiungere o più casi d'uso da coprire.
Apri css/brandnav.css
per controllare gli stili non correlati al layout che ho applicato a questo componente. Non ritenevo che fosse importante per il set di funzionalità su cui mi stavo concentrando e speravo che separare gli stili dal layout avrebbe incoraggiato la copia e incolla. Potresti trovare altre informazioni utili.
Come creare componenti sidenav adattabili scorrevoli? Hai mai più di 1, ad esempio una su entrambi i lati? Mi piacerebbe mostrare la tua soluzione in un video di YouTube. Assicurati di inviarmi un tweet o di commentare su YouTube con il tuo codice, sarà di aiuto a tutti.