Budując stopniowo ulepszane menu mobilne, które działa bez JavaScriptu
Ostatnia aktualizacja 21 stycznia 2019 r.
Pure CSS off-canvas hamburger menus nie są niedawnym odkryciem. W końcu Chris Coyier napisał o tej technice jeszcze w listopadzie 2012 roku.
- Jeśli jest to dla ciebie stara sztuczka, to powiesić się ze mną na trochę. Ulepszyłem przykład Chrisa i chciałbym poznać twoje opinie.
- Jeśli jest to dla ciebie nowość, nie martw się. Masz dużo towarzystwa, jako że wydaje się, że duża część sieci jeszcze tego nie załapała.
W ten sposób zbudujemy proste, responsywne menu hamburgerowe poza kanwą, używając tylko CSS, które łatwo będzie włączyć do twojego własnego projektu. Ale najpierw…
Co jest nie tak z JavaScriptem?
Nic.
Aaron Gustafson wyjaśnia znaczenie Progressive Enhancements i rolę JavaScript w tworzeniu stron internetowych lepiej niż ja kiedykolwiek mogłem. Powinieneś przeczytać jego post. Ale dla zwięzłości, postaram się go podsumować:
- „Podstawowe zadania zawsze można wykonać bez JavaScriptu.”
- Podstawowe zadania powinny być wykonywane na najbardziej stabilnej warstwie (tj. nie JavaScript).
- Progresive Enhancements nie jest anty-JavaScript. Chodzi tylko o zastosowanie właściwych technologii na właściwej warstwie.
- „Ponieważ istnieje jakaś szansa, że JavaScript nie będzie działał, musimy zawsze brać pod uwagę tę szansę.”
- Nigdy nie jest dobrym pomysłem ignorowanie potencjalnych użytkowników.
- Progressive Enhancements to po prostu dobra inżynieria.
Więc, zrobimy tyle, ile się da z HTML i CSS. Następnie niech JavaScript zrobi swoją magię na bardziej odpowiedniej warstwie – poprawiając już istniejący UI.
Krok 1: HTML
Jak być może wiesz, pierwszym krokiem jest zawsze napisanie solidnej, dobrze przemyślanej, bazowej warstwy HTML.
Uwaga: Używam Font Awesome dla ikon w moim przykładzie.
Wygląda raczej standardowo, prawda? Mamy:
- Naszego rodzica <element header>
- Ikonę hamburgera („fa-bars”)
- Główny nagłówek (lub potencjalnie logo)
- Nawigację w elemencie <nav>
- Ikonę zamknięcia („fa-close”) wewnątrz nawigacji (więcej na ten temat później)
- Ikona „backdrop” po nawigacji. Dlaczego jest to znacznik anchor? Wyjaśnię później.
Krok 2: Uczyńmy ją bardziej dostępną
Dostępność nigdy nie powinna być czymś po fakcie – jak po napisaniu aplikacji. Powinna być zaplanowana od samego początku. Dodanie kilku podstawowych uwag teraz nie tylko poprawi ogólną dostępność twojej strony, ale zapewni tobie (deweloperowi) lepszy znacznik do wykorzystania w twoim JavaScript!
W związku z tym, dodamy jeszcze kilka atrybutów i trochę tekstu przeznaczonego tylko dla czytników ekranu:
Tutaj jest szybki podział wszystkich tych atrybutów i jak one działają:
- Dodaliśmy unikalne identyfikatory do kierowania naszych HREFów (więcej o tym jak to działa później).
- Zapewniliśmy informacyjną etykietę przycisków dla czytników ekranu za pomocą .
- Ukryliśmy ikony przed czytnikami ekranu za pomocą , ponieważ są one wizualnymi reprezentacjami, i dodaliśmy tekst tylko dla czytników ekranu za pomocą elementów <span class=”sr-only”>.
- Wyjęliśmy „tło” z indeksu tabulacji za pomocą . Jest to czysto wizualna natura i nie chcemy dezorientować naszych niedowidzących i używających klawiatury użytkowników.
- Dodaliśmy atrybut amazing, aby ustawić początkowy (i semantyczny) stan „tła”. Koniec ze śmieciami – jakże ekscytujące!
Oto dotychczasowy rezultat:
Krok 3: Wystylizujmy to!
Podejdziemy do tego mobile-first, więc zlikwidujmy widok mobilny, „hamburgerowy” (interesująca część).
Najpierw zajmiemy się tylko poprawnym układem nagłówka (bez interaktywności):
Wynik:
Krok 4: Interaktywność za pomocą czystego CSS
Przy tworzeniu interaktywnych widżetów za pomocą CSS, masz kilka opcji:
- Użyj radia lub checkboxów
- Użyj pseudo-klasy :target.
Radia i checkboxy działają zadziwiająco dobrze dla większości widżetów, takich jak zakładki, moduły, dropdowns i akordeony. Chris Coyier nazwał tę technikę „the checkbox hack”. Kilku programistów użyło tego „hacka” do swoich menu poza kanwą, jak w tutorialu Paula Lewisa na Chrome Dev Summit lub w morfującym menu hamburgerowym Luisa Manuela.
Jednakże, pseudoklasa :target jest bardziej semantyczna w tym przypadku użycia, ponieważ mamy do czynienia bezpośrednio z nawigacją. Możesz się nie zgodzić, i to jest całkowicie w porządku! Byłoby niewiarygodnie łatwo i całkowicie do zaakceptowania zamienić pseudoklasę :target na checkbox.
Każda z tych technik ma jednak swoje zastrzeżenia.
Użycie pola wyboru:
- Wymaga JavaScript do zamknięcia menu off-canvas jeśli jeden z linków w menu był linkiem zakotwiczonym do konkretnej sekcji tej samej strony.
- Wymaga aby pole <input> było rodzeństwem menu lub przynajmniej rodzeństwem przodka menu. Innymi słowy, CSS jest nieco bardziej skomplikowany. Możesz mieć <label> (nawet wiele etykiet) gdzie indziej, chociaż.
- Element <label> nie będzie bezpośrednio focusowalny lub tab-able, wymagając nieco bardziej skomplikowanego CSS do obsługi fokusu na polu wyboru przy jednoczesnej zmianie widocznego wyglądu <label>.
- Nawigacja klawiaturowa wokół otwierania/zamykania menu będzie niemiła. Zmiana stanu pola wyboru jest dokonywana za pomocą klawisza, a nie klawisza. Podczas gdy niewidomi użytkownicy mogą zrozumieć, że widżet jest obsługiwany przez pole wyboru, widzący użytkownicy klawiatury będą zdezorientowani, ponieważ pole wyboru nie jest widoczne – coś, co uważałem za wyłącznik w tym przypadku użycia.
Użycie pseudoklasy :target:
- Dodaje otwarcie/zamknięcie menu off-canvas do historii przeglądarki (przesuwając hash do paska adresu). Będzie wymagać JavaScript, aby uruchomić Event.preventDefault(), aby tego uniknąć (i potencjalnie irytujące przeskakiwanie na górę strony).
I mogą być inne zastrzeżenia, które przegapiłem. Tak czy inaczej, wybór, która technika jest zarówno kwestią preferencji, jak i podlega wymaganiom twojego projektu. W każdym razie, odbiegam od tematu…
Oto interaktywna część CSS:
Wynik po kliknięciu:
Jak to wszystko działa
Podsumowując, pseudo-klasa :target daje nam nowy „stan” do stylizacji docelowej nawigacji. Kiedy main-menu zostało namierzone (z jego hashem dodanym do URL), możemy teraz wysunąć menu. Jest to trochę jak pseudoklasa :focus dla elementu docelowego (nie dla samego linku).
Pozwoliliśmy także na wyświetlanie „tła”, gdy nawigacja jest docelowa.
Zauważ, że ikona głównego hamburgera jest powiązana z ID nawigacji, podczas gdy zarówno ikona zamknięcia jak i przyciski tła są powiązane z ikoną głównego hamburgera. To pozwala nam kliknąć ikonę zamknięcia lub tło, aby usunąć „fokus” – lub naprawdę :target – z nawigacji. Gdyby tło nie było linkiem, nie byłoby klikalne bez JavaScript.
Połączyłem także selektory :target wraz z atrybutem w CSS. To ostatecznie będzie miejsce, gdzie stopniowo wzmocnimy menu hamburgera za pomocą JavaScript, aby nie przeskakiwało do nagłówka po kliknięciu – unikając zastrzeżenia, o którym wspomniałem wcześniej. Posiadanie JavaScriptu porywającego zachowanie hash przeglądarki oznacza, że pseudo-klasa :target nie będzie już działać. Kiedy to się stanie, skorzystamy z atrybutu, aby stylizować przełączanie za pomocą wartości true/false, tak jak mogliśmy to zrobić w przeszłości z klasami.
W międzyczasie jednak, działa to pięknie bez JavaScriptu.
Dodałem zapytanie medialne @supports, aby dostarczyć preferowane position:fixed CSS do przeglądarek (zarówno mobilnych jak i desktopowych), które je obsługują. W przeciwnym razie, kiepskie przeglądarki i urządzenia – patrzę na ciebie iOS – dostaną position:absolute.
Krok 5: Style dla większych ekranów
Ponieważ nie chcemy, aby menu hamburgera wyświetlało się na urządzeniach niemobilnych (lub ogólnie na większych ekranach), dodamy niezbędne media query. Następnie wystylizujemy je tak, aby wyglądało jak pozioma nawigacja:
Wynik: