Byg en responsiv Javascript nav-menu

Responsivt webdesign (RWD) har haft en enorm indflydelse på, hvordan vores branche udvikler websteder og applikationer til forskellige enheder. Overalt hvor vi ser er der nye teknikker, værktøjer og tanker om emnet. RWD giver os de værktøjer, vi har brug for til at skabe fantastiske oplevelser til de mange enheder, som vores brugere har.

Ethan Marcottes originale artikel skitserer de tre kernestykker i et responsivt design: flydende gitre, fleksible billeder og medieforespørgsler. Selvom JavaScript ikke er et af disse fundament for RWD, tillader det udviklere at forbedre interaktioner og skabe rigere oplevelser for brugerne. Mange mennesker (inklusive mig selv) hævder, at vores indhold skal være tilgængeligt for brugere uden JavaScript aktiveret. Det er her, vi træder en fin linje mellem at bruge JavaScript til at gøre vores websteder mere brugbare og at skjule indhold bag en JS-væg.



  • Hent kildefiler til denne vejledning

Hvis du bruger tid på at skrive JavaScript til RWD, er du sikker på at støde på arbejdet med Scott Jehl af Filament Group . Det er heldigt for os, at der er sådanne mennesker, der skaber og deler værktøjer for at hjælpe med at bevæge responsivt design fremad.



Lad os bygge noget

Jeg har ikke en specifik oversigt over, hvor meget tid vi bruger på hver sektion på vores websteder, men vi bruger generelt mere på navigationen (især på store websteder) end noget andet aspekt. At sikre, at vi har det rigtige indhold, sørger for, at det er organiseret godt, det er let at komme til, er tilgængeligt, og funktioner på alle de enheder, vi kan få fat i, kan mildt sagt være tidskrævende.

Brug jQuery til nemt at håndtere browserens uoverensstemmelse med begivenhedsbindinger og gøre det let at skifte klasser på DOM-elementer



Brug jQuery til nemt at håndtere browserens uoverensstemmelse med begivenhedsbindinger og gøre det let at skifte klasser på DOM-elementer

Så for at gøre vores liv lettere, lad os bygge noget lydhør navigation. Et par mål for denne navigation er:

  1. At arbejde godt på små og store skærme.
  2. At arbejde i Chrome, Safari, Firefox og IE (8+).
  3. At arbejde med eller uden JavaScript.

Markeringen

Hvis du ikke bruger filerne fra vejledningen, ville det være en god tid til i det mindste at kopiere base.css . Da vores fokus her er på JavaScript, vil vi ikke se meget på CSS. Gå videre og tag fat i index.html-filen fra vejledningsfilerne og lad os komme i gang.

Når du først har kigget på HTML-filen, spørger du dig muligvis: hvorfor er navet i sidefoden? Godt spørgsmål. Et af vores mål var at gøre navigationen tilgængelig for ikke-JavaScript-brugere. For brugere på små skærme uden JS ønsker vi ikke, at navigationsenheden spiser skærmen op, når de besøger siden. Så i overskriften har vi et link til navigationen, som findes (udvidet) i sidefoden.



Navigationen i en lille størrelse efter berøring / klik på menuikonet for at eksponere off-canvas-elementet

Navigationen i en lille størrelse efter berøring / klik på menuikonet for at eksponere off-canvas-elementet

Mindste først

Det er generelt meget lettere at opbygge lydhøre sider, hvis du starter med den mindste størrelse og arbejder derfra. På dette tidspunkt skal du have en navigation, der fungerer i en lille størrelse med JavaScript slået fra, har en Vis Nav link (der i øjeblikket ikke gør noget) i denne størrelse, når JavaScript er aktiveret, og fungerer med en simpel svæver i store størrelser både med og uden JavaScript.

Lad os begynde at tilføje noget JavaScript for at puste lidt liv ind i navigationen i lille størrelse. Du bliver nødt til at tilføje referencer til jQuery og JavaScript JavaScript lige før det afsluttende body tag af index.html .

Vi begynder med følgende i nav.js . Dette vil skabe et objekt ( vindue.NAV ) for at indeholde al koden til kontrol af vores navigation:

(function() { window.NAV = { $body: $('body'), $subMenus: $('.subMenu'), toggle: function(e) { e.preventDefault(); NAV.$body.toggleClass('mainMenu-is-open'); }, bindEvents: function() { $('.js-togglesOffCanvas').on('click', NAV.toggle); }, init: function() { NAV.bindEvents(); } } })(); NAV.init();

