Tworzenie komponentu bocznego

Podstawowe informacje o tworzeniu elastycznego wysuwanego panelu bocznego

W tym poście przedstawię prototypowanie internetowego komponentu Sidenav, który 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 na YouTube:

Przegląd

Stworzenie elastycznego systemu nawigacji jest trudne. Część użytkowników korzysta z klawiatury, inni na zaawansowanych komputerach, a jeszcze inni na małych urządzeniach mobilnych. Wszyscy odwiedzający powinni mieć możliwość otwierania i zamykania menu.

Wersja demonstracyjna układu elastycznego z komputerów na urządzenia mobilne
Przejście z jasnego i ciemnego motywu na iOS i Androida

Taktyki internetowe

W ramach tej eksploracji składowej udało mi się połączyć kilka ważnych funkcji platformy internetowej:

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

Moje rozwiązanie ma 1 pasek boczny i przełącza się tylko wtedy, gdy znajduje się w widocznym obszarze na poziomie „mobilnym” nieprzekraczającym 540px. 540px będzie naszym punktem przerwania przy przełączaniu się między interfejsem interaktywnym na urządzenia mobilne a układem statycznym na komputery.

Pseudoklasa CSS :target

Jeden link <a> ustawia hasz adresu URL na #sidenav-open, a drugi jest pusty (''). Ostatni element zawiera parametr id odpowiadający haszu:

<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 naszej strony, a potem dzięki pseudoklasie wyświetlam i ukrywam panel boczny:

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

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

Siatka CSS

Dawniej używałam układów i komponentów nawigacji bocznej z bezwzględnymi lub stałymi pozycjami. Jednak dzięki składni grid-area można przypisać wiele elementów do tego samego wiersza lub kolumny.

Stosy

Podstawowy element układu #sidenav-container to siatka, która tworzy jeden wiersz i 2 kolumny. Jedna z nich ma nazwę stack. Gdy przestrzeń jest ograniczona, CSS przypisuje wszystkie elementy podrzędne elementu <main> do tej samej nazwy siatki, umieszczając wszystkie elementy w tej samej przestrzeni i tworząc 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 element animowany zawierający boczny panel nawigacyjny. Ma dwa 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 ustawienia 2fr i 1fr, aby znaleźć odpowiedni współczynnik proporcji nakładki menu i jej przycisku zamykania.

Prezentacja, co się stanie, gdy zmienisz współczynnik.

Przekształcenia i przejścia CSS 3D

Nasz układ jest teraz warstwowy w rozmiarze widocznego obszaru na urządzeniach mobilnych. Dopóki nie dodam nowych stylów, domyślnie nakłada się on na artykuł. W następnej sekcji chcę podać kilka informacji o wrażeniach użytkownika:

  • Animacja otwarcia i zamykania
  • Animuj z ruchem tylko wtedy, gdy użytkownik to akceptuje
  • Animuj visibility tak, aby zaznaczenie z klawiatury nie wprowadzało elementu poza ekranem

Zaczynając implementowanie animacji ruchu, chcę zacząć od ułatwień dostępu.

Ruch z ułatwieniami dostępu

Nie każdy chciałby mieć możliwość wysunięcia się z niego. W naszym rozwiązaniu tę preferencję stosujemy, dostosowując zmienną CSS --duration w zapytaniu o media. Wartość zapytania o multimedia to preferencja użytkownika w zakresie ruchu w systemie operacyjnym (jeśli jest dostępna).

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

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

Teraz, gdy pasek boczny przesuwa się w górę i w dół, a użytkownik preferuje zmniejszony ruch, natychmiast przesuwam element w widoku, zachowując jego stan bez ruchu.

Przejście, przekształcenie, tłumaczenie

Sidenav Out (domyślnie)

Aby ustawić domyślny stan panelu bocznego na urządzeniu mobilnym w trybie poza ekranem, ustawiam element za pomocą transform: translateX(-110vw).

Dodaję kolejny 10vw do typowego kodu spoza ekranu -100vw, aby mieć pewność, że box-shadow panelu bocznego nie zasłania widoku głównego widocznego obszaru, gdy jest 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 będzie zgodny z wartością :target, ustaw pozycję translateX() na bazę główną 0 i obserwuj, jak CSS przesuwa element z pozycji poza nią (-110vw) na pozycję „0” zamiast „var(--duration)” po zmianie skrótu adresu URL.

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

Widoczność przejścia

Obecnie celem jest ukrycie menu przed czytnikami ekranu, gdy jest ono wyłączone, a systemy nie umieszczają w nim opcji poza ekranem. Jest to możliwe dzięki ustawieniu widocznego przejścia po zmianie parametru :target.

  • Zadbaj o to, aby elementy były widoczne od razu. Gdy się pojawią, pokaż element, który się wysunie, i zaznacz, że jest aktywny.
  • Gdy wychodzisz, włącz widoczność przejścia z opóźnieniem, aby na końcu przejść do hidden.

Ulepszenia ułatwień dostępu

To rozwiązanie wymaga zmiany adresu URL w celu umożliwienia zarządzania stanem. Tu należy użyć elementu <a> i bezpłatnie uzyskać do niego przydatne funkcje ułatwień dostępu. Ozdóbmy nasze elementy interaktywne etykietami, które jasno przedstawiają 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>
Wersja demonstracyjna obsługi interakcji z głosem lektora i klawiatury.

Teraz jasno określają one przeznaczenie myszy i klawiatury.

:is(:hover, :focus)

Dzięki temu praktycznemu pseudoselektorowi CSS możemy szybko dodawać elementy do stylów, które są pokazywane po najechaniu kursorem.

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

Posypka w języku JavaScript

Aby zamknąć, naciśnij escape

Klawisz Escape na klawiaturze powinien zamknąć menu? Podłączmy to pod prąd.

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

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

Aby uniemożliwić interakcję otwierania i zamykania w historii przeglądarki wielu wpisów, dodaj do przycisku zamykającego ten kod JavaScript:

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

Przy zamknięciu zostanie usunięty wpis historii adresów URL, przez co menu nie będzie nigdy otwierane.

Skup się na wrażeniach użytkownika

Następny fragment pomaga nam skupić się na przyciskach otwierania i zamykania, gdy są one otwierane lub zamykane. Chcę ułatwić sobie przełączanie.

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

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

Po otwarciu panelu bocznego zaznacz przycisk zamykania. Po zamknięciu panelu nawigacyjnego upewnij się, że przycisk otwierania jest otwarty. Wywołuję focus() w elemencie w JavaScript.

Podsumowanie

Skoro już wiesz, jak to udało mi się osiągnąć, to jak? W ten sposób powstaje zabawna architektura komponentów. Kto utworzy pierwszą wersję z przedziałami? 🙂

Przeanalizujmy różne podejścia i nauczmy się korzystać z internetu. Utwórz glitch i napisz mi swoją wersję, a dodam ją do sekcji Remiksy społeczności poniżej.

Remiksy społeczności