Responsive, Pure CSS Off-Canvas Hamburger Menu

, Author

Last bijgewerkt op 21 januari 2019.

Pure CSS off-canvas hamburger menu’s zijn niet een recente ontdekking. Chris Coyier schreef immers al in november 2012 over deze techniek.

  • Als dit een oude truc voor je is, blijf dan nog even bij me. Ik heb het voorbeeld van Chris verbeterd en zou graag je feedback horen.
  • Als dit nieuw voor je is, maak je dan geen zorgen. Je hebt genoeg gezelschap, want het lijkt erop dat een groot deel van het web dit nog niet doorheeft.

Met dat, gaan we een eenvoudig, responsief off-canvas hamburger menu bouwen met alleen CSS, dat gemakkelijk in je eigen project te integreren is. Maar eerst…

Wat is er mis met JavaScript?

Niks.

Aaron Gustafson legt het belang van Progressive Enhancements en de rol van JavaScript in webontwikkeling beter uit dan ik ooit zou kunnen. Je zou zijn post moeten lezen. Maar om het kort te houden, zal ik proberen het samen te vatten:

  • “Kerntaken kunnen altijd worden uitgevoerd zonder JavaScript.”
  • Kerntaken moeten worden uitgevoerd op de meest stabiele laag (dus niet JavaScript).
  • Progressive Enhancements is niet anti-JavaScript. Het gaat gewoon om het omarmen van de juiste technologieën op de juiste laag.
  • “Omdat er een kans is dat JavaScript niet werkt, moeten we altijd rekening houden met die kans.”
  • Het is nooit een goed idee om potentiële gebruikers te negeren.
  • Progressive Enhancements is gewoon goede engineering.

Dus, we gaan zo veel mogelijk doen met HTML en CSS. Dan laten we JavaScript zijn magie doen op een meer geschikte laag – het verbeteren van de reeds bestaande UI.

Stap 1: HTML

Zoals je misschien weet, is de eerste stap altijd het schrijven van een solide, goed doordachte, basislaag van HTML.

Note: ik gebruik Font Awesome voor de pictogrammen in mijn voorbeeld.

Step 1: Initiële HTML voor een responsief hamburger-menu met pure CSS

Het ziet er nogal standaard uit, toch? We hebben:

  • Onze parent <header> element
  • Het hamburger (“fa-bars”) icoon
  • Een hoofd heading (of eventueel een logo)
  • De navigatie in een <nav> element
  • Een sluit icoon (“fa-close”) in de navigatie (later meer hierover)
  • Een “backdrop” na de navigatie. Waarom is het een anker-tag? Dat leg ik later uit.

Stap 2: Laten we het toegankelijker maken

Toegankelijkheid moet nooit een gedachte achteraf zijn – zoals nadat je je applicatie hebt geschreven. Het moet vanaf het begin worden gepland. Door nu een paar basisoverwegingen toe te voegen, verbetert niet alleen de algemene toegankelijkheid van uw site, maar krijgt u (de ontwikkelaar) ook betere markup om in uw JavaScript te gebruiken!

Daarmee gaan we nog een paar attributen en wat tekst voor schermlezers toevoegen:

Stap 2: De HTML toegankelijker maken.

Hier volgt een kort overzicht van al deze attributen en hoe ze werken:

  • We hebben unieke ID’s toegevoegd om onze HREF’s te kunnen richten (later meer over hoe dit werkt).
  • We hebben de knoppen van een informatief label voorzien voor schermlezers met .
  • We hebben de pictogrammen verborgen voor schermlezers met , omdat het visuele voorstellingen zijn, en alleen voor schermlezers bestemde tekst toegevoegd met de <span class=”sr-only”>-elementen.
  • We hebben de “achtergrond” uit de tabbing index gehaald met een . Het is puur visueel van aard en we willen onze visueel gehandicapte en toetsenbord-only gebruikers niet in verwarring brengen.
  • We hebben het amazing attribuut toegevoegd om de initiële (en semantische) status van de “achtergrond” in te stellen. Geen rommel meer – hoe spannend!

Hier is het resultaat tot nu toe:

Figuur 1: Resulterende weergave van de HTML na stappen 1 en 2.

Stap 3: Laten we het stijlen!

We gaan dit eerst mobiel benaderen, dus laten we de mobiele, “hamburger-y” weergave (het interessante deel) eruit halen.

Eerst gaan we alleen de layout van de header goed krijgen (zonder de interactiviteit):