Det i det ovenstående metode indeholder alle de nødvendige opsætninger. Her ringer det NAV.bindEvents , som bruger jQuery til at binde en klikhændelse til noget med en klasse af js-togglesOffCanvas , for at ringe til NAV.toggle metode .

NAV.toggle vil stoppe standardhændelsen fra at affyre (så vi ikke følger links, vi ikke vil have) og bruge jQuery til at skifte mellem mainMenu-er-åben klasse på kroppen. Dette vil oprette CSS-reglerne for at flytte .mainNav div (aktuelt placeret fra venstre side af skærmen) til visning ved hjælp af CSS-transformationer. Ved brug af oversætte3d tvinger hardwareacceleration i WebKit. Så vi kan registrere, hvad der er tilgængeligt ved hjælp af Modernizr og brug oversætte3d (hvis tilgængelig) til glattere animationer.

Fremhævning af overlay div via JavaScript. Klikhændelsen på denne div er bundet til lukning af menuhandling

Fremhævning af overlay div via JavaScript. Klikhændelsen på denne div er bundet til lukning af menuhandling

Da vores begivenhed er bundet til klassen js-togglesOffCanvas , skal du tilføje den klasse til showlinket i overskriften:

Show Nav

Du skal nu have en navigation, der glider ind fra venstre side i en lille størrelse, når du klikker på Vis Nav link. Men vent - vi har ikke en måde at lukke navigationen på, når vi har åbnet den. Lad os ordne det.

Jeg vil gerne have en knap øverst til venstre på det samme sted, hvor det åbne link var, før vi skubbede det til højre. Jeg vil også gerne være i stand til at klikke på noget til højre for navigationen for at udløse en lukning. I stedet for at forsøge at tilføje en begivenhedslytter til alt på højre side, lad os falde i en overlay div og lytte efter klik på den. Opret en JS-variabel for at gemme markeringen og tilføje til vores NAV-objekt:

