Lesonderdeel 2: Off-canvas menu

Off-Canvas menu

Op de afbeelding is net zoals in de code is aangegeven, een knop aanwezig <button class="btn" onclick="sidenav()">&#9776;</button> met daaronder drie horizontaal gepositioneerde <a href=""></a> elementen en waarvan we 1 element <a href="javascript:void(0)" class="closebtn" onclick="sidenav()">&times;</a> gaan gebruiken voor het menu te sluiten.

Merk dat deze sluitknop onderaan staat. Dit doen we bewust om het navigeren met de tabtoets te faciliteren. Logischerwijs willen we de sluitknop als laatste aanduiden maar later meer hierover. Zowel de knop als het laatste element is voorzien van een onclick attribuut waarmee we het menu met behulp van JS (JavaScript) kunnen bedienen.

Verder heb ik anders als bij het vorig lesonderdeel voor de iconen gebruik gemaakt van de html 5 entiteitsreferenties &times; en &#9776;. Dit is een soort bibliotheek waarin symbolen en speciale charachters opgenomen zijn. Voor het linken van andere webpagina's dienen de hashtags nog wel vervangen te worden door reeƫle webpagina's. De hashtag belet dat we een foutmelding genereren bij het klikken wanneer de webpagina's nog onbestaand zijn. De "javascript:void(0)"invulling geeft aan dat deze geen link is maar een verwijzing naar een functie in javascript. Beide verhinderen dus in afwachting van het vervoledigen van onze webpagina een foutmelding bij het per ongeluk aanklikken.

HTML
Mark up topnavigatie

<!DOCTYPE html>
<html lang="nl">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">          
<title>Topnavigatie</title>
</head>
<body>				
  <nav>
    <button class="btn" onclick="sidenav()">&#9776;</button>
    <div id="mySidenav1" class="sidenav">
      <a href="#" class="active">Les 1: Topnavigatie</a>
      <a href="#">Les 2: Off-canvas menu</a>
      <a href="javascript:void(0)" class="closebtn" onclick="sidenav()">&times;</a>
    </div>
  </nav>
</body>
</html>
Code copied! Html code

Opmaak

Op de afbeelding is net zoals in de code een bedieningsknop te zien <button class="btn" onclick="sidenav()">&#9776;</button> met daaronder drie horizontaal gepositioneerde <a href=""></a> anchor tag elementen waarvan we 1 element gaan gebruiken voor het menu terug in te klappen <a href="javascript:void(0)" class="closebtn" onclick="sidenav()">&times;</a>. Uiteraard beginnen we met deze elementen onder elkaar te positioneren door onder de selector display:block; aan te geven en om de onderstreping te werwijderen gebruiken we wederom textdecoration:none;. Padding zorgt voor de nodige ruimte rond de text.

Merk dat het sluiticoon onderaan staat. Men zou kunnen stellen dat we deze bovenaan kunnen zetten in de html markup om zodoende de positie van dit element te veranderen. Het nadeel is echter dat wanneer we met de tabtoets in het menu willen navigeren deze dan als eerste element wordt opgelicht. Logischerwijs willen we de sluitknop als laatste aanduiden.

Om de sluitknop te positioneren stellen we nog een bovenmarge in voor het eerste element en kunnen dan met behulp van position:absolute de sluitknop rechts bovenaan plaatsen. Wanneer we een achtergrondkleur toevoegen aan het menu zal men merken dat ondanks we de hoogte op 100% hebben ingesteld, de elementen door de eigenschappen van het boxmodel die we voorheen hebben toegekend display:block; over heel de breedte van de pagina loopt. Dit kunnen we verhelpen door het element de position:fixed; eigenschap te geven. hierbij geven we in dit geval ook een positie aan t.o.v de webpagina bovenaan top: 0; en links left: 0;.Aangezien het menu zowel verschijnt als verdwijnt vanuit de linkermarge van de pagina, voeren we alvast een vertraagde transitie transition: 0.3s; door.

Voor de functionaliteit en de bediening van het menu dienen we het menu visibility: hidden; en de overflow van de inhoud overflow-x: hidden;te verbergen. Daarna stellen we nog een breedte voor het menu in op 0width: 0; voor de gesloten toestand. We voegen nog een een class toe aan de selector van het menu voor de open toestand en deze noemen we .sidenavOpen {}. We stellen de breedte parameter in op width: clamp(200px, 20%, 600px);.

