Ćwiczenia z programowania: tworzenie komponentu Sidenav

Z tego ćwiczenia w Codelabs dowiesz się, jak utworzyć w internecie elastyczny układ z bocznym paskiem nawigacji. Będziemy tworzyć komponent na bieżąco, zaczynając od HTML, potem CSS, a na końcu JavaScript.

Aby dowiedzieć się więcej o funkcjach platformy internetowej CSS, które zostały wybrane do tworzenia tego komponentu, przeczytaj wpis na blogu Tworzenie komponentu menu bocznego.

Konfiguracja

  1. Kliknij Remixuj do edycji, aby umożliwić edycję projektu.
  2. Otwórz pokój app/index.html.

HTML

Najpierw musisz poznać podstawy konfiguracji kodu HTML, aby mieć treści i pola, z którymi możesz pracować.

Wklej ten kod HTML do tagu <body>.

<aside></aside>
<main></main>

Element <aside> zawiera menu nawigacyjne jako element uzupełniający element <main>, który zawiera główną treść strony.

Następnie wypełnimy te elementy semantyczne resztą treści strony.

Dodaj element nawigacji, kilka linków nawigacyjnych i link do zamknięcia w elemencie <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>

Linki świetnie sprawdzają się w elementach <nav>, a elementy <nav> w bocznych panelach <aside>. Nadal jednak możemy coś zrobić, aby ulepszyć tę funkcję.

W głównym elemencie treści dodaj nagłówek i artykuł, aby semantycznie przechowywać zawartość układu.

<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>

W nagłówku znajduje się link do menu. Zawiera on przycisk zamykania. Wkrótce będziemy wyświetlać i ukrywać elementy na podstawie rozmiaru widoku.

W elemencie <article> wklejono zdanie zastępcze. Zastąp „” własnymi treściami lub wklej lorem podanego poniżej:

<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>

Te treści i ich długość powodują, że strona jest przewijalna, gdy przekracza wysokość widocznego obszaru.

Do tej pory dodałeś/dodałaś element boczny z menu, linkami i opcją zamknięcia menu bocznego. Dodałaś(-eś) też nagłówek, sposób otwierania paska bocznego i artykuł do głównego elementu. Jest to już czyste, semantyczne i dosyć ponadczasowe, ale możemy je jeszcze bardziej uprościć i ulepszyć dla wszystkich. Link do otwierania w menu bocznym mógłby być lepiej oznaczony.

Dodaj atrybuty titlearia-label do elementu linku otwierającego w nagłówku:

<a href="#sidenav-open" class="hamburger">
<a href="#sidenav-open" title="Open Menu" aria-label="Open Menu" class="hamburger">

Ikona otwartego pliku SVG mogłaby być lepiej oznaczona. Dodaj do elementu SVG w elemencie otwierania linku te atrybuty:

<svg viewBox="0 0 50 40">
<svg viewBox="0 0 50 40" role="presentation" focusable="false" aria-label="trigram for heaven symbol">

Link do zamknięcia w menu bocznym mógłby być lepiej oznaczony. Dodaj atrybuty title i aria-label do elementu linku do zamykania paska bocznego:

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

CSS

Czas na ułożenie elementów. Główna treść i menu boczne są bezpośrednimi elementami podrzędnymi tagu <body>, więc warto zacząć od nich.

Dodaj ten kod CSS do elementu css/sidenav.css, aby element <body> wyświetlał elementy podrzędne.

body {
  display: grid;
  grid: [stack] 1fr / min-content [stack] 1fr;

  @media (max-width: 540px) {
    & > :matches(aside, main) {
      grid-area: stack;
    }
  }
}

Ten układ mówi zasadniczo: „Utwórz wiersz o nazwie stack z wszystkimi elementami oraz 2 kolumny w tym wierszu, z których druga ma też nazwę stack”. Rozmiar pierwszej kolumny powinien być dostosowany do minimalnych potrzeb treści, a druga kolumna może zająć pozostałą część. Następnie, jeśli widoczny obszar ma wymiary 540px lub mniejsze, umieść elementy menu bocznego i główne treści w tym samym wierszu i kolumnie, dzięki czemu będą one nakładać się na siebie w siatce 1 x 1.

Dzięki tej funkcji elastycznego układania możemy teraz wykorzystywać stan paska adresu URL do przełączania widoczności i stylu przejścia paska bocznego.

Zaktualizuj element <aside> w komponencie app/index.html:

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

Umożliwia to CSS dopasowanie elementu i hasza adresu URL. Jest to ważne w przypadku :target. Teraz identyfikator elementu może pasować do hasha adresu URL, który ustawimy za pomocą tagów <a>.