Stap 3: Voeg wat CSS toe om de header te stijlen (zonder interactiviteit, voor nu).

Het resultaat:

Figuur 2: Resulterende weergave van de HTML & CSS na stap 3.

Stap 4: Interactiviteit met pure CSS

Wanneer u widgets interactief maakt met CSS, hebt u een paar opties:

  1. Gebruik radio’s of checkboxes
  2. Gebruik de :target pseudo-class.

Radio’s en checkboxes werken verbazingwekkend goed voor de meeste widgets, zoals tabs, modals, dropdowns en accordeons. Chris Coyier noemde deze techniek “de checkbox hack.” Verschillende ontwikkelaars hebben deze “hack” gebruikt voor hun off-canvas menu’s, zoals in Paul Lewis’ tutorial voor Chrome Dev Summit of Luis Manuel’s morphing hamburger menu.

De :target pseudo-class is echter semantischer in dit use-case, aangezien we direct te maken hebben met navigatie. Misschien bent u het daar niet mee eens, en dat is helemaal prima! Het zou ongelooflijk eenvoudig en volkomen aanvaardbaar zijn om de :target pseudo-klasse te verwisselen voor een selectievakje.

Een van beide technieken heeft echter zijn beperkingen.

Het gebruik van een checkbox:

  • Vraagt JavaScript om het off-canvas menu te sluiten als een van de links in het menu een anker-link was naar een specifieke sectie van dezelfde pagina.
  • Vraagt dat het <input> veld een sibling is van het menu of op zijn minst een sibling van de voorouder van het menu. Met andere woorden, de CSS is een beetje lastiger. U kunt de <label> (zelfs meerdere labels) elders hebben, dat wel.
  • Het <label> element zal niet direct focusable of tab-able zijn, wat wat iets lastigere CSS vereist voor het afhandelen van de focus op de checkbox terwijl de zichtbare verschijning van de <label> wordt veranderd.
  • De toetsenbord navigatie rond het openen/sluiten van het menu zal wat vreemd zijn. Het veranderen van de status van een checkbox gebeurt met de toets, niet met de toets. Hoewel blinde gebruikers misschien begrijpen dat de widget wordt bediend door een selectievakje, zullen gebruikers met een normaal gezichtsvermogen in de war raken omdat het selectievakje niet zichtbaar is – iets wat ik in dit geval een probleem vond.

Door gebruik te maken van de :target pseudo-class:

  • Wordt het openen/sluiten van het off-canvas menu toegevoegd aan de browsergeschiedenis (door de hash in de adresbalk te plaatsen). JavaScript moet Event.preventDefault() uitvoeren om dit te voorkomen (en het mogelijk vervelende springen naar de bovenkant van de pagina).

En misschien zijn er nog andere beperkingen die ik over het hoofd heb gezien. Hoe dan ook, de keuze voor een bepaalde techniek is een kwestie van voorkeur en hangt af van de vereisten van uw project. Maar goed, ik dwaal af…

Hier is het interactieve deel van de CSS:

Stap 4: Voeg wat CSS toe voor de interactiviteit.

Het resultaat wanneer erop wordt geklikt:

Figuur 3: Resultaat van de weergave van het hamburgermenu wanneer het wordt geopend.

Hoe dit alles in zijn werk gaat

In wezen geeft de pseudoklasse :target ons een nieuwe “toestand” voor het stylen van de gerichte navigatie. Wanneer het hoofdmenu is getarget (met de hash toegevoegd aan de URL) kunnen we nu het menu uitschuiven. Het is een beetje als een :focus pseudo-class voor het getargete element (niet de link zelf).

We hebben ook toegestaan dat de “achtergrond” wordt weergegeven wanneer de navigatie is getarget.

Je zult zien dat het hoofd hamburger icoon is gekoppeld aan de ID van de navigatie, terwijl zowel het sluit icoon als de achtergrond knoppen zijn gekoppeld aan het hoofd hamburger icoon. Dit stelt ons in staat om op het sluit icoon of de achtergrond te klikken om de “focus” – of eigenlijk :target – van de navigatie te verwijderen. Als het achterdoek geen link was, zou het niet klikbaar zijn zonder JavaScript.

