
Egy fokozatosan továbbfejlesztett, JavaScript nélkül működő mobil menü építése
Legutóbb frissítve: 2019. január 21.
A Pure CSS Off-Canvas Hamburger Menu nem új keletű felfedezés. Elvégre Chris Coyier már 2012 novemberében írt erről a technikáról.
- Ha ez egy régi trükk számodra, akkor tarts velem egy kicsit. Továbbfejlesztettem Chris példáját, és örülnék a visszajelzésednek.
- Ha ez új neked, ne aggódj. Rengeteg társaságod van, mivel úgy tűnik, hogy a web nagy része még nem igazán fogta fel.
Ezzel egy egyszerű, reszponzív off-canvas hamburger menüt fogunk építeni, csak CSS-t használva, amit könnyű lesz beépíteni a saját projektedbe. De előbb…
Mi a baj a JavaScript-szel?
Semmi.
Aaron Gustafson jobban elmagyarázza a Progressive Enhancements fontosságát és a JavaScript szerepét a webfejlesztésben, mint én valaha is tudnám. Érdemes elolvasni a bejegyzését. De a rövidsége kedvéért megpróbálom összefoglalni:
- “Az alapfeladatokat mindig el lehet végezni JavaScript nélkül.”
- Az alapfeladatokat a legstabilabb rétegen (azaz nem a JavaScripten) kell elvégezni.”
- A Progressive Enhancements nem JavaScript-ellenes. Csak arról szól, hogy a megfelelő technológiákat a megfelelő rétegen kell alkalmazni.
- “Mivel van rá némi esély, hogy a JavaScript nem fog futni, mindig számolnunk kell ezzel az eséllyel.”
- Soha nem jó ötlet figyelmen kívül hagyni a potenciális felhasználókat.
- A Progressive Enhancements csak jó mérnöki munka.
Szóval, annyit fogunk tenni, amennyit csak tudunk HTML és CSS segítségével. Aztán hagyjuk, hogy a JavaScript egy alkalmasabb rétegben tegye a dolgát – javítva a már meglévő felhasználói felületet.
1. lépés: HTML
Amint azt talán tudod, az első lépés mindig egy szilárd, jól átgondolt HTML alapréteg megírása.
Megjegyzem: példámban Font Awesome-ot használok az ikonokhoz.
Meglehetősen szabványosnak tűnik, igaz? Megvan:
- A szülő <header> elemünk
- A hamburger (“fa-bars”) ikonja
- Egy főcím (vagy esetleg egy logó)
- A navigáció egy <nav> elemben
- Egy bezáró ikon (“fa-close”) a navigáción belül (erről bővebben később)
- Egy “háttér” a navigáció után. Miért van ez egy anchor tag? Majd később elmagyarázom.
2. lépés: Tegyük elérhetőbbé
A hozzáférhetőség soha nem lehet egy utólagos gondolat – például az alkalmazás megírása után. Már a kezdetektől fogva meg kell tervezni. Néhány alapvető megfontolás mostani hozzáadása nem csak az oldalad általános hozzáférhetőségét fogja javítani, hanem neked (a fejlesztőnek) jobb jelölést biztosít, amit a JavaScriptben felhasználhatsz!
Ezek után hozzáadunk még néhány attribútumot és néhány, csak a képernyőolvasók számára elérhető szöveget:
Itt van egy gyors bontás mindezen attribútumokról és azok működéséről:
- Egyedi azonosítókat adtunk hozzá a HREF-jeink célzásához (ennek működéséről később lesz szó).
- A képernyőolvasók számára informatív feliratot adtunk a gomboknak a .
- Elrejtettük az ikonokat a képernyőolvasók elől a , mert ezek vizuális ábrázolások, és csak a képernyőolvasók számára elérhető szöveget adtunk a <span class=”sr-only”> elemekkel.
- A “hátteret” kivettük a lapozóindexből a . segítségével, ez tisztán vizuális jellegű, és nem akarjuk összezavarni a látássérült és csak billentyűzetet használó felhasználóinkat.
- A “háttér” kezdeti (és szemantikai) állapotának beállításához hozzáadtuk a csodálatos attribútumot. Nincs több szemét – milyen izgalmas!
Itt az eddigi eredmény:

