Tworzenie komponentu bocznego

Podstawowe omówienie tworzenia elastycznej wysuwanej nawigacji bocznej

W tym poście opowiem, jak udało mi się stworzyć prototypowy komponent Sidenav dla stron internetowych. Jest elastyczny, stanowy, obsługuje nawigację za pomocą klawiatury, obsługuje JavaScript i bez niego oraz działa w różnych przeglądarkach. Zobacz prezentację.

Jeśli wolisz film, oto wersja tego posta w YouTube:

Przegląd

Stworzenie elastycznego systemu nawigacyjnego jest trudne. Niektórzy będą korzystać z klawiatury, inni z wydajnymi komputerami, a inni korzystają z małych urządzeń mobilnych. Każda osoba odwiedzająca powinna mieć możliwość otwarcia i zamknięcia menu.

Demonstracja układu elastycznego z komputerów na urządzenia mobilne
Jasny i ciemny motyw w wersji na iOS i Androida

Taktyki internetowe

Podczas tej eksploracji komponentów udało mi się połączyć kilka kluczowych funkcji platformy internetowej:

  1. Usługa porównywania cen :target
  2. Siatka CSS
  3. transforms CSS
  4. Zapytania o multimedia CSS na potrzeby widocznego obszaru i preferencji użytkownika
  5. JS na potrzeby focus ulepszeń UX

Moje rozwiązanie ma jeden pasek boczny i przełącza się tylko w widocznym obszarze na urządzeniach mobilnych, który wynosi 540px lub mniej. 540px będzie naszym punktem przerwania przy przełączaniu między interaktywnym układem mobilnym a statycznym układem na komputery.

Pseudoklasa usługi porównywania cen :target

Jeden link <a> ustawia hasz adresu URL na #sidenav-open, a drugi na pusty (''). Ostatnim elementem jest id pasujący do skrótu:

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

Kliknięcie każdego z tych linków zmienia stan skrótu adresu URL strony, a następnie za pomocą pseudoklasy wyświetlam i ukrywam boczny panel nawigacyjny:

@media (max-width: 540px) {
  #sidenav-open {
    visibility: hidden;
  }

  #sidenav-open:target {
    visibility: visible;
  }
}

Siatka CSS

Wcześniej używałem tylko układów i komponentów nawigacji bocznej o stałej lub stałej pozycji. Siatka, dzięki składni grid-area, pozwala nam przypisać wiele elementów do tego samego wiersza lub kolumny.

Stosy

Podstawowy element układu #sidenav-container to siatka, która tworzy 1 wiersz i 2 kolumny, z których 1 ma nazwę stack. W przypadku ograniczenia przestrzeni CSS wszystkie elementy podrzędne elementu <main> przypisują tej samej nazwie siatki, umieszczając wszystkie elementy w tej samej przestrzeni i tworzą stos.

#sidenav-container {
  display: grid;
  grid: [stack] 1fr / min-content [stack] 1fr;
  min-height: 100vh;
}

@media (max-width: 540px) {
  #sidenav-container > * {
    grid-area: stack;
  }
}

<aside> to animowany element, który zawiera boczne elementy nawigacyjne. Ma 2 elementy podrzędne: kontener nawigacyjny <nav> o nazwie [nav] i tło <a> o nazwie [escape], które służy do zamykania menu.

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

Dostosuj parametry 2fr i 1fr, aby znaleźć odpowiedni współczynnik proporcji nakładki menu i jej przycisku zamykania.

Prezentacja tego, co się dzieje po zmianie współczynnika.

Przekształcenia i przejścia 3D CSS

Nasz układ jest teraz układany w stos do rozmiaru widocznego obszaru na urządzeniach mobilnych. Dopóki nie dodam nowych stylów, będą one domyślnie nakładane na nasz artykuł. W następnej sekcji pokażę, jak zwiększyć wygodę użytkowników.

  • Otwieranie i zamykanie
  • Animuj z ruchem tylko wtedy, gdy użytkownik wyrazi na to zgodę
  • Animuj element visibility tak, aby zaznaczenie z klawiatury nie znalazło się w elemencie poza ekranem

Zaczynając wdrażanie animacji animacji, zwróćmy uwagę na ułatwienia dostępu.

Ruch z ułatwieniami dostępu

Nie każdemu przydałaby się ruchoma wysuwana reklama. W naszym rozwiązaniu to ustawienie jest stosowane przez dostosowanie zmiennej CSS --duration w zapytaniu o media. Ta wartość zapytania o multimedia odpowiada preferencjom w ruchu w systemie operacyjnym użytkownika (jeśli są dostępne).