Ik heb ook de :target selectors samen met het attribuut in de CSS geketend. Dit zal uiteindelijk de plaats zijn waar we het hamburger menu geleidelijk aan verbeteren met JavaScript om niet naar de header te springen als erop geklikt wordt – om het voorbehoud te vermijden dat ik eerder noemde. Het kapen van het hash gedrag van de browser door het JavaScript betekent dat de :target pseudo-klasse niet langer zal werken. Wanneer dit gebeurt, zullen we gebruik maken van het attribuut om het wisselen te stylen met waar/niet waar waarden, zoals we dat in het verleden hebben gedaan met klassen.

In de tussentijd werkt dit echter prachtig zonder JavaScript.

Ik heb de @supports media query toegevoegd om de voorkeurspositie:vast CSS te geven aan browsers (zowel mobiel als desktop) die dit ondersteunen. Anders krijgen kreupele browsers en apparaten – ik kijk naar jullie iOS – position:absolute.

Stap 5: Grotere scherm stijlen

Omdat we niet willen dat het hamburger menu wordt weergegeven op niet-mobiele apparaten (of grotere schermen in het algemeen), voegen we daar de benodigde media query voor toe. Daarna gaan we het zo vormgeven dat het eruit ziet als een horizontale navigatie:

Step 5: CSS voor het vormgeven van de navigatie op grotere schermen.

Het resultaat:

Figuur 4: Resulterende weergave van de navigatie gestyled voor grotere schermen.

Voila! We zijn klaar!

Het geheel

Hier is de uiteindelijke HTML:

Eind HTML voor het responsive hamburger menu met alleen CSS.

Hier is de uiteindelijke CSS:

Eind CSS voor het responsive hamburger menu.

Demo

Probeer mijn CodePen zelf uit:
→ Zuiver CSS Hamburger Menu zonder JavaScript.

Note: u kunt de checkbox-versie van het menu ook demonstreren.

Wilt u JavaScript toevoegen om het gladder te maken?

Hoewel we het off-canvas menu volledig met CSS kunnen laten functioneren – wat de prestaties en betrouwbaarheid ten goede komt – zullen we toch JavaScript nodig hebben om op de een of andere manier de interactiviteit rond de nadelen van beide technieken te verbeteren. U kunt JavaScript ook gebruiken om scrollen op de pagina te voorkomen terwijl het menu geopend is.

Het is ook de moeite waard op te merken dat een behoorlijk niveau (en misschien wel het belangrijkste niveau) van toegankelijkheid kan worden bereikt zonder JavaScript. Het is echter moeilijk om een robuust niveau van toegankelijkheid te bieden zonder JavaScript’s vermogen om het DOM te manipuleren (bijv. focus management, ARIA attribuut updates, enz.).

Voor meer informatie over het verbeteren van de toegankelijkheid van uw website door middel van JavaScript, bekijk de volgende artikelen:

  • Het gebruik van ARIA-attributen voor JavaScript state setting & styling
  • Het schrijven van JavaScript met toegankelijkheid in gedachten

Heeft u andere gedachten of suggesties?

Ik hoor graag uw commentaar op mijn benadering van een puur CSS hamburger menu.

Edits en latere herkauwingen

21 januari 2019: Artikel bewerkt en codevoorbeelden bijgewerkt om onnodige ARIA-attributen te verwijderen en de toegankelijkheid te verbeteren.

Naarmate ik meer heb geleerd over het gebruik van ARIA en het ontwikkelen & van testen voor toegankelijkheid in het algemeen, heb ik me een paar dingen gerealiseerd:

  1. JavaScript heeft zeker zijn plaats, en zou deel moeten uitmaken van elk robuust toegankelijkheids UI-patroon.
  2. Met uitzondering van ARIA-aanduidingspunten, is JavaScript vereist om ARIA goed te gebruiken. En, veel van de attributen die ik heb gebruikt, zoals zijn beter overgelaten aan JavaScript om toe te voegen zodra geladen in plaats van het direct toe te voegen in de markup. Dit concept volgt goede Progressive Enhancement praktijken – ARIA states en eigenschappen samen met JavaScript zijn een upgrade en moeten worden behandeld op een aparte laag.
  3. Vorig behandelde ik de focus niet goed, omdat de focus zou verdwijnen als het door de visueel verborgen links ging (als ze samenvouwen). Ik heb een display: none; aan de menu CSS toegevoegd om dit te verhelpen.

Dus, als je een eerdere versie van mijn Pure CSS Off-Canvas Hamburger Menu hebt geimplementeerd, overweeg dan om het te updaten naar deze eenvoudigere en meer toegankelijke versie!

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.