Opóźnione zwijanie drop-down menu przy pomocy CSS transitions
Rozwiązałem dzisiaj zupełnym przypadkiem dwa problemy związane z niedorozwinięciem CSS-a na jakie trafiam co jakiś czas. Istnieje pewne prawdopodobieństwo, że komuś przyda się moje rozwiązanie, więc o to i ono.
Miałem dzisiaj za zadanie stworzyć typowe drop-down menu rozwijające się po najechaniu. Typowa sytuacja. Ze względów estetycznych otwieranie pozycji powinno się animować, a ze względów UX nie powinno zwijać się od razu po zjechaniu myszką, bo przecież nikt tego nie lubi. Z lenistwa też, niechęci do scriptaculousa i możliwości wymuszenia przeglądarki postanowiłem wszystko zrobić za pomocą CSS transitions. Załóżmy, że stworzyłem sobie taki kod HTML:
<ul id="menu"> <li> <span>Kaczka</span> <ul> <li>dzióbek</li> (...) </ul> </li> <li> <span>Donald</span> <ul> (...) </ul> </li> (...) </ul>
Pierwszy problem na który trafiłem to niemożliwość tworzenia przejść do height: auto, a nie znam wysokości listy opcji. Googiel pomógł podpowiadając, że mogę zrobić przejście dla max-height. Np. tak:
#menu ul { max-height: 0; overflow: hidden; transition: max-height 0.5s ease-in-out; } #menu :hover ul { max-height: 1000px; }
Gdzie 1000px to jakaś wartość, którą możemy przyjąć za bezpieczny szacunek maksymalnej wysokości listy opcji. W wielu przypadkach jednak to rozwiązanie ma spory minus – wizualnie submenu zaczyna nam się zwijać po bliżej nieokreślonym czasie. Ale zaraz… Przecież tego właśnie chciałem – żeby menu zwijało mi się dopiero po chwili od opuszczenia jego obszaru.
I tak właśnie powstał Chocapic (działający przykład).
Rozwiązanie oczywiście idealne nie jest (wspomniany nieokreślony czas na zwinięcie i gubienie hovera od razu po zjechaniu, jeszcze przed zwinięciem) i tam gdzie jakość rozwiązania jest najważniejsza bym go nie polecał. Mi jednak w pełni wystarczyło i spodobała mi się jego prostota.
Przewidując nadchodzące pytania – tak mamy opcję delay dla transition, ale jej użycie spowodowałoby również opóźnienie na starcie (przy rozwijaniu), czego byśmy nie chcieli.
Czy mamy jakiś wpływ na opóźnienie zwijania? Tak. Im większy max-height wybierzemy, tym później menu zacznie nam się zwijać. Skutkiem ubocznym będzie też przyszypszenie™ samej animacji, co jest kolejną niedogodnością.
Podobne wpisy:






Spróbuj jeszcze pokombinować z dostępnością, bo na urządzeniach dotykowych to menu jest zestawem 3 linków i tylko tym.
Akurat na swoją obronę mam to, że rozpatrywany case był typowo intranetowy i miałem, tak jak napisałem, pełną władzę nad doborem przeglądarki :).
Z drugiej strony racja, że nie mam w ogóle doświadczenia z mobile’ami i będę musiał w tym kierunku się doszkolić.
Nie chodzi tylko o mobile – masz przecież nawet laptopy z matrycą dotykową :-) no i oczywiście tablety. Czyli wystarczyłoby obsługiwać nie tylko :hover, ale też kliki, np. przez dodanie linków z kotwicami i dla css :target.
Kliki przez :target, to raczej kiepski pomysł, bo menu nie zniknie o ile nie klikniemy w jakiś link, bądź nie przeedytujemy ręcznie URL-a. Chyba, że jest jakieś sensowne rozwiązanie tego problemu?
Do opóźnienia na animacji (transition-delay) spokojnie można użyć 2 różnych wartości dla zwijania i rozwijania:
W ten sposób przy rozwijaniu opóźnienie wyniesie 0 (delay nadpisany w :hover), a przy zwijaniu 3s (z transition na stylu bez hover).
Ale oczywiście nie rozwiązuje to problemu z brakiem możliwości animowania do nieznanej pełnej wysokości elementu.
Ciekawe. Nie pomyślałem o tym. Może się przydać do innych rzeczy.
No dobra ale co z dostępnością na IE? Na IE7, IE8 nie działa, a na IE9 nie ma animacji rozwijania.
Tak jak napisałem we wpisie – skorzystałem z takiego rozwiązania z tego względu iż mogłem wymusić nowoczesną przeglądarkę (system intranetowy). Rzecz jasna trzeba byłoby go poprawić dla IE6/7/8 i pewnie całej masy innych przeglądarek, ale nie o tym był wpis.
Jeśli chodzi o to, że pod IE9 nie ma animacji rozwijania – bardzo mi przykro ;) Łączę się z użytkownikami IE9 w bólu.
Fakt, moje przeoczenie. A już chciałem pisać, że rozwiązanie jest bezużyteczne ;)
No bo w zasadzie trochę jest ;) Liczba przypadków użycia nie jest zbyt duża.