#sidenav-open {
  --duration: .6s;
}

@media (prefers-reduced-motion: reduce) {
  #sidenav-open {
    --duration: 1ms;
  }
}
Prezentacja interakcji z zastosowanym czasem trwania i bez niego.

Jeśli użytkownik preferuje zmniejszony ruch, od razu przenoszę element w widok, utrzymując przy tym stan bez ruchu, gdy nasz boczny pasek nawigacyjny otwiera się i zamyka.

Przejście, przekształcenie, tłumaczenie

Sidenav Out (domyślnie)

Aby ustawić domyślny stan nawigacji sidenav na urządzeniach mobilnych na poza ekranem, pozycjonuję element za pomocą funkcji transform: translateX(-110vw).

Uwaga: dodałem kolejny element 10vw do typowego kodu poza ekranem kodu -100vw, aby mieć pewność, że element box-shadow panelu nawigacyjnego nie wypadnie do głównego widocznego obszaru, gdy jest on ukryty.

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

Gdy element #sidenav pasuje jako :target, ustaw pozycję translateX() na wartość Homebase 0 i obserwuj, jak CSS przesuwa element z pozycji -110vw do pozycji „w” (0 na var(--duration)), gdy hasz adresu URL ulegnie zmianie.

@media (max-width: 540px) {
  #sidenav-open:target {
    visibility: visible;
    transform: translateX(0);
    transition:
      transform var(--duration) var(--easeOutExpo);
  }
}

Widoczność przejścia

Celem jest ukrycie menu przed czytnikami ekranu, aby nie było ono skoncentrowane na menu poza ekranem. Jestem w tym celu ustawiany przez ustawienie widoczności w przypadku zmiany :target.

  • Gdy wchodzisz, nie zmieniaj widoczności; bądź od razu widoczny, żeby element wsuwał się do środka i był widoczny.
  • Widoczność przejścia powinna być opóźniona, tak aby po zakończeniu przejścia została przełączona na hidden.

Ulepszenia UX ułatwień dostępu

Działanie tego rozwiązania wymaga zmiany adresu URL na potrzeby zarządzania stanem. Oczywiście tutaj należy użyć elementu <a>, który zapewnia bezpłatne funkcje ułatwień dostępu. Dodajmy do naszych elementów interaktywnych etykiety jasno określające intencje.

<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>
Prezentacja UX UX lektora i klawiatury.

Teraz nasze główne przyciski interakcji jasno określają przeznaczenie zarówno myszy, jak i klawiatury.

:is(:hover, :focus)

Ten praktyczny pseudoselektor CSS pozwala nam szybko i skutecznie promować integrację społeczną dzięki stylom wyświetlanym po najechaniu kursorem.

.hamburger:is(:hover, :focus) svg > line {
  stroke: hsl(var(--brandHSL));
}

Dodawanie elementów JavaScript

Aby zamknąć, naciśnij escape

Klawisz Escape na klawiaturze powinien zamykać menu? Zaczynajmy.

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

sidenav.addEventListener('keyup', event => {
  if (event.code === 'Escape') document.location.hash = '';
});
Historia przeglądarki

Aby podczas otwierania i zamykania interakcji z otwartą i zamykającą interakcją w historii przeglądarki nie było nakładać się wielu wpisów, dodaj do przycisku zamykania następujący kod JavaScript:

<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu" onchange="history.go(-1)"></a>

Spowoduje to usunięcie wpisu w historii adresów URL przy zamknięciu, a menu się nie otworzy.

Koncentracja na UX

Następny fragment pomaga skupić się na przyciskach otwierania i zamykania. Chcę ułatwić przełączanie się między urządzeniami.

sidenav.addEventListener('transitionend', e => {
  const isOpen = document.location.hash === '#sidenav-open';

  isOpen
      ? document.querySelector('#sidenav-close').focus()
      : document.querySelector('#sidenav-button').focus();
})

Gdy otworzy się boczna nawigacja, ustaw fokus na przycisku zamykania. Po zamknięciu panelu nawigacji ustaw fokus na przycisku otwierania. Wywołuję w tym celu funkcję focus() w elemencie w JavaScript.

Podsumowanie

Skoro już wiesz, jak to robię, jak Ty?! W ten sposób tworzymy ciekawą architekturę komponentów. Kto przygotuje pierwszą wersję z automatami do gry? 🙂

Wybierzmy różne podejścia i poznajmy sposoby budowania obecności w internecie. Utwórz usterkę, napisz do mnie swoją wersję, a dodam ją do sekcji Remiksy społeczności poniżej.

Remiksy utworzone przez społeczność