Skip links en inhoudsopgave

Laatst aangepast: .

Simpel dropdownmenu, twee niveaus diep

Korte omschrijving

Als je met de cursor over een van de ingangen in de menubalk hovert, opent een submenu. Onder de ingangen in dat submenu zit een link naar een pagina. Het menu waar je over hovert en de bijbehorende hogere ingang verkleuren.

BELANGRIJK

Alles op deze site kan vrij worden gebruikt, met twee beperkingen:

* Je gebruikt het materiaal op deze site volledig op eigen risico. Het kan prima zijn dat er fouten in de hier verstrekte info zitten. Voor eventuele schade die door gebruik van materiaal van deze site ontstaat, in welke vorm dan ook, zijn www.css-voorbeelden.nl en medewerkers daarvan op geen enkele manier verantwoordelijk.

* Deze uitleg wordt regelmatig bijgewerkt. Het is daarom niet toegestaan deze uitleg op welke manier dan ook te verspreiden, zonder daarbij duidelijk te vermelden dat de uitleg afkomstig is van www.css-voorbeelden.nl en dat daar altijd de nieuwste versie is te vinden. Dit is om te voorkomen dat er verouderde versies worden verspreid.

Een link naar www.css-voorbeelden.nl wordt trouwens altijd op prijs gesteld.

Opmerkingen

In dit voorbeeld wordt voor Internet Explorer 7 en 8 een beetje JavaScript gebruikt, omdat dat de enige mogelijkheid is om in deze twee browsers nieuwe elementen uit html5 te gebruiken.

Voor bepaalde dingen wordt gebruik gemaakt van eigenschappen uit css3. Deze werken niet allemaal in Internet Explorer 7, 8 en 9. Zie verder bij Bekende problemen.

Links in deze uitleg, vooral links naar andere sites, kunnen verouderd zijn. Op de pagina met links vind je steeds de meest recente links.

Alles op deze site is gemaakt op een systeem met Linux. Daarbij is vooral gebruik gemaakt van Quanta Plus, GIMP en Firefox met extensies. De pdf-bestanden zijn gemaakt met LibreOffice.

Vragen of opmerkingen? Fout gevonden? Ga naar het forum.

Iets gevonden waar je wat aan hebt? Mooi. Als je je waardering wilt uiten, maak dan een donatie over aan War Child Nederland, een organisatie die kinderen uit oorlogsgebieden helpt hun trauma's te verwerken. Of - nog beter - wordt donateur:
War Child Nederland

Achterliggend idee

Naar dit soort uitklapmenu's is tamelijk veel vraag. Vrijwel altijd zijn ze geschreven in JavaScript. Terwijl dit soort menu's ook simpel in alleen html en css is te maken.

Het eerste niveau, de bovenste knoppen die altijd zichtbaar zijn, is gewoon 'n ongeordende lijst. Bij het hoveren over een van de <li>'s uit die lijst opent 'n tweede <ul>, waarin 'n lijstje met links staat.

Omdat de hele lay-out via css wordt gedaan, heb je zonder css 'n keurige serie ongeordende lijsten met daarin netjes alle links per lijst: heel overzichtelijk. En dus goed toegankelijk voor spraakbrowsers, zoekmachines, en dergelijke.

Het menu is verder nog wat opgeleukt met kadertjes, achtergrondkleuren, enz.

Door het gebruik van em als maateenheid op vrijwel alle plaatsen kun je de lettergrootte veranderen, terwijl de lay-out van 't menu intact blijft.

In dit voorbeeld wordt een nieuwe semantische code uit html5 gebruikt: <nav>. Internet Explorer 7 en 8 kunnen - tegen de standaard in - geen css koppelen aan onbekende elementen. Daarom wordt voor deze twee browsers 'n heel klein beetje JavaScript gebruikt, waardoor ze dit wel kunnen.

De voorvoegsels -moz-, -ms-, -o- en -webkit-

Voordat een nieuwe css-eigenschap wordt ingevoerd, is er in de regel een experimentele fase. Browsers passen het dan al toe, maar met een aangepaste naam. Tijdens deze fase kunnen problemen worden opgelost en worden veldslagen uitgevochten over hoe de standaard precies moet worden toegepast.

Als iedereen het overal over eens is en alle problemen zijn opgelost, wordt de officiële naam uit de standaard gebruikt.

De belangrijkste browsers hebben elk een eigen voorvoegsel:

Firefox: -moz-, naar de maker: Mozilla.

Google Chrome en Safari: -webkit-, naar de gebruikte weergave-machine: webkit.

Opera: -o-, je mag zelf bedenken waar de letter o vandaan komt (hint: Opera wordt door Opera Software gemaakt).

Internet Explorer: -ms-, naar de maker: Microsoft. Traditiegetrouw heeft Microsoft zich hier jarenlang niets van aangetrokken, pas bij Internet Explorer 8 is Microsoft -ms- gaan gebruiken. Omdat het ook zonder -ms- werkt en de speciale css voor Internet Explorer toch in een aparte stylesheet staat, gebruik ik -ms- nooit voor oudere versies dan Internet Explorer 9.

Als je css valideert met de w3c css-validator, moet je even instellen dat je geen foutmelding krijgt voor het gebruik van deze voorvoegsels.

In dit voorbeeld wordt transition gebruikt.

Firefox herkent -moz-transition. Safari herkent -webkit-transition. Opera herkent -o-transition. Internet Explorer 7, 8 en 9 herkennen transition helemaal niet, maar Internet Explorer 10 gaat het waarschijnlijk wel herkennen. Omdat onduidelijk is of Microsoft het gaat implementeren met of zonder -ms-, gebruik ik voor de zekerheid ook -ms-transition.

Zodra de experimentele fase voorbij is, wordt het voorvoegsel weggelaten. Omdat dat moment niet bij alle browsers hetzelfde is, zet je nu ook al de officiële naam transition erbij. Deze wordt als laatste opgegeven. Bijvoorbeeld Firefox herkent -moz-transition. Zodra Firefox transition gaat herkennen, zal dit -moz-transition overrulen, omdat het er later in staat. Dat ze er beide in staan, is dus geen enkel probleem.

Op dit moment moet je nog het volgende schrijven:

{-moz-transition: ...; -ms-transition: ...; -o-transition: ...; -webkit-transition: ...; transition: ...;}

In de toekomst kun je volstaan met:

{transition: ...;}

Semantische elementen en outline

In dit voorbeeld staat het hele menu in het nieuwe semantische html5-element <nav>. Een semantisch element geeft min of meer aan om wat voor soort inhoud het gaat. Zo geeft bijvoorbeeld een <h1> aan dat het om een belangrijke kop gaat, een <p> dat het om een alinea gaat, enz. <nav> geeft aan dat het om een serie links voor navigatie gaat. Dit soort semantische elementen kan spraakbrowsers, zoekmachines en dergelijke helpen hun weg te vinden binnen een pagina.

Normaal genomen zou je bij de tekst en dergelijke op de pagina ook nog gebruik maken van semantische html5-elementen als <section>. In dit geval heb ik dat niet gedaan, omdat op deze pagina alleen maar Latijnse opvultekst staat.

<nav> is een van de elementen die wordt gebruikt om de outline van een pagina te maken. De outline is een soort geautomatiseerde inhoudsopgave, waarvan spraakbrowsers, zoekmachines, en dergelijke gebruik kunnen maken om de structuur van een pagina vast te stellen. Op dit moment werkt dat nog niet, en dat zal ook nog wel even duren, maar het kan geen kwaad hier al rekening mee te houden. Het is een kleine moeite en maakt je pagina geschikt voor de toekomst.

Meer over deze outline kun je vinden op de pagina met links onder HTMLOutline (van document).

Alleen :hover of :hover, :focus en :active?

Het eerste deel van deze tekst is voor alle voorbeelden met links en dergelijke hetzelfde, het laatste deel (onder het kopje Speciaal bij dit voorbeeld) is speciaal voor dit voorbeeld.

De meeste mensen openen 'n link door erop te klikken. Er is echter 'n tweede manier: met behulp van de Tab-toets (sommige browsers gebruiken andere toetsen, maar het principe is hetzelfde). Met behulp van de Tab-toets kun je van link naar link 'springen'. Op welke link je staat, wordt door alle browsers aangegeven met een of ander kadertje rondom de link.

De link met het kadertje eromheen heeft focus. Dat wil zeggen dat je die link volgt als je op de Enter-toets drukt. In principe werkt dit precies hetzelfde als gewoon klikken op de link.

Als iemand geen muis wil of kan gebruiken, bijvoorbeeld door 'n handicap, is deze manier om 'n link te openen erg handig. Als de volgorde van de links in de code niet logisch is, kun je eventueel met behulp van tabindex 'n afwijkende volgorde van de links opgeven. De Tab-toets volgt dan die afwijkende volgorde.

Tot zover is er nauwelijks verschil tussen het gebruik van de Tab-toets of van de muis.