Aby ułatwić kierowanie kodu JavaScript, dodaj identyfikatory kluczowych elementów, które kontrolują pasek boczny. Najpierw dodaj identyfikator do linku otwierania menu bocznego:

<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">

Następnie dodaj identyfikator do linku zamykania paska bocznego:

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

To wszystko, co chciałam powiedzieć o makro <body> i responsywnym układzie z wielopoziomowym układem oraz o połączeniu z paskiem adresu URL. Kontynuujmy.

<aside> ma też przejrzysty układ. Zawiera 2 elementy podrzędne: <nav>, który jest elementem przypominającym papier, który wysuwa się na zewnątrz, oraz zamykający element linku <a>, który ustawia adres URL na #. Link jest niewidoczny po prawej stronie paska nawigacyjnego w trybie rozkładania. Dzięki temu użytkownicy mogą „kliknąć poza” wizualny element, aby go zamknąć.

Dodaj do pliku css/sidenav.css ten kod CSS:

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

Uważam, że proporcje i nazwy są bardzo dobrym pomysłem, ponieważ siatka może się tu świetnie sprawdzić i dać projektantowi dużo kontroli.

Następnie muszę warunkowo nałożyć główną zawartość i zatrzymać pozycję podczas przewijania dokumentu. To świetna praca dla position: sticky i overscroll-behavior.

Dodaj te style dla menu bocznego:

#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 */
  }
}

Te style zapewniają, że pasek boczny ma wysokość widocznego obszaru, przewija się w kierunku pionowym i zawiera suwak. Co bardzo ważne, ukrywa on element. Domyślnie, gdy widok jest mniejszy niż 540px, ukryj menu boczne. Chyba że

Dodaj do elementu #sidenav-open pseudoselektor :target:

#sidenav-open {

  @media (max-width: 540px) {

    &:target {
      visibility: visible;
    }
  }
}

Jeśli identyfikator tego elementu i paska adresu URL są takie same, ustaw visibility na visible. Otwórz menu boczne po przewinięciu strony lub spróbuj przewinąć stronę, gdy jest otwarte menu boczne. Co myślisz?

Dodaj ten kod CSS na dole pliku 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;
  }
}

Te style dotyczą przycisków otwierania i zamykania, określają ich styl dotyku i dotknięcia, a także ukrywają je, gdy widok 540px lub większy.

Aby nadać styl, dodajmy przekształcenia CSS z uwzględnieniem dostępności. Dodaj do pliku css/sidenav.css ten kod 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;
  }
}
Demo interakcji z zastosowaniem i bez zastosowania czasu trwania na podstawie zapytania multimedialnego „prefers-reduced-motion”.

Dodawanie kodu JavaScript

Przycisk Escape powinien zamknąć menu. Dodaj ten kod JS do pliku js/index.js:

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

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

Nasłuchuje on kluczowego zdarzenia w elemencie menu bocznego. Jeśli jest Escape, hasz adresu URL jest pusty, co powoduje przejście z menu bocznego.

Kolejnym elementem UX JS jest zarządzanie obszarem fokusu. Chcę, aby otwieranie i zamykanie było łatwe, więc czekam, aż pasek boczny zakończy przełączanie, a potem sprawdzam to na podstawie hasha adresu URL, aby określić, czy jest otwarty czy zamknięty. Następnie za pomocą JavaScriptu ustawiam fokus na przycisku, który jest uzupełnieniem tego, który został właśnie naciśnięty.

Dodaj do js/index.js ten kod JavaScript:

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();
});

Wypróbuj

  • Aby wyświetlić podgląd strony, kliknij Wyświetl aplikację. Następnie kliknij Pełny ekran pełny ekran.

Podsumowanie

To wszystko, co chciałam powiedzieć na temat tego komponentu. Możesz go dowolnie modyfikować, sterować nim za pomocą stanu JavaScript zamiast adresu URL i ogółem uczynić go swoim. Zawsze można dodać więcej treści lub omówić więcej przypadków użycia.

Otwórz css/brandnav.css, aby sprawdzić style niezwiązane z układem, które zastosowałem do tego komponentu. Nie uważam, aby było to ważne w przypadku zestawu funkcji, na którym się skupiałem, i miałem nadzieję, że oddzielenie stylów od układu zachęci do kopiowania i wklejania. Możesz się tam dowiedzieć więcej.

Jak tworzyć przesuwane komponenty nawigacji bocznej? Czy zdarza się, że jest ich więcej niż 1, np. po obu stronach? Chętnie przedstawię Twoje rozwiązanie w filmie w YouTube. Pamiętaj, aby wysłać do mnie tweeta lub dodać komentarz w YouTube z kodem. Pomoże to innym użytkownikom.