Stræk 3: Lad os style det!
Vi skal gribe det her mobilt an først, så lad os få styr på den mobile, “hamburgeragtige” visning (den interessante del).
Først skal vi bare have layoutet overskriften rigtigt (uden interaktivitet):
Resultatet:
Strin 4: Interaktivitet med ren CSS
Når du gør widgets interaktive med CSS, har du et par muligheder:
- Brug radioer eller afkrydsningsfelter
- Brug pseudoklassen :target.
Radioer og afkrydsningsfelter fungerer forbløffende godt til de fleste widgets, f.eks. faner, modaler, dropdowns og harmonikaer. Chris Coyier har døbt denne teknik “checkbox-hacket”. Flere udviklere har brugt dette “hack” til deres menuer uden for lærredet, f.eks. i Paul Lewis’ tutorial til Chrome Dev Summit eller Luis Manuels morphing hamburgermenu.
Pseudoklassen :target er imidlertid mere semantisk i dette tilfælde, da vi har direkte med navigation at gøre. Du er måske uenig, og det er helt ok! Det ville være utrolig nemt og helt acceptabelt at udskifte pseudoklassen :target med en afkrydsningsboks.
Begge teknikker har dog deres forbehold.
Ved brug af en afkrydsningsboks:
- Kræver, at JavaScript lukker off-canvas-menuen, hvis et af linkene i menuen var et ankerlink til et bestemt afsnit på samme side.
- Kræver, at <input>-feltet er en søskende til menuen eller i det mindste en søskende til menuens forfader. Med andre ord er CSS’en lidt mere tricky. Du kan dog godt have <label> (endda flere labels) et andet sted.
- <label>-elementet vil ikke kunne fokuseres eller tabuleres direkte, hvilket kræver noget lidt mere tricky CSS til håndtering af fokus på afkrydsningsfeltet, samtidig med at <label>s synlige udseende ændres.
- Tastaturnavigationen omkring åbning/lukning af menuen vil være skæv. Påvirkning af en tilstandsændring på en afkrydsningsboks sker via den og ikke via tasten. Mens blinde brugere måske forstår, at widgeten betjenes af en afkrydsningsboks, vil seende tastaturbrugere blive forvirrede, da afkrydsningsboksen ikke er tydelig – noget, jeg følte var en deal breaker i denne brugssituation.
Anvendelse af pseudoklassen :target:
- Føjer åbning/lukning af menuen uden for lærredet til browserhistorikken (skubber hash’en ind i adresselinjen). Det vil kræve, at JavaScript kører Event.preventDefault() for at undgå dette (og det potentielt irriterende spring til toppen af siden).
Og der kan være andre forbehold, som jeg har overset. Uanset hvad, så er valget af teknik både et spørgsmål om præferencer og underlagt dit projekts krav. Nå, men jeg er kommet lidt væk…
Her er den interaktive del af CSS’en:
Resultatet, når der klikkes:
Sådan fungerer alt dette
Pseudoklassen :target giver os i bund og grund en ny “tilstand” til styling af den målrettede navigation. Når main-menu er blevet målrettet (med dens hash tilføjet til URL’en), kan vi nu skubbe menuen ud. Det er lidt ligesom en :focus-pseudoklasse for det målrettede element (ikke selve linket).
Vi har også givet “baggrunden” mulighed for at blive vist, når navigationen er målrettet.
Du vil bemærke, at hovedhamburgerikonet er knyttet til navigationens ID, mens både lukkeikonet og baggrundens knapper er knyttet til hovedhamburgerikonet. Dette giver os mulighed for at klikke på lukkeikonet eller baggrundsknappen for at fjerne “fokus” – eller egentlig :target – fra navigationen. Hvis baggrunden ikke var et link, ville den ikke kunne klikkes uden JavaScript.
Jeg har også kædet :target-selektorerne sammen med attributten i CSS’en. Det vil i sidste ende være her, hvor vi gradvist forbedrer hamburgermenuen med JavaScript, så den ikke hopper til overskriften, når der klikkes på den – så vi undgår det forbehold, jeg nævnte tidligere. Når JavaScript kaprer browserens hash-adfærd, betyder det, at pseudoklassen :target ikke længere vil fungere. Når det sker, vil vi udnytte attributten til at style toggling med true/false-værdier på samme måde som vi tidligere kunne have gjort det med klasser.
I mellemtiden fungerer det dog fint uden JavaScript.
Jeg har tilføjet @supports media query for at give den foretrukne position:fixed CSS til de browsere (både mobil og desktop), der understøtter det. Ellers får lamme browsere og enheder – jeg kigger på dig iOS – position:absolute.
Stræk 5: Stile til større skærme
Da vi ikke ønsker, at hamburgermenuen skal vises på ikke-mobile enheder (eller større skærme generelt), tilføjer vi det nødvendige media query til det. Derefter stiliserer vi den, så den ligner en vandret navigation:
Resultatet:
Voila! Vi er færdige!
Samlet set
Her er den endelige HTML:
Her er den endelige CSS:
Demo
Afprøv selv min CodePen:
→ Ren CSS Hamburgermenu uden JavaScript.
Bemærk: Du kan også demonstrere afkrydsningsboksversionen af menuen.
Vil du tilføje JavaScript for at gøre det smartere?
Selv om vi kan få off-canvas-menuen til at fungere udelukkende med CSS – hvilket forbedrer dens ydeevne og pålidelighed – har vi stadig brug for JavaScript til at hjælpe på en eller anden måde for at forbedre interaktiviteten omkring begge teknikers ulemper. Du kan også bruge JavaScript til at forhindre scrolling på siden, mens menuen er åben.
Det er også værd at bemærke, at der kan opnås et rimeligt niveau (og vel nok det vigtigste niveau) af tilgængelighed uden JavaScript. Det er imidlertid vanskeligt at levere et solidt tilgængelighedsniveau uden JavaScript’s evne til at manipulere DOM (f.eks. fokusstyring, ARIA-attributopdateringer osv.).
For mere information om forbedring af dit websteds tilgængelighed via JavaScript kan du læse følgende artikler:
- Brug af ARIA-attributter til JavaScript-tilstandssætning & styling
- Skrivning af JavaScript med tilgængelighed i tankerne
Har du andre tanker eller forslag?
Jeg vil meget gerne høre dine kommentarer med min tilgang til en ren CSS-hamburgermenu.
Redigeringer og senere grublerier
21. januar 2019: Redigeret artikel og opdateret kodeeksempler for at fjerne unødvendige ARIA-attributter og forbedre tilgængeligheden.
I takt med at jeg har lært mere om brug af ARIA og udvikling & af test for tilgængelighed generelt, er jeg blevet klar over et par ting:
- JavaScript har helt sikkert sin plads og bør være en del af ethvert robust tilgængeligheds-UI-mønster.
- Med undtagelse af ARIA-landemærker er JavaScript påkrævet for at kunne bruge ARIA korrekt. Og mange af de attributter, jeg har brugt, som er bedre overladt til JavaScript til at tilføje, når de er indlæst, i stedet for at tilføje det direkte i markup’en. Dette koncept følger god praksis for progressiv forbedring – ARIA-tilstande og -egenskaber sammen med JavaScript er en opgradering og bør håndteres på et separat lag.
- Tidligere håndterede jeg ikke fokus korrekt, da fokus ville forsvinde, når det bevægede sig gennem de visuelt skjulte links (når de var sammenklappet). Jeg tilføjede en display: none; til menuens CSS for at rette dette.
Så, hvis du har implementeret en tidligere version af min Pure CSS Off-Canvas Hamburger Menu, så overvej venligst at opdatere den til denne enklere og mere tilgængelige version!