3. lépés: Stílusosítsuk!
Először mobilról közelítjük meg a dolgot, ezért üssük ki a mobilos, “hamburgeres” nézetet (az érdekes részt).
Először csak a fejléc elrendezését alakítsuk ki (interaktivitás nélkül):
Az eredmény:

4. lépés: Interaktivitás tiszta CSS-szel
A widgetek CSS-szel való interaktívvá tételénél több lehetőséged van:
- Rádiók vagy checkboxok használata
- A :target pszeudo-osztály használata.
A rádiók és checkboxok elképesztően jól működnek a legtöbb widgetnél, például a lapok, modálok, legördülő ablakok és harmonikák esetében. Chris Coyier ezt a technikát “a checkbox hack”-nek nevezte el. Több fejlesztő is használta ezt a “hacket” az off-canvas menükhöz, például Paul Lewis bemutatója a Chrome Dev Summit-on vagy Luis Manuel morfózó hamburger menüje.
A :target pszeudo-osztály azonban szemantikusabb ebben a felhasználási esetben, mivel közvetlenül a navigációval foglalkozunk. Lehet, hogy nem értesz egyet, és ez teljesen rendben van! Hihetetlenül egyszerű és tökéletesen elfogadható lenne a :target pszeudo-osztályt egy checkboxra cserélni.
Bár mindkét technikának megvannak a maga fenntartásai.
A checkbox használata:
- Követeli, hogy a JavaScript bezárja az off-canvas menüt, ha a menüben lévő egyik link egy horgonykapcsolat volt ugyanannak az oldalnak egy adott részéhez.
- Követeli, hogy a <input> mező a menü testvére legyen, vagy legalábbis a menü ősének testvére. Más szóval a CSS egy kicsit trükkösebb. A <label> (akár több címke) azonban máshol is lehet.
- A <label> elem nem lesz közvetlenül fókuszálható vagy tabulátorozható, ami némileg trükkösebb CSS-t igényel a jelölőnégyzet fókuszának kezeléséhez, miközben a <label> látható megjelenése megváltozik.
- A menü nyitása/zárása körüli billentyűzetes navigáció furcsa lesz. A jelölőnégyzet állapotváltozásának befolyásolása a nem a billentyűzeten keresztül történik. Míg a vak felhasználók megérthetik, hogy a widgetet egy jelölőnégyzet működteti, a látó billentyűzetfelhasználók zavarba jönnek, mivel a jelölőnégyzet nem látható – amit ebben a felhasználási esetben úgy éreztem, hogy ez a probléma megoldhatatlan.
A :target pszeudo-osztály használata:
- A canvason kívüli menü megnyitását/bezárását a böngésző előzményeihez adja (a hash-t a címsorba tolja). Ennek (és a potenciálisan bosszantó, az oldal tetejére való ugrásnak) az elkerülése érdekében a JavaScript Event.preventDefault() futtatására lesz szükség.
És lehet, hogy vannak más figyelmeztetések is, amelyeket kihagytam. Akárhogy is, az, hogy melyik technikát választod, mind preferencia kérdése, mind pedig a projekted követelményeitől függ. Mindegy, elkalandoztam…
Itt van a CSS interaktív része:
Az eredmény kattintáskor:

Hogyan működik mindez
Lényegében a :target álosztály egy új “állapotot” ad nekünk a célzott navigáció stílusához. Ha a main-menu meg lett célozva (a hash-ja hozzá lett adva az URL-hez), akkor most már ki tudjuk csúsztatni a menüt. Ez egy kicsit olyan, mint egy :focus pszeudo-osztály a megcélzott elemhez (nem magához a linkhez).
A “háttér” megjelenítését is lehetővé tettük, amikor a navigáció meg van célozva.
Láthatja, hogy a fő hamburger ikon a navigáció azonosítójához kapcsolódik, míg mind a bezárás ikon, mind a háttér gombok a fő hamburger ikonhoz kapcsolódnak. Ez lehetővé teszi számunkra, hogy a bezár ikonra vagy a háttérre kattintva eltávolítsuk a “fókuszt” – vagy valójában :target – a navigációról. Ha a háttér nem lenne link, akkor JavaScript nélkül nem lenne kattintható.
A :target szelektorokat is láncoltam az attribútummal együtt a CSS-ben. Ez lesz végül az a hely, ahol fokozatosan javítjuk a hamburger menüt JavaScript segítségével, hogy ne ugorjon a fejlécre kattintáskor – elkerülve a korábban említett figyelmeztetést. Azzal, hogy a JavaScript eltéríti a böngésző hash viselkedését, a :target pszeudo-osztály többé nem fog működni. Ha ez megtörténik, kihasználjuk majd az attribútum előnyeit, hogy a váltást igaz/hamis értékekkel stilizáljuk, hasonlóan ahhoz, ahogyan azt korábban az osztályokkal tehettük.
Addig is azonban ez gyönyörűen működik JavaScript nélkül is.
Hozzáadtam a @supports médiakérdést, hogy a preferált position:fixed CSS-t az azt támogató böngészők (mind mobil, mind asztali) számára biztosítsam. Ellenkező esetben a béna böngészők és eszközök – rád nézek iOS – position:absolute-t kapnak.
5. lépés: Nagyobb képernyőstílusok
Mivel nem akarjuk, hogy a hamburger menü megjelenjen a nem mobil eszközökön (vagy általában a nagyobb képernyőkön), hozzáadjuk az ehhez szükséges médiakérdést. Ezután úgy stilizáljuk, hogy úgy nézzen ki, mint egy vízszintes navigáció:
Az eredmény:

