Responsiv, ren CSS off-canvas hamburgermenu uden for lærred

, Author

Sidst opdateret den 21. januar 2019.

Rene CSS off-canvas hamburgermenuer er ikke en nyere opdagelse. Chris Coyier skrev trods alt om denne teknik tilbage i november 2012.

  • Hvis dette er et gammelt trick for dig, så hænger du lidt med mig. Jeg har forbedret Chris’ eksempel, og jeg vil gerne have din feedback.
  • Hvis dette er nyt for dig, skal du ikke bekymre dig. Du har masser af selskab, da det ser ud til, at en stor del af internettet faktisk ikke har fattet det endnu.

Med det vil vi bygge en simpel, responsiv off-canvas hamburgermenu udelukkende ved hjælp af CSS, som vil være let at indarbejde i dit eget projekt. Men først…

Hvad er der galt med JavaScript?

Ingen.

Aaron Gustafson forklarer betydningen af Progressive Enhancements og JavaScript’s rolle i webudvikling bedre, end jeg nogensinde kunne. Du bør læse hans indlæg. Men for at gøre det kortfattet vil jeg forsøge at opsummere det:

  • “Kerneopgaver kan altid løses uden JavaScript.”
  • Kerneopgaver bør udføres på det mest stabile lag (dvs. ikke JavaScript).
  • Progressive Enhancements er ikke anti-JavaScript. Det handler bare om at omfavne de rigtige teknologier på det rigtige lag.
  • “Fordi der er en vis chance for, at JavaScript ikke kan køre, skal vi altid tage højde for den chance.”
  • Det er aldrig en god idé at ignorere potentielle brugere.”
  • Progressive Enhancements er bare god teknik.”

Så, vi vil gøre så meget som muligt med HTML og CSS. Derefter lader vi JavaScript trylle på et mere passende lag – og forbedrer den allerede eksisterende brugergrænseflade.

Stræk 1: HTML

Som du måske ved, er det første skridt altid at skrive et solidt, velgennemtænkt grundlag af HTML.

Bemærk: Jeg bruger Font Awesome til ikonerne i mit eksempel.

Stræk 1: Initial HTML til en ren CSS responsiv hamburgermenu

Det ser ret standard ud, ikke? Vi har:

  • Vores overordnede <header>-element
  • Hamburger-ikonet (“fa-bars”)
  • En hovedoverskrift (eller potentielt et logo)
  • Navigationen i et <nav>-element
  • Et lukkeikon (“fa-close”) inde i navigationen (mere om dette senere)
  • En “baggrund” efter navigationen. Hvorfor er det et ankertag? Det vil jeg forklare senere.

Stræk 2: Lad os gøre det mere tilgængeligt

Accessibility bør aldrig være en eftertanke – som efter at du har skrevet din applikation. Den skal planlægges fra starten. Hvis du tilføjer et par grundlæggende overvejelser nu, vil det ikke kun forbedre den overordnede tilgængelighed på dit websted, men det vil også give dig (udvikleren) bedre markup at bruge i dit JavaScript!

Dermed vil vi tilføje et par attributter mere og noget tekst til skærmlæsere:

Stræk 2: Forbedring af HTML’en, så den bliver mere tilgængelig.

Her er en hurtig oversigt over alle disse attributter, og hvordan de fungerer:

  • Vi har tilføjet unikke ID’er til at målrette vores HREF’er (mere om, hvordan det fungerer senere).
  • Vi har givet en informativ etiket for knapperne til skærmlæsere ved hjælp af .
  • Vi har skjult ikonerne for skærmlæsere med , fordi de er visuelle repræsentationer, og vi har tilføjet tekst kun for skærmlæsere med <span class=”sr-only”>-elementerne.
  • Vi har taget “baggrunden” ud af tabulatorindekset med et . Det er rent visuelt af natur, og vi ønsker ikke at forvirre vores synshandicappede og tastaturbrugere.
  • Vi har tilføjet attributten amazing for at indstille den indledende (og semantiske) tilstand for “baggrunden”. Ikke mere skrald – hvor spændende!

Her er resultatet indtil videre:

Figur 1: Resulterende visning af HTML efter trin 1 og 2.

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):

Strin 3: Tilføj noget CSS for at style overskriften (uden interaktivitet, indtil videre).

Resultatet:

Figur 2: Resultatvisning af HTML & CSS efter trin 3.

Strin 4: Interaktivitet med ren CSS

Når du gør widgets interaktive med CSS, har du et par muligheder:

  1. Brug radioer eller afkrydsningsfelter
  2. 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:

Stræk 4: Tilføj noget CSS til interaktiviteten.

Resultatet, når der klikkes:

Figur 3: Resultatet af visningen af hamburgermenuen, når den åbnes.

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:

Stræk 5: CSS til stilisering af navigationen på større skærme.

Resultatet:

Figur 4: Resulterende visning af navigationen stylet til større skærme.

Voila! Vi er færdige!

Samlet set

Her er den endelige HTML:

Den endelige HTML for den responsive hamburgermenu, der kun bruger CSS.

Her er den endelige CSS:

Den endelige CSS for den responsive hamburgermenu.

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:

  1. JavaScript har helt sikkert sin plads og bør være en del af ethvert robust tilgængeligheds-UI-mønster.
  2. 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.
  3. 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.
  4. 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!

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.