Als je echter extra dingen onder de link hebt gestopt, die pas gaan werken als je over de link hovert, is er wel 'n verschil. Je geeft dat aan met :hover: als je over de link hovert. Met de Tab-toets alleen kun je niet over 'n link hoveren. Dus als er bijvoorbeeld 'n pop-up wordt geopend, zul je die niet zien als je de Tab-toets gebruik om naar 'n link te gaan.

Om dit op te lossen kun je op dezelfde manier als je :hover gebruikt :focus gebruiken: als de link focus heeft. Dat is dus als er 'n kadertje rondom de link staat en de link wordt gevolgd bij het indrukken van Enter.

Door dus a:hover, a:focus {...} te gebruiken, opent bijvoorbeeld 'n pop-up ook als je de Tab-toets gebruikt. Maar er zitten 'n paar adders onder het gras.

* Naast :hover en :focus is er nog :active. Deze laatste zou horen te werken als de muis wordt ingedrukt op de link. Dat werkt ook zo in alle browsers, behalve in Internet Explorer vóór versie 8. In haar onmetelijke wijsheid heeft Microsoft besloten af te wijken van de standaard: :active werkt in oudere versies zoals :focus hoort te werken, en :focus werkt gewoon helemaal niet vóór versie 8. In alle andere browsers werken :focus en :active dus wel volgens de standaard, en met ingang van versie 8 van Internet Explorer houdt Microsoft zich ook eindelijk aan de standaard.

Dit betekent dat je niet kunt volstaan met a:hover, a:focus {...}, maar dat je a:hover, a:focus, a:active {...} moet gebruiken, want anders werkt het niet in oudere versies van Internet Explorer. Het zal nog jaren duren voor deze oude versies niet meer worden gebruikt, maar omdat Microsoft zich nu eindelijk ook aan de standaard houdt op dit punt, wordt :active nu ook langzaamaan bruikbaar voor waar het voor is bedoeld.

* Belangrijke informatie moet je niet geven via :focus of :active, omdat dit niet werkt als css uit staat.

* Ten slotte kan 'n pop-up of zoiets gruwelijk in de weg komen te staan, bijvoorbeeld door de rest van de pagina af te dekken. Iemand die gewoon de muis kan gebruiken, verplaatst deze even en de pagina is weer zichtbaar. Iemand die moeite heeft met het gebruik van de muis, heeft deze mogelijkheid niet of minder. Als je buiten de link en de daarbij horende pop-up en dergelijke klikt, sluit deze weliswaar, maar dat is nu juist het probleem: mensen die de muis niet goed kunnen gebruiken, hebben nou net daar problemen mee.

Als je via de terug-toets teruggaat naar de vorige pagina, heeft de link waar je vandaan kwam nog steeds focus, en dus staan pop-up en dergelijke ook nog open. Wat ook heel storend kan zijn als andere delen van de pagina daardoor niet te zien zijn. Op het moment dat ik dit schreef, werkte de terug-toets bij alle browsers zo, met uitzondering van Google Chrome. Maar 't kan best zijn dat Google Chrome het inmiddels ook doet, of 'n andere juist weer niet, want dit schijnt nogal te veranderen.

Om al deze redenen is het goed je even af te vragen of de voordelen van 'n pop-up en dergelijke wel opwegen tegen de nadelen. Ik zet zelf mijn eigen overwegingen bij elk voorbeeld steeds even erbij. Wat natuurlijk niet wil zeggen dat je daar geen andere mening over zou kunnen hebben.

Speciaal bij dit voorbeeld

Dit voorbeeld zou ideaal zijn om ook :focus en :active te gebruiken, maar helaas werkt dit niet op lijsten en lijst-ingangen. Zou het wel werken, dan zou de toegankelijkheid voor mensen die de Tab-toets gebruiken gelijk ook goed zijn, maar helaas...

(In een eerdere versie stond in elke lijst-ingang een link. Dat was nodig voor Internet Explorer 6. Maar dat maakte voor de werking geen verschil: ook hier was de Tab-toets onbruikbaar.)

Beschrijving van code en css

De code die te maken heeft met de basis van dit voorbeeld is rood gekleurd. Alle voor dit voorbeeld niet-essentiële code is bruin.

Deze uitleg hoort bij het voorbeeld dat in de download zit. Het voorbeeld uit de download verschilt iets van het voorbeeld hier op de site. In de download ontbreken bijvoorbeeld de witte vlakken met de links. Ook in de kopregels zit vaak wat verschil. Daarnaast kunnen er nog andere (meestal kleine) verschillen zijn.

Als je deze uitleg leest naast de broncode van het voorbeeld op de site, kan het dus bijvoorbeeld zijn dat 'n h1 uit de css bij 'n <h2> uit de html hoort. Maar het gaat niet om hele grote, fundamentele afwijkingen.

Als je dit lastig vindt, downloadt dan de hele handel (ga terug naar het voorbeeld en kies daar voor downloaden). In de download zit 'n voorbeeld dat wel naadloos aansluit op de uitleg in de download.

<!DOCTYPE html> <html lang="nl">

Een document moet met een doctype beginnen om weergaveverschillen tussen browsers te voorkomen. Zonder doctype is de kans op verschillende (en soms volkomen verkeerde) weergave tussen verschillende browsers heel erg groot.

Geldige doctypes vind je op www.w3.org/QA/2002/04/valid-dtd-list.

Gebruik het volledige doctype, inclusief de eventuele url, anders werkt het niet goed. Het hier gebruikte doctype is dat van html5. 'n Stuk korter dan oudere doctypes.

<meta charset="utf-8">

Zorgt dat de browser letters met accenten en dergelijke goed kan weergeven. Bij html5 is deze korte regel voldoende.

utf-8 is de beste charset (tekenset), omdat deze alle talen van de wereld (en nog heel veel andere extra tekens) bestrijkt, maar toch niet meer ruimte inneemt voor de code, dan nodig is. Als je utf-8 gebruikt, hoef je veel minder entiteiten (&auml; en dergelijke) te gebruiken, maar kun je bijvoorbeeld gewoon ä gebruiken.

Deze regel moet zo hoog mogelijk komen te staan, als eerste regel binnen de head, omdat hij anders door sommige browsers niet wordt gelezen.

<link rel="stylesheet" href="../../css/naam-van-stylesheet.css">

Deze regel heeft in dit voorbeeldbestand geen enkel nut. Normaal genomen is het een verwijzing naar een extern stylesheet, waarin de style staat. In dit voorbeeld verwijst de href naar een niet bestaand bestand. In html5 is de toevoeging type="text/css" niet meer nodig, omdat dit standaard al zo staat ingesteld.

De bedoeling is dat je bovenstaande regel aanpast voor je eigen bestand. De hele style, die onder deze regels in de <head> staat, wordt dan in het externe bestand geplaatst waar de href naar verwijst. In dat bestand komt de style precies zo te staan zoals die nu in de <head> staat. Het bestand moet eindigen op .css.

Voordeel van een externe stylesheet is onder andere, dat deze geldig is voor alle pagina's waaraan deze is gelinkt. 'n Verandering in de lay-out hoef je dan maar op één enkele centrale plek te aan te brengen.

In die externe stylesheet zet je alles wat in dit voorbeeld tussen <style> en </style> staat (zonder deze begin- en eindregel). Op de plaats van "../../css/naam-van-stylesheet.css" moet je pad naar en naam van jouw stylesheet invullen.

<style>

Voor de duidelijkheid staat de style hier in het bestand zelf, maar het is beter deze in een apart stylesheet te zetten, zoals hierboven beschreven. In die stylesheet komt alles wat tussen <style> en </style> staat.

Technisch gezien is er geen enkel bezwaar om het in die stylesheet te zetten met dezelfde vreselijke lay-out, zoals ik die in dit voorbeeld gebruik. Maar als je dat doet, garandeer ik je hele grote problemen, omdat het volstrekt onoverzichtelijk is. Ik gebruik deze lay-out alleen, omdat het anders veel te veel regels worden.

Voorbeeld van 'n goede lay-out in je css:


	div#header-buiten
	{
	    position: absolute;
	    right: 16px;
	    width: 100%;
	    height: 120px;
	    background: yellow;
	}

	div#header-binnen
	{
	    margin-left: 16px;
	    height: 120px;
	    text-align: center;
	}
body

Het element waarbinnen de hele pagina staat. Veel instellingen die hier worden opgegeven, worden geërfd door de kinderen van <body>. Ze gelden voor de hele pagina, tenzij ze later worden gewijzigd. Dit geldt bijvoorbeeld voor de lettersoort, de lettergrootte en de voorgrondkleur.

margin: 0; padding: 0;

Slim om te doen, is soms wat afwijkend in verschillende browsers.

font-family: Arial, Helvetica, sans-serif;

Lettersoort. Als er geen Arial is, wordt gezocht naar Helvetica. Als dat er ook niet is in ieder geval 'n lettersoort zonder schreef (dwarsstreepjes).