window.NAV = { $clickOverlay: $(' '), …

Vi tilføjer derefter en linje til i det metode til at tilføje denne div til DOM. På denne måde tilføjer vi kun dette, hvis vi har JS, og nav-off-canvas-navigationen muligvis er aktiveret.

hvilket af følgende er det bedste dokument for en faktura, der er omtvistet
init: function() { NAV.$clickOverlay.appendTo('body'); NAV.bindEvents(); }

Hvis du vil se denne div, tilføj en klasse af synlig: da dette element er usynligt, kan dette være nyttigt til testning. Nu er det et godt tidspunkt at føje luk-knappen til selve navet. Tilføj en lige inden i :

Close Menu

Nu kan vi lukke vores navigation - en lettelse - selvom vi ikke kan komme til links på andet niveau i denne off-canvas-tilstand. Vi kan gøre noget ved dette via et par ændringer til vores nav.js fil. Først skal du tilføje denne metode til ER IKKE objekt:

toggleSubNav: function(e) { e.preventDefault(); $(this).siblings('ul').stop().slideToggle('fast'); },

Tilføj derefter en klikhåndterer til .js-togglesSubMenu til NAV.bindEvents .

bindEvents: function() { $('.js-togglesOffCanvas').on('click', NAV.toggle); $('.mainNav').on('click', '.js-togglesSubMenu', NAV.toggleSubNav); },

Tilføj js-togglesSubMenu klasse til ethvert link, der skal åbne en undermenu

    i index.html .

  • Products

    Denne navigation kommer virkelig sammen nu, men hvis du roter rundt, kan du finde et par problemer. Den første vises, når off-canvas-nav er åben, og en medieforespørgsel ændrer layoutet til at skifte til non-off-canvas-layoutet. Alt ser brudt ud: legeme element har stadig en klasse af mainMenu-er-åben anvendt. Også, hvis du åbner og derefter lukker en undermenu, vil svæveeffekten på den i større størrelse ikke virke - et problem, hvis det brudpunkt, hvor kontakten sker, ligger mellem stående og liggende tilstand af en håndholdt enhed.

    Off-canvas-navigationen blev åbnet og udvidet fuldt ud for at afsløre en menu på andet niveau

    Off-canvas-navigationen blev åbnet og udvidet fuldt ud for at afsløre en menu på andet niveau

    I øjeblikket affyrer browsere ikke begivenheder, når medieforespørgsler ændrer tilstand. Men nyere browsere har adgang til at bestemme, om en bestemt medieforespørgsel anvendes via matchMedia API . I dette tilfælde bruger jeg en indpakning, mediaCheck , som jeg skrev omkring matchMedia API. Det lader os indstille funktioner til at udføre, når en medieforespørgsel bliver eller holder op med at være aktiv. For at gøre det tilføjer vi en henvisning til mediaCheck i index.html lige før nav.js :

    Derefter skal vi tilføje koden for at fortælle mediaCheck hvilke medieforespørgsler, man skal se, og også hvad man skal gøre, når de ændres. Tilføj disse linjer i slutningen af ​​init fungere() .

    mediaCheck({ media: '(min-width: 35em)', entry: function() { NAV.clear(); } });

    Tilføj nu NAV. Klar metode. Fjern mainMenu-er-åben klasse fra kroppen, nulstilling af elementer flyttet for at give plads til navet tilbage til deres rigtige steder og fjernelse af indbyggede stilarter jQuery-animationerne tilføjet til elementerne:

    window.NAV = { $subMenus: $('.subMenu'), clear: function() { NAV.$body.removeClass('mainMenu-is-open'); NAV.$subMenus.removeAttr('style'); } …

    Nu, når browserbredden bliver større end eller lig med 35ems mainMenu-er-åben klasse og de indbyggede stilarter fra jQuery fjernes.

    Enheder med uret fra øverst til venstre: Apple iPad, BlackBerry Z10 og Apple

    Enheder med uret fra øverst til venstre: Apple iPad, BlackBerry Z10 og Apples iPhone 5

    Et andet problem, der eksisterer, er, at de overgange, der skaber glidende animation uden for lærred, stadig anvendes, når navigationen skifter mellem sammenhænge. Dette resulterer i et ret grimt skift mellem medieforespørgsler. Vi kan bygge videre på rettelsen til det første problem ved at tilføje følgende metode til vindue.NAV :

    toggleAnimations: function() { if ( APP.getState() === 'small' ) { NAV.$body.addClass('enableAnimations'); } else { NAV.$body.removeClass('enableAnimations'); } },

    Rediger mediaCheck kalde init-metoden sådan:

    mediaCheck({ media: '(min-width: 30em)', entry: function() { NAV.clear(); NAV.toggleAnimations(); }, exit: function() { NAV.toggleAnimations(); } });

    Og til sidst skal du ændre linje 80 i base.css at være:

    .enableAnimations .mainNav, .enableAnimations .mainContent, .enableAnimations .masthead, .enableAnimations .clickOverlay {

    Nu er overgange bundet til enableAnimations klasse er til stede, og denne klasse anvendes kun i den lille størrelse.

    Du bemærker det tredje problem, hvis du prøver at klikke på produktmenuen i større størrelse. Visning af andet niveau nav i denne størrelse skal håndteres af svæver. Den klikhåndterer, vi anvendte til at håndtere den mindre størrelse, skyder stadig.

    Brug af Modernizr giver os en måde at bruge funktionsdetektering til at træffe CSS- og JavaScript-beslutninger

    Brug af Modernizr giver os en måde at bruge funktionsdetektering til at træffe CSS- og JavaScript-beslutninger

    Dette er lidt vanskeligere. Jeg udviklede oprindeligt en løsning, men med hjælp fra Adam Simpson har gjort store forbedringer. Se på app.js i tutorial-filerne, og du vil se en metodedefinition til APP.getState , som injicerer et element med et ID på SizeTest ind på siden. Dette element henter typografier fra CSS, som det bruger til at få en idé om, hvilken størrelse browseren har i forhold til de definerede medieforespørgsler. Tilføj app.js henvisning til index.html:

    I CSS finder du følgende erklæringer (dette er lidt af et hack):

    #sizeTest { font-size: 10px; } @media (min-width: 30em) { #sizeTest { font-size: 30px; } }

    APP.getState kontrollerer skriftstørrelse af dette element for at returnere en streng (som du kan definere): enten lille eller stor . Vi har prøvet andre tilgange, men dette har den bedste understøttelse på tværs af browsere / enheder. Dette kan derefter bruges til at kontrollere den logiske strøm af vores JavaScript. NAV.toggleSubNav bliver til:

    toggleSubNav: function(e) { e.preventDefault(); if ( APP.getState() === 'small' ) { $(this).siblings('ul').stop().slideToggle('fast'); } }

    Nu vil JavaScript-skift kun ske i små størrelser.

    Konklusion

    På dette tidspunkt skal du have ret solid navigation, der fungerer næsten overalt. Hvis du vil dykke videre, vil jeg anbefale at følge Scott Jehl , Brad Frost og Tændkasse : vi har kun skrabet overfladen af, hvad vi kan gøre for at forbedre vores lydhøre hjemmesider ved hjælp af JavaScript.

    Ord: Rob Tarr

    Denne artikel af Rob Tarr oprindeligt dukkede op i netmagasin Opgave 245.