Voila! Készen vagyunk!
Összeillesztés
Itt a végleges HTML:
Itt a végleges CSS:
Demo
Kipróbáld magad a CodePen-emmel:
→ Pure CSS Hamburger Menu JavaScript nélkül.
Megjegyzem: a menü checkbox változatát is demózhatod.
Szükséged van JavaScriptre, hogy még dörzsöltebb legyen?
Míg az off-canvas menüt teljesen CSS-szel is működőképessé tehetjük – javítva a teljesítményét és megbízhatóságát -, addig a JavaScriptre továbbra is szükségünk lesz, hogy valamilyen módon segítsen a mindkét technika hátrányait körülvevő interaktivitás javításában. JavaScriptet használhatunk arra is, hogy megakadályozzuk a görgetést az oldalon, amíg a menü nyitva van.
Azt is érdemes megjegyezni, hogy a hozzáférhetőség egy tisztességes (és vitathatatlanul a legfontosabb) szintje elérhető JavaScript nélkül is. Nehéz azonban robusztus szintű hozzáférhetőséget biztosítani a JavaScriptnek a DOM manipulálására való képessége nélkül (pl. fókuszkezelés, ARIA-attribútumok frissítése stb.).
A weboldal hozzáférhetőségének JavaScript segítségével történő javításáról további információkért tekintse meg a következő cikkeket:
- Az ARIA-attribútumok használata a JavaScript állapotbeállításához & stilizálás
- A JavaScript írása a hozzáférhetőség szem előtt tartásával
Van más gondolata vagy javaslata?
Szívesen meghallgatnám a megjegyzéseit a tiszta CSS hamburgermenüvel kapcsolatos megközelítésemmel kapcsolatban.
Szerkesztések és későbbi eszmefuttatások
2019. január 21.: Szerkesztettem a cikket és frissítettem a kódpéldákat a felesleges ARIA-attribútumok eltávolítása és a hozzáférhetőség javítása érdekében.
Amint többet tanultam az ARIA használatáról és általában az & akadálymentességi tesztelés fejlesztéséről, rájöttem néhány dologra:
- A JavaScriptnek határozottan megvan a helye, és minden robusztus akadálymentesítési UI-mintának része kell, hogy legyen.
- Az ARIA-jelzők kivételével a JavaScript szükséges az ARIA megfelelő használatához. És, sok attribútumot használtam, mint például jobb hagyni JavaScript hozzáadása egyszer betöltött helyett hozzáadása közvetlenül a jelölés. Ez a koncepció követi a jó Progressive Enhancement gyakorlatokat – az ARIA állapotok és tulajdonságok a JavaScript mellett egy frissítés, és külön rétegben kell kezelni.
- Előtte nem kezeltem megfelelően a fókuszt, mivel a fókusz eltűnt, ahogy a vizuálisan rejtett linkeken keresztül haladt (amikor összecsukva). Hozzáadtam egy display: none; -t a menü CSS-éhez, hogy ezt kijavítsam.
Szóval, ha a Pure CSS Off-Canvas Hamburger menü korábbi verzióját valósítottad meg, kérlek, fontold meg a frissítést erre az egyszerűbb és könnyebben hozzáférhető verzióra!