font-size: 110%;

Iets groter dan standaard. 't Zal de leeftijd zijn, maar ik vind de standaardgrootte wat te klein.

Ik gebruik hier % als eenheid, en voor alle andere lettergroottes gebruik ik em. Dat komt door Internet Explorer. Als ik als maateenheid iets als px neem, kunnen gebruikers van Internet Explorer de lettergrootte niet veranderen.

Maar als ik overal em neem als maateenheid, wat dan voor de hand zou liggen, kom ik in de problemen met versies van Internet Explorer ouder dan versie 8. De stappen van de verkleining of vergroting zijn in die browsers zo groot, dat 't gelijk onleesbaar klein of absurd groot is.

Als je nou echter bij body geen em gebruikt (font-size: 1.1em; zou hetzelfde moeten zijn als font-size: 110%;), dan is de lettergrootte in Internet Explorer te veranderen, en in oudere versies dan versie 8 zijn de tussenstappen teruggebracht tot normale grootte.

Dit werkt ook als je als lettergrootte 100% invult. Dat heeft geen enkele invloed op de lettergrootte, behalve dus dat de tussenstappen in oudere versies nu normaal werken.

In Internet Explorer 8 is deze bug eindelijk gerepareerd. Aangezien we waarschijnlijk nog vele jaren met oudere versies dan Internet Explorer 8 zitten opgescheept, zal deze truc ook nog jaren moeten worden toegepast.

color: black;

Voorgrondkleur zwart. Dit is onder andere de kleur van de tekst.

Hoewel dit de standaardkleur is, geef ik de kleur toch op. Hieronder geef ik een achtergrondkleur op. Sommige mensen hebben zelf de kleur en/of achtergrondkleur veranderd, bijvoorbeeld omdat ze slecht kleuren kunnen onderscheiden. Als ik nu de achtergrondkleur verander, maar niet de voorgrondkleur, loop ik het risico dat tekstkleur en achtergrondkleur te veel op elkaar gaan lijken.

Door beide op te geven, weet ik redelijk zeker dat achtergrond- en tekstkleur genoeg van elkaar blijven verschillen. Als de gebruiker !important heeft gebruikt, is er nog niets aan de hand, want dan veranderen achtergrond- en voorgrondkleur geen van beide.

background: #ff9;

Achtergrondkleurtje.

#skippy

Het element met id="skippy". Dit is een zogenaamde skip-link. Het geeft de mogelijkheid in één keer het menu te passeren, zodat dit niet wordt voorgelezen.

Een menu dat binnen een <ul> staat, zoals in dit voorbeeld ook het geval is, wordt door spraakbrowsers en dergelijke vaak herkend en kan dan in één keer worden overgeslagen. De gemiddelde gebruiker van een spraakbrowser zal niet echt genieten van het voorlezen van steeds hetzelfde menu op elke pagina. Door het menu binnen een <ul> te zetten, kan de gebruiker dat voorlezen voorkomen.

En omdat een menu binnen een <ul> ook makkelijk met css is aan te sturen, gaat toegankelijkheid hier prima samen met goed te onderhouden code.

(Te verwachten is dat een <nav> op termijn dezelfde werking gaat krijgen, maar op dit moment is dat nog niet het geval. Bovendien blijft een <ul> hoe dan ook het meest geschikt voor een menu, ook binnen een <nav>.)

Een andere groep mensen heeft hier echter niets aan. Sommige mensen kunnen de muis niet gebruiken (of willen dat niet). Met behulp van de Tab-toets of een soortgelijke toets kun je één voor één alle links en dergelijke op een pagina aflopen. Die mensen moeten eerst door het hele menu heen tabben, voordat ze eindelijk op de eigenlijke pagina aankomen. Dat zijn hier 36 links, dus te vrezen valt dat dit niet bijdraagt tot het verhogen van hun levensgeluk.

Voor deze mensen wordt gelijk voor het menu een zogenaamde skip-link neergezet. De link in het rode kadertje hiernaast zie je normaal genomen niet, omdat hij met behulp van css ver links buiten het venster van de browser wordt geparkeerd. Maar ook al zie je hem niet, hij is er wel. En wordt dus door de Tab-toets gewoon gezien. De bij de link horende html:

<a id="skippy" href="#content" tabindex="1">Skip menu met links</a>

De tabindex is nodig, omdat de Tab-toets in Opera alleen werkt bij links die een tabindex hebben.

Bij het begin van de eigenlijke content van de pagina staat het anker, waarnaar wordt gelinkt:

<div id="content">

Als ik de Tab-toets gebruik, is de skip-link de eerste link die focus krijgt. Een link heeft focus, als je er met de Tab-toets (of een soortgelijke) toets bent aangekomen. Er staat dan een klein kadertje rondom de link, tenzij je dat zelf met css verandert. Als je op Enter drukt, wordt de link gevolgd.

Normaal genomen is de skip-link onzichtbaar, omdat hij met behulp van css ver links buiten het venster van de browser wordt geparkeerd. Zodra de link focus heeft, wordt hij midden over het menu geplaatst. En omdat hij groot is en 'n knalrode rand heeft en zo, is hij vrijwel niet te missen. Als je nu op Enter drukt, wordt de link gevolgd: je passeert met één toetsindruk alle 36 links uit het menu.

Deze link is natuurlijk absoluut foeilelijk. En dat is precies de bedoeling: nu valt hij goed op. Zodra je nog 'n keer op de Tab-toets drukt, heeft de link geen focus meer en verdwijnt weer links buiten het venster. Hij verpest dus niet de hele pagina, want hij is alleen maar zichtbaar als mensen de Tab-toets gebruiken om van link naar link te gaan. En precies voor die mensen is de link bedoeld.

In feite heb je op elke pagina alleen maar die ene simpele regel html van hierboven en een anker nodig. Daarnaast nog wat css, maar die is voor elke pagina hetzelfde. Dit soort hele kleine aanpassingen maakt het verschil tussen een volstrekt ontoegankelijke en een redelijk toegankelijke pagina.

De bij de skip-link horende css:

position: absolute;

Om de skip-link buiten het venster van de browser te kunnen parkeren. Ik kan hem ook onzichtbaar maken met display: none;, maar dan ziet niet elke spraakbrowser en dergelijke hem.

Een link is van zichzelf een inline-element. Door hem absoluut te positioneren verandert hij in een blok-element en kan ik eigenschappen als breedte en hoogte gebruiken.

left: -2000px;

Ver links buiten het venster van de browser parkeren, zodat hij normaal genomen onzichtbaar is.

top: 0;

Bovenaan het venster van de browser neerzetten.

z-index: 50;

Een z-index werkt alleen als het element absoluut, relatief of fixed is gepositioneerd, zoals hier het geval is. Ik wil zeker weten dat de skip-link altijd zichtbaar is (als hij binnen het venster van de browser wordt gezet) en niet onder 'n ander element verdwijnt, vandaar een vrij hoge z-index.

width: 10.5em;

De <a> is door hem absoluut te positioneren veranderd in een blok-element. Normaal genomen krijgt een blok-element automatisch dezelfde breedte als z'n ouder. Dat is hier de body, dus de link zou hier even breed als de pagina worden. Wat veel te breed zou zijn.

Een absoluut gepositioneerd blok-element krijgt echter niet dezelfde breedte als z'n ouder. Een absoluut gepositioneerd element wordt niet breder, dan nodig is om de inhoud van het blok-element weer te kunnen geven. De link wordt hier dus niet even breed als de pagina.

Ik maak de <a> iets breder dan de tekst erin. Dat levert links en rechts een lege ruimte op, en dat staat beter, vind ik.

border: red solid 3px;

Opvallende knalrode rand.

background: white;

Witte achtergrond, valt lekker op.

font-size: 2em;

Lekker grote letter. Als eenheid neem ik em, zodat ook gebruikers van Internet Explorer de lettergrootte kunnen veranderen.

text-align: center;

Tekst horizontaal centreren.

line-height: 2em;

Normaal genomen is een regelhoogte automatisch ongeveer 1,2 em. Een maat in em wordt altijd genomen ten opzichte van de lettergrootte, het is een relatieve grootte. Een grotere letter krijgt normaal genomen dus automatisch een grotere regelhoogte. Hierboven heb ik een lettergrootte van 2 em opgegeven. Dat is groter dan de standaardletter, dus de regelhoogte wordt ook groter, ook als ik deze niet zelf op zou geven.

Hier geef ik 2 em op, dus de regelhoogte wordt nog hoger dan nodig is. Hierdoor krijg ik aan boven- en onderkant een marge.

De <a> is door hem absoluut te positioneren veranderd in een blok-element. Normaal genomen krijgt een blok-element automatisch precies de hoogte die nodig is, om de inhoud van het blok-element weer te kunnen geven. Dat is hier, vanwege de regelhoogte, 2 em.