De clamp functie is een methode om o.a de lettergroote en andere elementen aan te passen aan de viewpoort of schermgrootte. Deze neemt een minimumwaarde, een voorkeurswaarde (dat in dit geval 20% van de viewport bedraagt) en een maximumwaarde op als parameter. Dit had echter ook met width: fit-content; methode gelukt maar dan was een vertraagde transitie of overgang bij het openen en sluiten van het menu niet mogelijk. Ook zal deze functie later nog bijdragen om ook onze lettergrootte aan te passen aan kleine en grote schermen.

We stellen verder ook nog de visibiliteit van het menu in en tot slot voegen we nog opmaak toe aan de bedieningsknop van het menu en voegen hierbij eveneens de clamp functie toe. Het menu zal dan met behulp van een JS functie verschijnen wanneer we op de knop klikken en sluiten wanneer we op de sluitknop klikken. Merk dat aangezien we een symbool en een speciaal character gebruiken voor beide bedieningsknopppen de eigenschappen van de clamp functie aangepast zijn op basis van de lettertype met een minimumwaarde van 2 rem, een voorkeurswaarde dat 1% van de viewport breedte bedraagt en een maximumwaarde van 2.5 rem. font-size: clamp(2rem, 1vw, 2.4rem);.

CSS
off-Canvas menu off-Canvas menu
                    
.sidenav a {
  display: block;
  text-decoration: none;
  padding: .2em .5em;
  color: #818181; 
}

.sidenav a:first-child {
  margin-top: 3.5em;
}

.sidenav .closebtn {
  position: absolute;
  top: 0;
  right: 0;
  font-size: clamp(2rem, 1vw, 2.4rem);
}

.sidenav {
  height: 100%; 
  background-color: #333;
  position: fixed;
  top: 0;
  left: 0;
  width: 0;
  transition: 0.6s;
  overflow-x: hidden;
  visibility: hidden;  
}

.sidenavOpen {
  width: clamp(250px, 20%, 600px); 
  transition: 0.6s;
  visibility: visible;
}

.btn:focus {
  border: 2px solid #ddd;
}

.btn:hover {
  border: 2px solid #ddd;
}

.btn {
  background-color: white;
  cursor: pointer;
  border-radius: 5px;
  margin: 5px;
  font-size: clamp(2rem, 1vw, 2.4rem);
}
Code copied! CSS code

Functionaliteit

Wanneer we de developper tools erbij nemen merken we dat het menu van configuratie veranderd bij schermen onder de 600px. Echter in de mobiele versie hebben we nog geen toegang tot de verborgen onderdelen van het menu wanneer we op het icoon klikken. Aangezien we in Css een bijkomende classname .sidenavOpen{}. hebben toegevoegd waarbij we het menu zichtbaar maken dienen we het class attribuut .sidenavOpen{}in html met JS te manipuleren.

Vooreerst selecteren we in de console van de developper tools het menu attribuut met behulp van volgende code:document.querySelector(".sidenav"). De console zal dan aangeven waar dit attribuut zich bevindt wanneer men op enter klikt. Uiterst rechts van deze regel bevindt zich een vizier waarmee we het element of de node kunnen selecteren. Deze leidt ons dus bij het aanklikken hiervan automatisch naar het element in de html markup dat zich onder de inspector tab bevindt.

We keren terug naar de console en breiden de code verder uit met document.querySelector(".sidenav").classList.toggle("sidenavOpen"); en drukken op enter. De console geeft "true" aan en het menu wordt nu toegankelijk. In de inspector tab bij de html mark-up onder het nav tag merken we nu dat het menu een classattribuut draagt met de naam "sidenav sidenavOpen". De aanpassing in de console is niet permanent en dient de JS coderegel nog ingevoerd te worden in het JS bestand onder een functie function sidenavOpen() {}. Zie codesnippet.

JavaScript
classList.toggle in developper tools
                                  
function sidenav() {
  document.querySelector(".sidenav").classList.toggle("sidenavOpen");
}
Code copied! JS code