Tworzenie komponentu bocznego

Podstawowy przegląd tworzenia elastycznego paska bocznego z przesuwnym menu

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:

Omówienie

Budowanie elastycznego systemu nawigacji jest trudne. Niektórzy będą korzystać z klawiatury, inni z wydajnymi komputerami, a inni korzystają z małych urządzeń mobilnych. Każdy użytkownik powinien mieć możliwość otwierania i zamykania menu.

Demonstracja przejścia z wersji na komputer na wersję responsywną na urządzenia mobilne
Tematyka jasna i ciemna na iOS i Androidzie

Taktyki internetowe

W tej eksploracji komponentów połączyłem kilka kluczowych funkcji platformy internetowej:

  1. CSS :target
  2. siatka w CSS,
  3. przekształcenia w CSS,
  4. Zapytania multimedialne CSS dotyczące widocznego obszaru i preferencji użytkownika
  5. JS do focus ulepszania UX

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

Pseudoklasa usługi porównywania cen :target

Jeden link <a> ustawia skrót URL na #sidenav-open, a drugi na pusty (''). Na koniec element ma wartość id, która pasuje 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 szyfrowania adresu URL strony, a następnie za pomocą pseudoklasy wyświetlam i ukrywanie menu bocznego:

@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 z pozycją bezwzględną lub stałą. Jednak dzięki użyciu składni grid-area możemy przypisać wiele elementów do tego samego wiersza lub tej samej kolumny.

Stosy

Główny element układu #sidenav-container to siatka, która tworzy 1 wiersz i 2 kolumny, z których każda 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, 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 animowany element, który zawiera boczne elementy nawigacyjne. Zawiera 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 wartości 2fr1fr, aby znaleźć odpowiedni stosunek dla menu nakładki i przycisku zamknięcia w pustej przestrzeni.

Demo, co się dzieje, gdy zmieniasz współczynnik.

Przekształcenia i przejścia 3D w CSS

Układ jest teraz ułożony w wielkości widocznego obszaru na urządzeniu mobilnym. 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.

  • Animowanie otwierania i zamykania
  • Animuj z ruchem tylko wtedy, gdy użytkownik wyrazi na to zgodę
  • Animuj visibility, aby zaznaczenie klawiatury nie przenosiło się na element poza ekranem.

Gdy zaczynam wdrażać animacje ruchu, chcę zacząć od dostępności.

Dostępność ruchu

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 reprezentuje preferencje użytkownika dotyczące animacji (jeśli są dostępne) w systemie operacyjnym.

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

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

Gdy użytkownik przesuwa panel boczny, aby go otworzyć lub zamknąć, a on woli ograniczone animacje, element jest natychmiast wyświetlany, zachowując stan bez animacji.

Przejście, przekształcenie, tłumaczenie

Sidenav out (domyślnie)

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

Do typowego kodu offscreen -100vw dodałem jeszcze 10vw, aby box-shadow paska boczna nie była widoczna w głównym widoku, gdy jest ukryta.

@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);
  }
}
Pasek boczny

Gdy element #sidenav pasuje do wartości :target, ustaw pozycję translateX() na pozycję wyjściową 0. Gdy zmienisz hasz URL, element przesunie się z pozycji wyjściowej -110vw do pozycji „wewnątrz” 0 nad pozycją var(--duration).

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

Widoczność przejścia

Naszym celem jest teraz ukrycie menu przed czytnikami ekranu, gdy jest ono wyświetlane, aby systemy nie przenosiły punktu zaznaczenia na menu poza ekran. Jestem w tym celu ustawiany przez ustawienie widoczności w przypadku zmiany :target.

  • Gdy wchodzę w element, nie przechodź do niego przez przejście. Element powinien być widoczny od razu, abym mógł zobaczyć, jak się pojawia i przejmuje fokus.
  • Podczas wychodzenia z okna widoczność przechodzi w tryb widoczny, ale z opóźnieniem, dzięki czemu na końcu okna jest ona ustawiona na hidden.

Ulepszenia wrażeń użytkownika związanych z ułatwieniami dostępu

To rozwiązanie polega na zmianie adresu URL w celu zarządzania stanem. Oczywiście należy tu użyć elementu <a>, który bezpłatnie zapewnia przydatne funkcje ułatwień dostępu. Oznaczmy nasze elementy interaktywne etykietami, które jasno określają ich przeznaczenie.

<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>
Demo interfejsu użytkownika dotyczącego lektora i interakcji z klawiaturą.

Teraz nasze główne przyciski interakcji wyraźnie określają swoje przeznaczenie zarówno w przypadku myszy, jak i klawiatury.

:is(:hover, :focus)

Ten przydatny funkcjonalny pseudoselektor CSS pozwala nam szybko stosować style najechania kursorem, udostępniając je również w przypadku najechania kursorem.

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

Dodawanie elementów JavaScript

Aby zamknąć, naciśnij escape

Przycisk Escape na klawiaturze powinien zamknąć menu. Zaczynajmy.

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

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

Aby zapobiec nagromadzeniu się wielu wpisów w historii przeglądarki w przypadku interakcji otwierania i zamykania, dodaj do przycisku Zamknij 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 z historii adresów URL po zamknięciu menu, tak jakby menu nigdy nie było otwierane.

Focus UX

Następujący fragment kodu pomaga nam ustawić fokus na przyciskach otwierania i zamykania po ich otwarciu lub zamknięciu. Chcę ułatwić przełączanie.

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ę pasek boczny, ustaw fokus na przycisku Zamknij. Gdy pasek boczny się zamknie, ustaw fokus na przycisku Otwórz. Aby to zrobić, wywołuję funkcję focus() elementu w JavaScript.

Podsumowanie

Skoro już wiesz, jak to robię, jak Ty?! To tworzy ciekawą architekturę komponentów. Kto ma utworzyć pierwszą wersję z miejscami? 🙂

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

Remiksy utworzone przez społeczność