Ik had ook een gewone height van 2 em kunnen geven, maar regelhoogte heeft hier een voordeel boven height. Voor de link zelf maakt het niets uit, die past zich automatisch aan de hoogte van de inhoud aan, dus ook aan de hoogte van de regelhoogte. Maar tekst wordt automatisch verticaal in het midden van de regelhoogte neergezet. Door de skip-link een hoogte te geven met regelhoogte in plaats van met height, wordt de tekst van de skip-link gelijk verticaal gecentreerd binnen de skip-link.

Als eenheid neem ik em, zodat ook in Internet Explorer de regelhoogte mee verandert met de lettergrootte.

a#skippy:focus, a#skippy:active

Als de link met id="skippy" focus heeft of als deze actief is.

Een link heeft focus als je er met de Tab-toets (of een soortgelijke) toets bent aangekomen. Er staat dan een klein kadertje rondom de link, tenzij je dat zelf met css verandert. Als je op Enter drukt, wordt de link gevolgd.

Een link is actief, zolang je de muis indrukt op de link.

Althans: zo hoort het te zijn. Maar Microsoft heeft om volstrekt duistere redenen besloten om :focus niet te implementeren, en :active de werking van :focus te geven. In Internet Explorer 8 is deze enormiteit gelukkig eindelijk hersteld. Maar voor eerdere foutenfestivals van Microsoft, zoals Internet Explorer 7, is dus :active nodig.

left: 50%;

De skip-link stond ver links buiten het venster van de browser. Nu mag hij binnen het venster worden gezet en wordt dus zichtbaar. Hij wordt precies halverwege het venster neergezet, ongeacht de breedte van dat venster.

margin-left: -5.25em;

Weer 5,25 em terugzetten naar links.

Bij #skippy heeft de link een breedte van 10,5 em gekregen. Hier gelijk boven is hij halverwege het venster van de browser neergezet. Als ik hem nu de helft van die 10,5 em terug naar links zet, komt de helft van die 10,5 em dus links van het midden en de helft rechts van het midden van het venster te staan. Oftewel: horizontaal gecentreerd, ongeacht de breedte van het venster.

(In Internet Explorer 7 komt de skip-link te veel naar rechts te staan. Dat is ongetwijfeld op te lossen, maar ik buig nederig voor de geniale programmeurs van Microsoft en laat het zo. In Internet Explorer 8 en later staat de link wel op de goede plaats.)

nav

Alle <nav>'s. Dat is er hier maar eentje: de <nav> waarbinnen het menu staat.

<nav> is een van de nieuwe semantische html5-elementen. Meer daarover vind je bij Semantische elementen en outline. In principe is een <nav> niets meer dan een soort gespecialiseerde <div>, bedoeld voor menu's.

display: block;

Een <nav> is een blok-element. Maar oudere browsers kennen dit element niet, en die weten dat dus niet. Sommige browsers zullen het daarom als een inline-element weergeven of doen er andere vreemde dingen mee. Om dat te voorkomen, meld ik hier expliciet dat dit een blok-element is. Ooit zal dat niet meer nodig zijn, maar dat zal nog wel even duren.

width: 39.8em;

De zes submenu's met borders en dergelijke passen precies binnen deze breedte.

Bij li worden de lijst-ingangen naar links gefloat. Normaal genomen komen lijst-ingangen op een nieuwe regel te staan, omdat het blok-elementen zijn. Door ze naar links te floaten, komen ze naast elkaar te staan. Maar daarbij is het wel nodig dat ze ook echt in de beschikbare ruimte passen.

Als ik deze breedte te klein neem, komt de lijst-ingang die er niet meer in past gewoon op de volgende regel te staan. En dus ook de daarin zittende knop. Dit kan ook gebeuren bij zoomen, omdat de maten dan worden afgerond. Als je pech hebt, passen de zes knoppen daardoor net niet meer in de <nav>. Daarom neem ik de breedte 'n heel klein beetje breder dan nodig is.

Gebied waar hoveren werkt voor de knop 'Toebehoren'

Op de afbeelding is even een rood lijntje rondom de <nav> gezet. De <nav> is even extra smal gemaakt, zodat het duidelijker is dat deze te smal is. De laatste <li>, met de daarin zittende knop komt op de volgende regel te staan: hij past er gewoon niet meer naast.

Als eenheid neem ik em, waardoor de breedte mee verandert met een eventuele andere lettergrootte.

max-width: 1380px;

Aan de tekst is een maximumbreedte opgegeven. Op heel brede schermen zouden de regels anders te lang kunnen worden, waardoor ze moeilijk leesbaar worden.

De tekst is horizontaal gecentreerd. Door het menu dezelfde breedte te geven als de tekst en het menu ook horizontaal te centreren, blijft het menu altijd midden boven de tekst staan. Het horizontaal centreren van het menu gebeurt gelijk hieronder.

margin: 30px auto 0;

Omdat voor links geen waarde is opgegeven, krijgt links automatisch dezelfde waarde als rechts. Hier staat dus eigenlijk 30px auto 0 auto in de volgorde boven - rechts - onder - links.

Kleine afstand tussen bovenkant van het venster van de browser en bovenkant van het menu.

Links en rechts auto wat hier betekent: evenveel. Oftewel: de marge links en rechts is altijd even groot, waardoor het menu altijd horizontaal gecentreerd staat, ongeacht de breedte van het venster van de browser.

Deze manier van horizontaal centreren van een blok-element werkt alleen, als het te centreren blok-element een breedte heeft.

ul

Alle ongeordende lijsten.

Het hoofdmenu, de altijd zichtbare knoppen, staan in een <ul>. Elk submenu staat ook weer in een eigen <ul>.

Een <ul> is een blok-element. Een blok-element krijgt normaal genomen automatisch dezelfde breedte als zijn ouder. Dat is hier bij het hoofdmenu <nav>, en bij de submenu's een <li>. Omdat ik bij die <nav> en die <li>'s een breedte opgeef, hoef ik dat hier niet te doen, want de <ul>'s krijgen automatisch dezelfde breedte als de <nav> of de <li> waar ze in staan.

list-style-type: none;

De gebruikelijke bolletjes en dergelijke bij een <ul> zijn hier niet welkom.

margin: 0; padding: 0;

Verschillende browsers hebben verschillende standaardinstellingen voor marge en padding binnen een <ul>. Daarom moet je altijd zelf een marge en padding opgeven. In dit geval zeg ik gewoon dat ik helemaal geen marge en padding wil. Dan ziet het er ook overal hetzelfde uit.

li

Alle lijst-ingangen.

Veel instellingen zijn voor alle lijst-ingangen hetzelfde, die kan ik hier voor allemaal opgeven. Als een lijst-ingang afwijkende css nodig heeft, kan ik die later apart opgeven.

position: relative;

Kinderen van een element kunnen alleen gepositioneerd worden ten opzichte van dat element, als het element een relatieve, absolute of fixed positie heeft. De <ul>'s waarbinnen de submenu's staan, moeten gepositioneerd worden ten opzichte van de <li>'s in het hoofdmenu. Dat kan nu.

Omdat ik verder niets opgeef van top of left of zo, heeft dit verder geen enkele invloed. Op lijst-ingangen die dit niet nodig hebben, heeft het dan ook verder geen enkel effect.

float: left;

Een <li> is een blok-element. Normaal genomen komt het op een nieuwe regel te staan. Door ze naar links te floaten, komen ze naast elkaar te staan.

Dat wil zeggen: als er genoeg ruimte is. Bij het hoofdmenu, de altijd zichtbare knoppen, is die ruimte er. De <ul> waar ze in staan is een blok-element en wordt daarom even breed als zijn ouder: <nav>. En die heeft bij nav een breedte van 39,7 em gekregen.

De <ul>'s met de submenu's echter staan binnen een <li>. En die <li> krijgt gelijk hieronder een breedte van 6,5 em. Daardoor past er van de submenu's maar één <li> naast elkaar, waardoor elke <li> toch op een nieuwe regel komt te staan, ook al zijn ze gefloat. Precies de bedoeling: de submenu's openen nu als verticale rijtjes.

width: 6.5em;

Breedte. Als eenheid neem ik em, zodat de breedte mee verandert met de lettergrootte.

color: black;

Voorgrondkleur zwart. Dit is onder andere de kleur van de tekst.

Hoewel dit de standaardkleur is, geef ik de kleur toch op. Hieronder geef ik een achtergrondkleur op. Sommige mensen hebben zelf de voorgrond- en/of achtergrondkleur veranderd, bijvoorbeeld omdat ze slecht kleuren kunnen onderscheiden. Als ik nu de achtergrondkleur verander, maar niet de voorgrondkleur, loop ik het risico dat tekstkleur en achtergrondkleur te veel op elkaar gaan lijken.

Door beide op te geven, weet ik redelijk zeker dat achtergrond- en tekstkleur genoeg van elkaar blijven verschillen. Als de gebruiker !important heeft gebruikt, is er nog niets aan de hand, want dan veranderen achtergrond- en voorgrondkleur geen van beide.

