Nastoletni
Programiści

Logo Nastoletnich Programistów

Rozwijane menu mobilne w czystym CSSie

Witajcie! W tym poradniku pokażę wam w jaki sposób przy użyciu czystego CSSa zrobić rozwijane menu, będące jednym z najpospolitszych rozwiązań nawigacji na urządzeniach mobilnych.

Zaprezentowany sposób nada się także do podobnych zastosowań, jak chociażby znany z for internetowych [spoiler]

Zasada działania

Cała filozofia działania opiera się na input[type="checkbox"] wraz z label’em. Checkbox chowamy, label stylujemy na przycisk lub odnośnik, a w CSSie pokazujemy i chowamy zawartość menu przy użyciu pseudoklasy :checked oraz selektora rodzeństwa ~.

Dla checkboxa warto profilaktycznie dodać atrybut autocomplete z wartością off, aby zapobiec przeglądarce wczytywaniu mu zaznaczenia z historii wypełnianych formularzy. Gwoli dostępności, nadamy checkboxowi aria-hidden="true", aby czytniki ekranowe go ignorowały.

Podrasuję graficznie nasze menu, aby na potrzeby poradnika rzeczywiście przypominało menu, a nie było paroma szeryfowymi linijkami tekstu:

Coś milszego dla oka

Menu działa, jednak pojawia się od razu, bez żadnej animacji. Animację można oczywiście zrobić w JSie. Prawda? Oczywiście, że można, ale my to zrobimy w CSSie. Bo można i to od dawna.

Załóżmy, aby animacja była taka sama jak na stronie na której to teraz czytasz w momencie pisania tego posta. Czyli obok tekstu „Rozwiń menu” dwa trójkąty wskazujące kierunek w który podąży menu przy kliknięciu. W dół gdy jest zwinięte i w górę gdy rozwinięte. Do tego niech rozsuwa się nie w jednej klatce, a interpoluje w, załóżmy, pół sekundy.

Na początek dodam pseudoelementami :before i :after oraz atrybutem content te trójkąciki. Jest to zwykły znak Unicode, możesz go skopiować: ▼.

Gdy checkbox jest zaznaczony (a więc menu rozsunięte) trójkącik powinien mieć wierzchołek zwrócony ku górze. Możemy po prostu zmienić content na inny trójkącik, albo, co jest IMO milsze dla oka, obrócić go ku górze, również interpolując rotacją przez pół sekundy. Zrobimy to przez nadanie transform: rotate(180deg) oraz -180deg odpowiednio dla :before oraz :after. Aby transformacja ta była animowana, dodajmy transition: transform .5s linear.

Animowanie rozsuwania się menu jest natomiast w czystym CSSie rzeczą ciut trudniejszą do osiągnięcia. Aby interpolować między dwiema wartościami, obie muszą być ustalone. A więc height gdy checkbox nie jest zaznaczony powinien mieć wartość 0, natomiast gdy zaznaczony – no właśnie, jaką powinien mieć wartość? Do wartości autoinherit czy initial nie można interpolować, a z poziomu CSSa nie znamy wysokości tego elementu. Ja widzę w tym przypadku jedno wyjście. Animować nie heightmax-height, gdzie tą drugą wartość należy ustawić na taką, która będzie realną górną granicą wysokości tego elementu. Im większa będzie różnica między wartością max-height a realną wysokością elementu nawigacji, tym większy będzie odstęp czasu między końcem animacji a osiągnięciem przez nawigacji pełnej długości.

To wszystko opakowane w kod prezentuje się następująco:

Jeżeli macie jakieś pytania zadajcie je w komentarzu, postaram się odpowiedzieć na każde 🙂

Albert

Główny admin Nastoletnich Programistów. Czuje się dobrze w webdeveloperce. Lubi jeździć na rowerze. Na co dzień uczeń technikum informatycznego.

Zobacz wszystkie posty tego autora →

Komentarze

  • Mam w sumie dwa pytania:

    1) Jak z dostępnością takiego rozwiązania? Bo dla czytników ekranowych wszak jest to po prostu pole formularza…
    2) [autocomplete] dla checkboxa? Widziałeś kiedyś autouzupełnianie czegoś, co ma jedynie stan on/off? 😛

    • Ad. 1) Rzeczywiście, zapomniałem o tej kwestii. aria-hidden powinno załatwić sprawę, jako że label już jest

      Ad. 2) Podczas robienia researchu znalazłem to pytanie. Co prawda jest z ’08 roku, jednak wziąłem ten przypadek pod uwagę, na wszelki wypadek.

  • Janek

    Może jakiś poradnik do menu w css, jak zrobić żeby się zmniejszało w takie rozwijane jak się nie mieści w jednej linii?

    • Na yt Alberta masz poradnik z tego co pamiętam 😀 Aczkolwiek filozofii w tym wielkiej nie ma, a słowem kluczem będzie @media queries 😀

    • CSS nie wie o szerokości elementów, stąd też nie dałoby się określić czy menu się w jednej linii mieści czy nie. Można natomiast osiągnąć podobny efekt przy użyciu media queries i określeniu szerokości przy której menu ma się „złamać”. Nagrałem poradnik pokazujący jak zrobić takie menu: https://youtu.be/tN2qnLIumek

  • JakubSerwatka

    Nawet spoko. Sam robię menu w css na zasadzie a:hover bo to fajne na mobilnych działa (ale tylko na mobilnych)

  • Rekseto

    divitis! cieżka choroba… div navigation zamien na nav i w navie umieszczamy tylko liste czyli nav>ul>li>a.. Naprawde jesli masz uczyc ludzi zlych praktyk to nie ucz
    (Menu – Lista wyboru – Dostepnosc)

    • Ależ to jest poradnik jak zrobić rozwijane menu. To nie musi być koniecznie nawigacja 🙂 Może to być dowolny rozwijany blok, jak chociażby spoiler znany z for internetowych. Ale na Twoją uwagę lekko uogólnię tytuł, żeby uniknąć niejasności.