Ik heb dit ook al bij de body opgegeven, maar sommige mensen hebben bij álle elementen de kleuren veranderd. Het heeft immers weinig zin, als ze dat alleen bij de body doen, terwijl de sitebouwer de kleuren ook bij bijvoorbeeld de paragrafen heeft aangepast.

background: #e4e4e4;

Grijs achtergrondkleurtje.

line-height: 2em;

Normaal genomen krijgt de <li> automatisch precies genoeg hoogte om de inhoud weer te kunnen geven. Hier maak ik de hoogte wat groter, dat levert iets hogere knoppen op.

Ik gebruik geen height, maar regelhoogte. Voor de hoogte van de <li> maakt dit geen verschil, die past zich automatisch aan. Maar voor de tekst maakt het wel verschil. Tekst wordt automatisch verticaal in het midden van de regelhoogte gezet, zodat de tekst verticaal gecentreerd staat. Als ik height zou gebruiken, zou dat niet gebeuren.

Als eenheid neem ik em, zodat ook in Internet Explorer de regelhoogte mee verandert met de lettergrootte.

text-align: center;

Tekst horizontaal centreren.

-moz-transition: 0.2s; -ms-transition: 0.2s; -o-transition: 0.2s; -webkit-transition: 0.2s; transition: 0.2s;

Hier staat in feite vijf keer hetzelfde: transition: 0.2s;. Waarom dat zo is, staat bij De voorvoegsels -moz-, -ms-, -o- en -webkit-.

Hierboven heb ik een grijze achtergrondkleur opgegeven. Als ik nu bij :hover, :focus, en dergelijke een andere kleur opgeef, zorgt transition ervoor dat die kleur niet in één keer wordt veranderd bij hoveren en dergelijke, maar langzaamaan. Als de kleur van grijs wordt veranderd naar wit, vindt die verandering geleidelijk aan plaats. De kleur verandert langzaam van grijs naar wit.

Internet Explorer 7, 8 en 9 ondersteunen transition niet. In deze browsers vindt de verandering gewoon in één keer plaats, zonder vertraging.

Bij transition staat maar één waarde: 0.2s. Als er maar één waarde wordt opgegeven, bepaalt die over hoeveel tijd de verandering wordt uitgesmeerd. Dat is hier vrij kort: nog geen halve seconde. Een eventuele tweede waarde, die hier ontbreekt, geeft een eventueel uitstel aan het begin aan.

Het is ook mogelijk om het verloop van de verandering aan te geven met behulp van sleutelwoorden of getallen. Hiermee kun je bijvoorbeeld aangeven dat de verandering aan het eind snel of juist langzaam moet gaan. Bij een verandering die maar 0,2 seconde duurt, is dat natuurlijk volmaakt zinloos.

transition brengt nog een geheel eigen risico met zich mee. In de specificatie staat, welke eigenschappen met behulp van transition kunnen veranderen. Je kunt eventueel bij transition opgeven, voor welke eigenschappen het geldt. Als ik bijvoorbeeld top en left beide wil veranderen bij :hover, kan ik bijvoorbeeld aangeven dat de geleidelijke verandering met behulp van transition alleen voor top geldt. left verandert dan gewoon in één keer.

Als ik niet opgeef, voor welke eigenschappen transition geldt, geldt het voor álle eigenschappen die bij :hover, :focus, en dergelijke worden veranderd. Als daar 'n eigenschap bij zit die op dit moment niet door transition kan worden vertraagd, verandert die gewoon in één keer. Maar als de specificatie of een van de browsermakers de geest krijgt en plotsklaps die eigenschap ook onder transition laat vallen, kan dat tot heel onverwachte resultaten leiden.

Stel dat je iets heel traag zichtbaar wilt laten worden bij :hover en iets anders flitsend snel. Mogelijk wordt dat flitsend snel dan opeens ook heel traag. Daarom moet je absoluut zeker weten dat ook in de toekomst geen problemen kunnen ontstaan.

In dit geval gebruik ik alleen :hover en geen :focus of :active. Verderop bij li:hover verander ik de achtergrondkleur. Verder verandert er niets. In dit geval mag dus alles vertraagd worden veranderd. Als dat niet zo is, zou ik moeten opgeven voor welke eigenschappen transition geldt.

Je kunt transition beperken tot bepaalde eigenschappen door die eigenschappen te noemen, gevolgd door tijdsduur en eventueel vertraging:

transition: left 2s; top 3s 1s;
#top > li

De lijst-ingangen binnen het element met id="top".

#top is de eerste <ul>, de <ul> die bij het hoofdmenu met de altijd zichtbare knoppen hoort. Maar ook de lijst-ingangen van de submenu's liggen binnen ul#top. Dus de css die ik hier opgeef, zou ook voor die lijst-ingangen gelden. En dat gaat problemen geven, want hieronder geef ik borders op, en die moeten voor de submenu's op een andere manier worden samengesteld.

De toevoeging > voorkomt dat deze css ook voor de <li>'s in de submenu's zou gelden. Dit teken betekent dat deze regel alleen geldt voor <li>'s die een direct kind zijn van ul#top. En dat zijn alleen de lijst-ingangen die bij het hoofdmenu met de altijd zichtbare knoppen horen.

De <li>'s uit de submenu's staan in een <ul>, die weer een kind is van een <li>:

<ul id="top"> <li>Direct kind van ul#top <ul> <li>Geen direct kind, want
er zitten 'n <li> en 'n <ul> tussen
(...) </li> </ul> </li> </ul>

De <li>'s uit de submenu's zijn geen directe kinderen van ul#top, dus geldt deze regel niet voor hun.

border: black solid;

Zwart kadertje. Gelijk hieronder geef ik de breedte op.

border-width: 1px 1px 1px 0;

Breedte van het kadertje. Gelijk hierboven heb ik kleur en stijl al opgegeven.

Zonder correctie dubbele verticale borders

Er moet aan alle kanten een kadertje komen, behalve aan de linkerkant. Omdat de <li>'s tegen elkaar aan komen te staan, zouden de borders van twee elkaar rakende <li>'s anders tegen elkaar aan komen te staan. En dat zou een border van 2 px breed opleveren, zoals op de afbeelding is te zien.

Deze manier van opgeven van een border, de breedte gesplitst van stijl en kleur, is in dit geval korter dan het volledig uitschrijven van alle vier de borders apart.

#top li:first-child

De <li> binnen het element met id="top", maar alleen als die <li> het eerste kind is van #top. ul#top is de <ul> die bij het hoofdmenu met de altijd zichtbare knoppen hoort. De eerste <li> daarbinnen, het eerste kind, is de <li> die bij de meest linkse knop hoort.

border-left: black solid 1px;

Bij #top > li heb ik alle <li>'s een border gegeven, maar alleen aan de boven-, rechter- en onderkant. Omdat de <li>'s tegen elkaar staan, hebben ze voor het oog toch aan alle kanten een border. Behalve de meest linkse: die mist de border aan de linkerkant. Die geef ik hier alsnog.

li ul

Alle ongeordende lijsten die binnen een lijst-ingang staan.

Dat zijn in dit geval de <ul>'s met de submenu's, want alleen die staan binnen een <li>. Het hoofdmenu met de altijd zichtbare knoppen staat niet binnen een <li>, dus daarvoor geldt deze regel niet.

position: absolute;

Om het submenu op een bepaalde plaats neer te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste ouder die zelf een absolute, relatieve of fixed positie heeft. Dat is in dit geval de <li>, waarbinnen de <ul> staat.

Je zou het submenu ook op andere manieren op de juiste plaats neer kunnen zetten. Maar in dit geval heeft het gebruik van een absolute positie voordelen. Normaal genomen is het submenu niet zichtbaar, omdat het boven het venster van de browser is geparkeerd. Het neemt dan ook geen ruimte in binnen het venster.

Als het wordt geopend, komt het binnen het venster te staan en neemt dan wel ruimte in. Waardoor het andere onderdelen van de pagina van hun plaats zou drukken. Dit kun je voorkomen door het element een absolute positie te geven. Een absoluut gepositioneerd element gedraagt zich hetzelfde als een absoluut heerser: het houdt nergens rekening mee. Het komt gewoon asociaal over de andere elementen heen te staan. Bij een submenu is dat, anders dan bij een absoluut heerser, precies de bedoeling.

top: -2000px; Submenu's even allemaal binnen het venster neergezet

2000 px naar boven verplaatsen. Daarmee staan de <ul>'s ver boven het venster van de browser en zijn dus onzichtbaar.

In feite zijn de submenu's gewoon voortdurend open, maar je ziet ze niet, omdat ze boven het venster staan. Als ik de top: -2000px; even verander in top: 60px; komen de submenu's binnen het venster van de browser te staan. Op de afbeelding is te zien, dat ze inderdaad allemaal compleet aanwezig zijn.

Ik maak de menu's niet onzichtbaar met display: none; omdat sommige spraakbrowsers en dergelijke het de menu's dan helemaal negeren.

left: -1px; Zonder correctie dubbele verticale borders

1 px naar links verplaatsen.

De <ul>'s met de submenu's hebben een zwart kadertje. De <li>'s met de knoppen waar de submenu's onder openen ook. Als ik de <ul> gewoon laat openen zonder correctie, opent hij binnen de breedte van de knop. De border van de <li> doet daarbij niet mee. Hierdoor komt het zwarte kadertje rondom het submenu 1 px te veel naar rechts te staan, zoals op de afbeelding is te zien.

opacity: 0;

Volledig doorzichtig maken, waardoor de <ul>'s en de inhoud daarvan onzichtbaar worden.

-moz-transition: opacity 0.3s; -ms-transition: opacity 0.3s; -o-transition: opacity 0.3s; -webkit-transition: opacity 0.3s; transition: opacity 0.3s;

Hier staat in feite vijf keer hetzelfde: transition: opacity 0.3s;. Waarom dat zo is, staat bij De voorvoegsels -moz-, -ms-, -o- en -webkit-.

Hierboven heb ik de <ul>'s volledig doorzichtig gemaakt. Als ik nu bij :hover, :focus, en dergelijke ze weer ondoorzichtig, dus zichtbaar, maak, zorgt transition ervoor dat ze niet in één zichtbaar worden bij hoveren en dergelijke, maar langzaamaan. Als de <ul>'s (en dus de erin zittende submenu's) van onzichtbaar naar zichtbaar veranderen, vindt die verandering geleidelijk aan plaats.

Internet Explorer 7, 8 en 9 ondersteunen transition niet. In deze browsers vindt de verandering gewoon in één keer plaats, zonder vertraging.

Bij transition staat maar één waarde: 0.3s. Als er maar één waarde wordt opgegeven, bepaalt die over hoeveel tijd de verandering wordt uitgesmeerd. Dat is hier vrij kort: nog geen halve seconde. Een eventuele tweede waarde, die hier ontbreekt, geeft een eventueel uitstel aan het begin aan.

Het is ook mogelijk om het verloop van de verandering aan te geven met behulp van sleutelwoorden of getallen. Hiermee kun je bijvoorbeeld aangeven dat de verandering aan het eind snel of juist langzaam moet gaan. Bij een verandering die maar 0,3 seconde duurt, is dat natuurlijk volmaakt zinloos.

transition brengt nog een geheel eigen risico met zich mee. In de specificatie staat, welke eigenschappen met behulp van transition kunnen veranderen. Je kunt eventueel bij transition opgeven, voor welke eigenschappen het geldt. Als ik bijvoorbeeld top en left beide wil veranderen bij :hover, kan ik bijvoorbeeld aangeven dat de geleidelijke verandering met behulp van transition alleen voor top geldt. left verandert dan gewoon in één keer.

Als ik niet opgeef, voor welke eigenschappen transition geldt, geldt het voor álle eigenschappen die bij :hover, :focus, en dergelijke worden veranderd. Als daar 'n eigenschap bij zit die op dit moment niet door transition kan worden vertraagd, verandert die gewoon in één keer. Maar als de specificatie of een van de browsermakers de geest krijgt en plotsklaps die eigenschap ook onder transition laat vallen, kan dat tot heel onverwachte resultaten leiden.

Stel dat je iets heel traag zichtbaar wilt laten worden bij :hover en iets anders flitsend snel. Mogelijk wordt dat flitsend snel dan opeens ook heel traag. Daarom moet je absoluut zeker weten dat ook in de toekomst geen problemen kunnen ontstaan.

In dit geval gebruik ik alleen :hover en geen :focus of :active. Verderop bij li:hover ul verander ik de positie van de <ul>, de marge aan de bovenkant van de <ul> en de doorzichtigheid.

De marge aan de bovenkant van de <ul> is 1 px. Bij ul heb ik opgegeven dat de marge 0 is. De verandering van 0 naar 1 px is zo klein en zo snel, dat het hier niets uitmaakt of je dat ziet of niet. Dit levert dus geen problemen op.

De zichtbaarheid wordt veranderd van volledig doorzichtig (onzichtbaar) naar volledig ondoorzichtig (zichtbaar). Dat wil ik langzaamaan veranderen, omdat hierdoor het submenu wat rustiger opent.

Verder verandert top nog. Dat is hierboven op -2000 px ingesteld en wordt bij li:hover ul veranderd in 2 em. En dat levert een probleem op. In plaats van dat het submenu wat rustiger opent, scheurt het als 'n soort raceauto van bovenaf het venster binnen: in 0,3 seconde wordt -2000px veranderd in 2 em. Bij top is de vertraging hier uiterst storend.

In dit geval maakt de verandering voor de margin-top niets uit, is hij nodig voor opacity en mag hij niet plaatsvinden bij top. Daarom geef ik hier aan voor welke veranderingen transition is bedoeld. In dit geval is dat alleen opacity.

Je kunt dat doen door de naam van de eigenschap op te geven:

transition: opacity 0.3s;

Nu geldt de vertraging alleen voor opacity. De eigenschappen margin-top en top worden net als normaal, in één keer, veranderd.

li li

Alle lijst-ingangen die binnen een lijst-ingang liggen. De lijst-ingangen van het hoofdmenu met de altijd zichtbare knoppen liggen niet binnen een andere <ul>, en dus ook niet binnen een <li>. De lijst-ingangen van de submenu's wel. Deze regel heeft dus alleen betrekking op de lijst-ingangen van de submenu's.

border: black solid;

Zwarte kadertje. Gelijk hieronder geef ik de breedte op.

border-width: 0 1px 1px;

Breedte van het kadertje. Gelijk hierboven heb ik kleur en stijl al opgegeven.

Zonder correctie dubbele horizontale borders

Omdat voor links geen waarde is opgegeven, krijgt links automatisch dezelfde waarde als rechts. Hier staat dus eigenlijk 0 1px 1px 1px in de volgorde boven - rechts - onder - links.

Er moet aan alle kanten een kadertje komen, behalve aan de bovenkant. Omdat de <li>'s tegen elkaar aan komen te staan, zouden de borders van twee elkaar rakende <li>'s anders tegen elkaar aan komen te staan. En dat zou een border van 2 px dik opleveren, zoals op de afbeelding is te zien.

Deze manier van opgeven van een border, de breedte gesplitst van stijl en kleur, is in dit geval korter dan het volledig uitschrijven van drie borders apart.

nav a

De links binnen een <nav>. Alleen binnen de submenu's zitten links, daarvoor geldt deze regel.

Eigenlijk is de toevoeging nav hier niet nodig, omdat op deze pagina alleen maar links binnen submenu's zitten. Maar vaak zullen er meer links op een pagina aanwezig zijn, en het is niet de bedoeling dat deze css voor álle links op de pagina gaat werken.

display: block;

Van zichzelf is een <a> een inline-element. Dat heeft hier een aantal nadelen, daarom verander ik het in een blok-element.

Als de links niet in een blok-element worden veranderd

Op de afbeelding hiernaast is de <a> niet veranderd in een blok-element en dus gewoon een inline-element. Het rood geeft de grootte van de <a> aan. Alleen het rode deel werkt als een link, alleen als je daarop klikt, wordt de link gevolgd. Terwijl mensen verwachten dat de hele knop als link werkt.

Door van de <a> een blok-element te maken, werkt de hele knop als link. Een blok-element wordt, in tegenstelling tot een inline-element, normaal genomen even breed als z'n ouder. Dat is hier de <li>, die bij li een breedte van 6,5 em heeft gekregen. Precies de bedoeling dus.

Een blok-element krijgt normaal genomen ook dezelfde regelhoogte als z'n ouder. Dat is hier ook weer de <li>, die bij li een regelhoogte van 2 em heeft gekregen.

Door een blok-element van de <a> te maken, wordt de link even groot als de lijst-ingang waar hij in staat. En omdat de link nu even groot is als de lijst-ingang met de daarin zittende knop, werkt klikken nu ook op de hele knop.

text-decoration: none;

Normaal genomen wordt tekst in een link onderstreept. Dat wil ik hier niet.

color: black;

Normaal genomen wordt link in een tekst gekleurd, dat wil ik hier niet.

li:hover

Als ik over een lijst-ingang hover.

background: white;

Achtergrond wit maken.

Als niet over de <li> wordt gehoverd, is de achtergrond grijs. Bij li heb ik met behulp van transition een kleine vertraging aan de verandering van kleur gegeven: het grijs verandert geleidelijk in wit.

li:hover ul

Als ik over een lijst-ingang hover, doe dan iets met de daarin zittende ongeordende lijst.

De enige <ul>'s die binnen een <li> zitten, zijn de <ul>'s waarbinnen de submenu's zitten. Het hoofdmenu met de altijd zichtbare knoppen zit niet binnen een <li>, dus daar geldt deze regel niet voor.

top: 2em;

Bij li ul zijn deze lijsten boven het venster van de browser neergezet, waardoor ze onzichtbaar zijn. Nu worden ze binnen het venster gezet, waardoor ze zichtbaar worden.

Dat wil zeggen: er wordt er eentje zichtbaar. Het hoofdmenu bestaat uit zes <li>'s, en alleen het submenu binnen de <li> waarover wordt gehoverd, wordt zichtbaar.

Bij li hebben alle lijst-ingangen een regelhoogte (en daardoor een hoogte) van 2 em gekregen. De <ul> met het submenu komt dus precies hieronder te staan. En omdat als eenheid em is genomen, verandert de plaats mee met een eventuele andere lettergrootte.

margin-top: 1px; Zonder correctie valt deel border weg

De hoogte van de altijd zichtbare knoppen is 2 em. Daaronder komt nog een border van 1 px. Daarom moet ik het submenu's 1 px lager neerzetten, want anders komt het over deze border te staan, zoals hiernaast is te zien.

Normaal genomen zou ik margin-top bij li ul hebben gezet, bij de rest van de opmaak. Alles op één plek is overzichtelijker. Maar hoveren werkt slecht in IE 7. Een van de workarounds is om bij hoveren de marge te veranderen, dan werkt hoveren wel. En andere browsers hebben er geen last van, dus...

opacity: 1;

Volledig ondoorzichtig maken, waardoor de <ul> en dus het daarin zittende submenu zichtbaar wordt.

Als niet over de <li> wordt gehoverd, is de erin zittende <ul> volledig doorzichtig, dus onzichtbaar. Bij li ul heb ik met behulp van transition een kleine vertraging aan de verandering van doorzichtigheid gegeven: de <ul> wordt geleidelijk aan zichtbaar.

#content

Het element met id="content".

clear: both;

De <li>'s zijn allemaal naar links gefloat. Dat heeft als bijeffect dat later komende tekst naast de <li>'s wordt gezet. Hiermee zorg ik ervoor dat de tekst op een nieuwe regel komt te staan.

max-width: 1380px;

Maximumbreedte om een te lange regel op heel brede schermen te voorkomen. Dit is trouwens nog steeds veel te lang, maar omdat het hier om opvultekst gaat, is dat niet zo belangrijk.

margin: 0 auto;

Omdat voor onder en links geen waarde is ingevuld, krijgen die automatisch dezelfde waarde als boven en rechts. Hier staat dus eigenlijk 0 auto 0 auto in de volgorde boven - rechts - onder - links.

Boven en onder geen marge.

Links en rechts auto wat hier betekent: evenveel. Oftewel: de tekst staat altijd horizontaal gecentreerd, ongeacht de breedte van het venster van de browser.

Omdat de <nav> waar het menu in staat dezelfde maximumbreedte heeft gekregen en op dezelfde manier wordt gecentreerd als deze div met tekst, zal het menu altijd midden boven de tekst staan, ongeacht de breedte van het venster.

padding: 1px 30px;

Omdat voor onder en links geen waarde is opgegeven, krijgen die automatisch dezelfde waarde als boven en rechts. Hier staat dus eigenlijk 1px 30px 1px 30px in de volgorde boven - rechts - onder - links.

Links en rechts wat ruimte tussen de buitenkant van het venster van de browser en de tekst. Dat is simpel.

Maar waarom boven en onder 1 px padding? Tja, dat ligt wat ingewikkeld.

De padding aan de onderkant is onbelangrijk, die had ik ook weg kunnen laten door als waarden op te geven: 1px 30px 0. Maar omdat die ene px aan de onderkant niets uitmaakt, heb ik 'm gewoon laten staan.

De ene px aan de bovenkant maakt wel uit. En niet zo weinig ook.

In heel veel gevallen worden verticale marges samengevoegd. Dat is heel vaak precies de bedoeling, maar niet altijd. Hier is het niet de bedoeling. En die padding van 1 px voorkomt dat samenvoegen hier.

Deze pagina is opgedeeld in twee grote blokken: <nav> met het menu en div#content met de tekst.

<nav> heeft aan de bovenkant een marge van 30 px. <nav> is een blok-element, en dat krijgt normaal genomen automatisch precies genoeg hoogte om de inhoud ervan weer te kunnen geven. Die inhoud is de ul#top waarin het hele menu staat.

ul#top is ook weer een blok-element, dus die krijgt ook automatisch genoeg hoogte om de inhoud weer te kunnen geven. En die hoogte wordt dan doorgegeven aan <nav>.

Maar niet hier. De inhoud van ul#top is namelijk gefloat, en elementen die gefloat zijn, hebben geen invloed op de hoogte van hun ouder. ul#top heeft dus geen hoogte, en <nav> daarom ook niet.

We hebben dus een <nav> zonder hoogte en met een marge aan de bovenkant van 30 px.

Het tweede deel van de pagina zit in div#content. Deze div heeft gewoon een hoogte en zo, want de inhoud is niet gefloat of wat dan ook. div#content heeft verder geen marge. Eigenlijk jok ik een beetje, want een div heeft altijd een marge. Maar als ik die verder niet opgeef, is dat gewoon de standaardmarge van 0 px.

Het eerste element binnen div#content is een <p>. Een paragraaf heeft van zichzelf een marge aan boven- en onderkant. Hier is alleen de marge aan de bovenkant van belang. Die is ongeveer 20 px.

Eigenlijk heb ik dus een div met een marge van 0 px aan de bovenkant, en daarbinnen een paragraaf met een standaardmarge aan de bovenkant van ongeveer 20 px. De marge van het eerste blok-element, hier de paragraaf, wordt normaal genomen samengevoegd met de marge van de ouder, hier div#content.

Hier betekent dat, dat de marge van 0 px aan de boven van de div wordt samengevoegd met de marge van ongeveer 20 px aan de bovenkant van de paragraaf. Waarmee div#content dus plotsklaps wél een marge aan de bovenkant heeft van ongeveer 20 px. Dit lijkt misschien onhandig, maar meestal is dit precies wat je wilt.

Ik heb nu dus een <nav> die feitelijk leeg is, met een hoogte van 0, en een marge aan de bovenkant van 30 px. En daar gelijk onder een div met een marge aan de bovenkant van 20 px.

Ook in dit geval worden deze marges weer samengevoegd. Ook hier geldt weer: dit is meestal wat je wilt.

Alleen nu niet.

In feite is de marge van de eerste paragraaf helemaal naar boven getransporteerd en valt die weg binnen de marge aan de bovenkant van <nav>. Waardoor de paragraaf veel te dicht op het menu komt te staan. Want daar was die marge nou juist handig voor.

Door het toevoegen van 'n padding van 1 px aan de bovenkant van div#content blokkeer je het samenvoegen van de twee marges. De marge aan de bovenkant van de paragraaf wordt nog steeds verplaatst naar de bovenkant van div#content. Maar de marge aan de bovenkant van div#content wordt, door de padding van 1 px, niet meer samengevoegd met de marge aan de bovenkant van <nav>.

JavaScript voor Internet Explorer 7 en 8

In de <head> staat, gelijk onder de css, een klein stukje JavaScript, binnen een 'conditional comment':

<!--[if lt IE 9]> <script> document.createElement("nav"); </script> <![endif]-->

Omdat deze code tussen <!-- en --> staat, wordt de code gezien als een commentaar en dus genegeerd door de browser. Behalve door Internet Explorer. Microsoft heeft een handigheidje bedacht, waardoor je het commentaar kunt gebruiken om alleen voor (een bepaalde versie van) Internet Explorer code te schrijven. Dat is wel nodig ook, want hoe ouder de versie, des te groter de ongelooflijke verzameling bugs en afwijkingen die Microsoft in z'n browsers heeft weten te proppen. Pas Internet Explorer 9 begint zich een een heel klein beetje als een volwassen browser te gedragen. Niet dat het evenveel kan als andere browsers, bij lange na niet, maar hij verpest in ieder geval niet meer van alles.

<!--[if lt IE 9]>: om het stukje tussen de teksthaken gaat het: if lt IE 9. lt is een afkorting voor less than: minder dan. In normale mensentaal staat hier: als minder dan Internet Explorer 9. Oftewel: elke versie van Internet Explorer ouder dan versie 9. Omdat ik alleen versie 7 en 8 nog ondersteun, gaat het in dit geval alleen om die twee. Het zou kunnen dat dit in Internet Explorer 6 werkt, het zou ook kunnen dat je computer in de fik vliegt en dat je partner de benen neemt. Dit stukje code opent het deel dat alleen door Internet Explorer 7 en 8 wordt gelezen.

<![endif]--> sluit de code voor Internet Explorer weer af.

Het is belangrijk dat de spaties in <!--[if lt IE 9]> en <![endif]--> precies zo worden overgenomen, zoals ze hier staan, want anders werkt het niet.

<script> en </script> geven gewoon het begin en einde van het JavaScript aan. Bij html5 hoef je geen type meer op te geven, want het staat standaard op JavaScript ingesteld.

document.createElement("nav"); is het eigenlijke stukje JavaScript. Tegen de standaard in kun je in Internet Explorer 8 en ouder geen css gebruiken bij onbekende elementen. En hier wordt het nieuwe html5-element <nav> gebruikt. De css voor <nav> zou dus niet werken.

Door nu via JavaScript het voor Internet Explorer 7 en 8 onbekende element <nav> gewoon zelf aan te maken, blijkt het plotsklaps wél herkend te worden. En kan dus gewoon css voor dit element worden gebruikt.

(In feite wordt <nav> aan de DOM toegevoegd, een soort inhoudsopgave van onder andere alle html-elementen in een pagina.)

Internet Explorer 9 kent <nav>, dus voor deze browser zijn geen speciale voorzieningen nodig.

Anders dan vaak het geval is, moet deze JavaScript in de <head> van de pagina staan. De browser moet de elementen al kennen, voordat ze kunnen worden weergegeven. Als de elementen worden gelezen, voordat ze zijn aangemaakt, worden ze gewoon genegeerd. En kan er dus ook geen css aan worden gegeven.

Deze JavaScript is uiterst beperkt: alleen de hier gebruikte html5-elementen worden aangemaakt, en dan alleen nog maar voor weergave op een scherm. Als je meer wilt doen dan alleen dit, is het mogelijk beter om voor Internet Explorer 7 en 8 het JavaScript op html5shiv te gebruiken.

Dit betekent helaas ook dat de css in Internet Explorer 7 en 8 niet werkt, als de bezoeker JavaScript uit heeft staan. Maar normaal genomen staat JavaScript alleen uit vanwege de veiligheid. En als je ook maar enigszins met veiligheid bezig bent, dan zul je niet Internet Explorer 7 of 8 gebruiken. Dus het aantal mensen waarbij in deze verouderde browsers JavaScript uit zal staan, is waarschijnlijk te verwaarlozen.

Mocht dit wel een bezwaar zijn, dan zul je <nav> door een gewone <div> moeten vervangen. Overigens wordt css hier alleen gebruikt om de <nav> te centreren en een blok-element van de links te maken. Ook zonder JavaScript zal het menu nog gewoon werken, alleen staat het niet meer in het midden en moet je precies op de tekst van de link klikken.

Een andere mogelijkheid is het gebruik van <noscript>, zoals ik op de site doe. Dit moet dan alleen voor Internet Explorer 7 en 8 worden gebruikt, want andere browsers herkennen de nieuwe elementen en hebben geen JavaScript nodig. In Internet Explorer kan <noscript> alleen css krijgen via een inline-style. Het wordt dan zoiets:

<!--[if lt IE 9]> <noscript> <div style="border: dotted red 10px; padding: 5px; background: white;"> Helaas, dit menu werkt niet zo goed als zou kunnen met oudere versies van Internet Explorer zonder JavaScript.<br> Drie mogelijkheden:<br> * Schakel JavaScript in;<br> * Installeer Internet Explorer 9;<br> * Stop met die troep van Miscrosoft en installeer 'n échte browser zoals Firefox, Google Chrome, Opera of Safari. </div> </noscript> <![endif]-->

De code aanpassen aan je eigen ontwerp

Toegankelijkheid en zoekmachines

Het eerste deel van deze tekst is voor alle voorbeelden hetzelfde. Eventueel specifiek voor dit voorbeeld geldende dingen staan verderop onder het kopje Specifiek voor dit voorbeeld.

Toegankelijkheid (accessibility in het Engels) is belangrijk voor bijvoorbeeld blinden die een spraakbrowser gebruiken, of voor motorisch gehandicapte mensen die moeite hebben met het bedienen van een muis. Een spider van een zoekmachine (dat is het programmaatje wat de site indexeert voor de zoekmachine) is te vergelijken met een blinde. Als je je site goed toegankelijk maakt voor gehandicapten, is dat dus gelijk goed voor een hogere plaats in een zoekmachine. Dus als je 't niet uit sociale motieven wilt doen, kun je 't uit egoïstische motieven doen.

(Op die plaats in de zoekmachine heb je maar beperkt invloed. De toegankelijkheid van je site is maar één van de factoren, maar zeker niet onbelangrijk.)

Als je bij het maken van je site al rekening houdt met toegankelijkheid, is dat nauwelijks extra werk. 't Is ongeveer te vergelijken met inbraakbescherming: doe dat bij 'n nieuw huis en 't is nauwelijks extra werk, doe 't bij 'n bestaand huis en 't is al snel 'n enorme klus.

Enkele tips die helpen bij toegankelijkheid:

Specifiek voor dit voorbeeld

Getest in

Laatst gecontroleerd op 5 maart 2012.

Dit voorbeeld is getest in Firefox, Opera, Safari, Google Chrome, Internet Explorer 7, 8 en 9 in de resoluties 800x600, 1024x768, 1280x1024 en 1440x900. Steeds met de laatste versie van die browsers, omdat ik geen zin heb om rekening te houden met mensen die met zwaar verouderde browsers surfen. Dat is trouwens vragen om ellende, want updates van browsers hebben heel vaak met beveiligingsproblemen te maken. In de resoluties 1024x768, 1280x1024 en 1440x900 is ook in- en uitzoomen en een kleinere en grotere letter getest. Er is ingezoomd en vergroot tot zover de browser kan, maar niet verder dan tot 200%.

Eventuele problemen met betrekking tot zoomen en lettergrootte staan bij Bekende problemen.

Er is getest met behulp van muis en toetsenbord.

Naast deze 'gewone' browsers is ook getest in Lynx, WebbIE, NVDA en Fangs Screen Reader Emulator. Lynx is een browser die alleen tekst laat zien en geen css gebruikt. WebbIE is een browser die gericht is op mensen met een handicap. NVDA is een screenreader, zoals die door blinden wordt gebruikt. Fangs Screen Reader Emulator is een extensie bij Firefox die de pagina laat zien zoals een screenreader hem ziet.

Als het voorbeeld in deze vier programma's toegankelijk is, zou het in principe toegankelijk moeten zijn in alle aangepaste browsers en dergelijke. En dus ook voor zoekmachines, want een zoekmachine is redelijk vergelijkbaar met een blinde. Eventuele opmerkingen over de toegankelijkheid van dit voorbeeld staan onderaan Toegankelijkheid en zoekmachines onder het kopje Specifiek voor dit voorbeeld.

Alleen op de hierboven genoemde systemen en browsers is getest. Er is dus niet getest op bijvoorbeeld mobiele systemen als iOS of Android, en ook niet op apparaten als smartphones, iPad, enz. De kans is heel erg groot dat dit voorbeeld niet (volledig) werkt op dat soort systemen en apparaten. Om het wel (volledig) werkend te krijgen, zul je vaak wijzigingen en/of aanvullingen moeten aanbrengen.

De html is gevalideerd met de validator van w3c, de css ook. Als om een of andere reden niet volledig gevalideerd kon worden, wordt dat bij Bekende problemen vermeld.

Nieuwe browsers test ik pas als ze uit het bèta-stadium zijn, omdat er anders 'n redelijke kans is dat ik 'n bug zit te omzeilen, die voor de uiteindelijke versie nog gerepareerd wordt. Dit voorbeeld is alleen getest in de hierboven met name genoemde browsers. Vragen over niet-geteste browsers kan ik niet beantwoorden, en het melden van fouten in niet-geteste browsers heeft ook geen enkel nut. (Melden van fouten, problemen, enz. in wel geteste browsers: graag!)

Wijzigingen

Alleen grotere wijzigingen worden hier vermeld, geen dingen als een link die is geüpdatet.

Nieuw opgenomen.

13 januari 2010:

Bij Bekende problemen → Toegankelijkheid stukje over Opera herschreven. Opera blijkt 'n aantal fantastische mogelijkheden te hebben, die helaas nauwelijks te vinden zijn.

6 februari 2011:

5 maart 2012:

Volledig herschreven.

31 maart 2012:

Paar kleine onjuistheden uit stuk over Javascript gehaald.

Bekende problemen

Internet Explorer 7, 8 en 9

Bij het openen van de submenu's en bij het verkleuren van de achtergrond, wordt gebruikt gemaakt van transition, een eigenschap uit css3. Deze browsers kennen die eigenschap niet. transition zorgt voor een kleine vertraging. Alles werkt in deze browsers gewoon zoals het hoort, alleen de kleine vertraging mist.

Internet Explorer 7 en Opera

Bij inzoomen (vergroten) verdubbelen sommige kadertjes. Bij uitzoomen (verkleinen) verdwijnt 'n enkel lijntje. In Internet Explorer 7 kun je ook de lettergrootte veranderen, maar dan speelt dit niet.

Valideren

Omdat de css-validator van w3c om wat voor reden dan ook soms nogal achter schijnt te lopen, wordt de eigenschap transition als een fout aangegeven. Dit is dus eigenlijk een fout van de validator en niet van de eigenschap.