Skip links en inhoudsopgave

Uitleg knoppen met toelichting en indicatie van huidige, bezochte en onbezochte pagina's

Laatst aangepast: .

Afbeelding 1: het menu in bredere en smallere vensters

Korte omschrijving

Menu met acht knoppen. In bredere browservensters verschijnt bij hoveren over of aanraken van een knop een bijpassende tekst. Een onderstreping geeft aan, of de link al is bezocht.

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

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 (Kubuntu). Daarbij is vooral gebruik gemaakt van Komodo Edit, GIMP en Firefox met extensies. De pdf-bestanden zijn gemaakt met LibreOffice.

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

Achterliggend idee

In de vorige versie was het leven nog mooi, omdat touchscreens nog nauwelijks gebruikt werden. De pop-ups konden gewoon met :hover worden gemaakt en iedereen was gelukkig en tevreden. Toen vonden computerfabrikanten het nodig om machines te maken, die alleen reageren op zware handtastelijkheden: touchscreens.

Bij touchscreens werkt :hover niet zonder meer. Je kunt er wel met je neus of 'n ander uitstekend lichaamsdeel vlak boven gaan hangen, maar dat levert in het gunstigste geval alleen 'n vies scherm op. Daarom moest de code ingrijpend worden gewijzigd, om dit menu ook op touchscreens werkend te krijgen.

De code valt in twee grote delen uiteen: browservensters smaller dan 740 px en vensters breder dan 740 px. Die tweedeling wordt bereikt door nieuwe @media-regels uit css3 te gebruiken. Elke browser gebruikt de css voor smallere vensters. Pas als de browser daadwerkelijk meldt dat het venster breder is, wordt de css voor browservensters breder dan 740 px gebruikt. Hierdoor werkt dit menu ook in heel oude en heel simpele browsers.

Vensters smaller dan 740 px

In zo'n smal venster zullen mensen niet zitten wachten op een menu, dat voortdurend aanwezig is en voortdurend een deel van de schaarse ruimte in beslag neemt.

In deze vensters staat daarom bovenaan de pagina alleen een balk met daarin de tekst 'Menu open' of 'Menu dicht'. Deze tekst staat in een <label>. Dat <label> hoort bij een checkbox.

De checkbox zelf wordt verborgen, zodat je hem niet ziet. Maar dat maakt voor de werking verder niets uit. Door op het bijbehorende <label> te klikken of door dit aan te raken, wordt de checkbox gewoon uit‑ of aangevinkt, of je hem nu ziet of niet.

Een van de nieuwe pseudo-classes uit css3 is :checked. Door als selector combinaties als :checked + #menu te gebruiken, kun je iets op het scherm veranderen, afhankelijk van of de checkbox :checked (aangevinkt) is of niet.

Het woordje 'Menu' staat altijd op het scherm, maar de daaropvolgende woordjes 'open' of 'dicht' zijn afhankelijk van het al dan niet aangevinkt zijn van de checkbox. Ze worden met behulp van content gegenereerd.

Het menu zelf heeft normaal genomen een breedte van 0 px, waarbij overflow op hidden is gezet. Hierdoor is het menu normaal genomen onzichtbaar. Als de checkbox is aangevinkt, krijgt het menu een breedte, waardoor het zichtbaar wordt en gebruikt kan worden.

Het geheel is wat opgeleukt met transition en kadertjes en zo, maar dat is voor de verdere werking niet echt van belang.

Vensters breder dan 740 px

Bij gebruik van een muis opent bij hoveren over een knop een kleine pop-up. Pas bij klikken wordt de link gevolgd. De pop-up kan hierbij gewoon in een span binnen de link zitten. Maar als je zo'n pop-up op een touchscreen gebruikt, kom je in de problemen.

Op iOS laten Safari en Chrome for iOS de pop-up even heel kort zien, waarna de link wordt gevolgd. Opera Mini laat de pop-up niet zien, maar volgt gelijk de link.

In Android 4.0.3 laten Chrome voor mobiel, Opera, Firefox en Android browser de pop-up heel kort zien, waarna de link wordt gevolgd.

In Android 2.3.6 tonen Opera, Opera Mini en Firefox de pop-up heel kort, waarna de link wordt gevolgd. Android browser volgt gelijk de link, zonder de pop-up te tonen.

In Windows 8 werkt het bij gebruik van een muis, maar bij gebruik van een touchscreen toont Internet Explorer 10 de pop-up heel kort. Firefox, Opera en Google Chrome volgen gelijk de link, zonder de pop-up te tonen.

Kortom: een pop-up binnen een span werkt niet. Logisch ook, want gewoon hoveren werkt niet op een touchscreen. Als je de link aanraakt, is het logisch dat die gelijk wordt gevolgd en niet eerst een pop-up opent.

Om een en ander werkend te krijgen op een touchscreen, moest er nogal wat aan de code worden gewijzigd.

De menubalk bestaat uit een gewone ongeordende lijst, met in elk lijst-item een link. Deze links worden echter aan de linkerkant buiten het scherm gepositioneerd. Pas bij hoveren over of aanraken van een van de knoppen in de menubalk, wordt de betreffende link op het scherm gezet.

In normale toestand, als er niet over de menubalk wordt gehoverd en deze niet wordt aangeraakt, staan er dus geen links binnen de menubalk. De tekst die bij de links hoort is wel zichtbaar, maar deze wordt gegenereerd met behulp van content bij de lijst-items. Voor het oog ziet het er dus uit, alsof er normale links binnen de menubalk staan, maar dat is niet zo.

De meeste screenreaders en dergelijke lezen gegenereerde tekst niet voor, wat hier een voordeel is, omdat dezelfde tekst ook nog 'ns binnen de 'echte' link staat.

Bij hoveren over of aanraken van een knop binnen de menubalk wordt de tekst binnen die knop onderstreept, waardoor deze er meer als een link uit gaat zien. Gelijktijdig verschijnen onder de menubalk links en rechts twee sluitknoppen. Deze zijn nodig voor iOS om de pop-up eventueel weer te kunnen sluiten.

Omdat er geen links binnen de menubalk staan, zijn onderstreping en sluitknoppen relatief simpel tevoorschijn te toveren. Want waar geen link staat, kan ook geen link voortijdig worden gevolgd. Hoveren over een <li> werkt op de normale manier, en met wat kleine aanpassingen heeft een aanraking van een lijst-item hetzelfde effect.

Tot nu toe staat er geen link binnen de menubalk. Maar op het moment dat een knop wordt aangeraakt, wordt de links buiten het scherm gepositioneerde link 0,24 seconde later binnen de bijbehorende knop geplaatst. Die 0,24 seconde bleek de tijd die minimaal nodig is om te voorkomen dat op een touchscreen de link wordt gevolgd. Omdat er bij aanraking gedurende 0,24 seconde helemaal geen link is, kan deze ook niet worden gevolgd.

De pop-up wordt met behulp van content vanuit de link gegenereerd. Als de link na 0,24 seconde op z'n plaats staat, kan de pop-up gewoon worden getoond. Omdat het om met behulp van content gegenereerde tekst gaat, wordt deze ook niet gelezen door de meeste screenreaders en dergelijke. Binnen deze tekst moet dus beslist geen belangrijke informatie worden neergezet.

Eventueel zou je de voor de pop-up gegeneerde tekst ook door gewone tekst binnen een span of zo kunnen vervangen, maar dan moet je die tekst wel op elke pagina in de html herhalen.

Als je een muis gebruikt, verschijnen bij hoveren over een knop sluitkruisjes en onderstreping. 0,24 seconde later staat de link op z'n plaats en kan worden geklikt om de link te volgen. Deze tijd is zo kort, dat het vrijwel onmogelijk is om binnen deze tijd te klikken. Zou dat wel gebeuren, dan wordt de link niet gevolgd, omdat deze stomweg nog niet aanwezig is. Als ik het heel geconcentreerd probeerde, lukte het mij een enkele keer om binnen die 0,24 seconde te klikken. Maar bij normaal gebruik zie ik dat niet zo snel gebeuren.

Op een touchscreen staat de link ook na 0,24 seconde op z'n plaats. Waarna de knop als een gewone link werkt. Bij een tweede aanraking wordt dus gewoon de link gevolgd.

Als mensen de Tab-toets gebruiken om van link naar link te gaan, wordt de link die focus heeft binnen de menubalk geplaatst. Om duidelijk te maken welke link focus heeft, krijgt deze een witte achtergrond. Omdat het wat verwarrend is als daar een vertraging van 0,24 seconde in zit, wordt bij gebruik van de Tab-toets de link zonder vertraging binnen de menubalk geplaatst.

Binnen elke link staat een span, die wordt gebruikt om de gekleurde streep onder de knoppen neer te zetten. Aan elke span wordt een achtergrondkleur gegeven. Deze achtergrondkleur is de gekleurde streep die je onder de knop ziet staan. Vanwege beveiliging kun je bij een bezochte link nog maar enkele dingen veranderen, waaronder de kleur van de achtergrond. Hierdoor kan de streep onder een bezochte link een andere kleur krijgen dan onder een nog niet bezochte.

Omdat de links normaal genomen aan de linkerkant buiten het scherm staan, worden de spans die voor de onderstreping zorgen normaal genomen ver naar rechts gepositioneerd, waardoor ze op de juiste plaats staan. Als de link in de menubalk wordt geplaatst, wordt de positionering van de onderstreping aangepast, waardoor deze ook nu weer op de juiste plaats staat.

Veel van de gebruikte selectors werken niet in Internet Explorer 8. Deze browser heeft daarom een hele serie eigen css. Als je even naar de lengte daarvan kijkt, begrijp je misschien waarom ik regelmatig in een woedekoliek over deze browser schiet. En Internet Explorer 6 en 7 waren nog véél erger... Wereldwijd moet het broddelwerk van Microsoft in de loop der jaren echt miljarden hebben gekost.

Los van wat hierboven staat, zijn er nog wat aanpassingen speciaal voor touchscreens nodig, omdat :hover anders niet of niet goed werkt. Deze staan verderop bij :hover, :focus en :active voor muis, toetsenbord, touchpad en touchscreen.

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.

Op webkit gebaseerde browsers, zoals Google Chrome en Safari: -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 worden linear-gradient, transition, animation, @keyframes en user-select gebruikt.

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 erbij. Deze wordt als laatste opgegeven. Bijvoorbeeld Safari herkent -webkit-linear-gradient. Zodra Safari linear-gradient gaat herkennen, zal dit -webkit-linear-gradient overrulen, omdat het er later in staat. Dat ze er beide in staan, is dus geen enkel probleem.

linear-gradient

Op dit moment moet je nog het volgende schrijven:

{-webkit-gradient(linear...); -webkit-linear-gradient: ...; linear-gradient: ...;}

In de toekomst kun je volstaan met:

{linear-gradient: ...;}

Je moet twee vormen voor -webkit- gebruiken, omdat de syntax voor linear-gradient ingrijpend is gewijzigd. Oudere versies van Safari en andere op webkit gebaseerde browsers gebruiken de eerste vorm van -webkit-.

Internet Explorer 10, Opera, Google Chrome en Firefox herkennen linear-gradient zonder voorvoegsel. Browsers die linear-gradient niet kennen, negeren deze eigenschap gewoon.

transition

Op dit moment moet je nog het volgende schrijven:

{-webkit-transition: ...; transition: ...;}

In de toekomst kun je volstaan met:

{transition: ...;}

Internet Explorer 10, Opera, Google Chrome en Firefox herkennen transition zonder voorvoegsel. Browsers die transition niet kennen, negeren deze eigenschap gewoon.

animation en @keyframes:

Deze twee eigenschappen worden alleen maar gebruikt om een bug in sommige oudere op webkit gebaseerde browsers te repareren. Daarom hoeft alleen maar op browsers gelet te worden, die op webkit zijn gebaseerd. In dit geval is daarom het volgende voldoende:

{-webkit-animation: ...;}

Hetzelfde geldt voor @keyframes:

@-webkit-keyframes {...}

In nieuwere browsers is deze bug niet meer aanwezig, dus de versie zonder voorvoegsel hoeft in dit geval helemaal niet gebruikt te worden.

(In het algemeen is het een bijzonder slechte gewoonte om van een eigenschap alleen één bepaalde versie te gebruiken. Dit gebeurt nogal eens voor iOS, waarmee Apple actief wordt geholpen om sites en dergelijke ontoegankelijk te maken voor andere browsers dan Safari. Ontwikkelaars die dit doen, werken mee aan de totstandkoming van eenzelfde wantoestand als in het verleden met het monopolie van Internet Explorer 6 heeft bestaan.

Maar in dit geval maakt het niet uit, omdat het alleen om een bug gaat. Andere browsers hebben deze css helemaal niet nodig.)

user-select:

Deze eigenschap wordt alleen maar gebruikt om een onhandigheid in Internet Explorer 10 op een touchscreen op te lossen. Daarom hoeft alleen maar op deze browser gelet te worden. In dit geval is daarom het volgende voldoende:

{-ms-user-select: ...;}

Omdat niet duidelijk is, of dit probleem zich ook in nieuwere versies blijft voordoen, laat ik de vorm zonder -ms- weg.

Semantische elementen en WAI-ARIA

Ik heb deze twee onderwerpen samengevoegd, omdat ze veel met elkaar te maken hebben.

Semantische elementen

De meeste elementen die in html worden gebruikt, hebben een semantische betekenis. Dat wil zeggen dat je aan de gebruikte tag al (enigszins) kunt zien, wat voor soort inhoud er in het element staat. In een <h1> staat een belangrijke kop. In een <h2> staat een iets minder belangrijke kop. In een <p> staat een alinea. In een <table> staat een tabel (en geen lay-out, als het goed is!). Enz.

Door het op de goede manier gebruiken van semantische elementen, kunnen zoekmachines, screenreaders, enz. de structuur van een pagina begrijpen. De spider van een zoekmachine is redelijk te vergelijken met een blinde. Het is dus ook in je eigen belang, om semantische elementen zo goed mogelijk te gebruiken. Een site die toegankelijk is voor mensen met een handicap, is in de regel ook goed te verwerken voor een zoekmachine en maakt dus een grotere kans gevonden en bezocht te worden.

Als het goed is, wordt het uiterlijk van de pagina bepaald met behulp van css. Het uiterlijk staat hierdoor (vrijwel) los van de semantische inhoud van de pagina. Met behulp van css kun je een <h1> heel klein weergeven en een <h6> heel groot, terwijl screenreaders, zoekmachines, en dergelijke nog steeds weten dat de <h1> een belangrijke kop is.

Slechts enkele elementen, zoals <div> en <span>, hebben geen semantische betekenis. Daardoor zijn deze elementen uitstekend geschikt, om met behulp van css het uiterlijk van de pagina aan te passen: de semantische betekenis verandert niet, maar het uiterlijk wel. Voor een screenreader of zoekmachine verandert er (vrijwel) niets, voor de gemiddelde bezoeker krijgt het door de css een heel ander uiterlijk.

(De derde laag, naast html voor de inhoud en css voor het uiterlijk, is JavaScript. Die zorgt voor de interactie tussen site en bezoeker. De min of meer strikte scheiding tussen css en html aan de ene kant en JavaScript aan de andere kant is met de komst van css3 en html5 veel vager geworden. Je kunt nu bijvoorbeeld ook met css dingen langzaam verplaatsen en met html deels de invoer in formulieren controleren. Maar op JavaScript ga ik op deze site verder niet echt in.)

Html5 heeft een aantal nieuwe elementen, die speciaal zijn bedoeld om de opbouw van een pagina aan te geven. In dit voorbeeld wordt hiervan <nav> gebruikt. <nav> gedraagt zich als een gewone <div>, maar dan een <div> met een semantische betekenis: het is bedoeld om een serie links voor navigatie in te zetten. Hierdoor kunnen screenreaders, zoekmachines, en dergelijke beter zien hoe de pagina is samengesteld.

Met behulp van dit soort nieuwe semantische elementen kan bijvoorbeeld een screenreader in één keer een hele header of <nav> passeren. Alleen hebben deze nieuwe elementen één probleem: ze hebben in de praktijk nog weinig nut, omdat screenreaders en dergelijke ze nog niet herkennen. En voordat alle screenreaders en dergelijke ze herkennen, zijn we jaren verder, want screenreaders zijn peperduur (behalve het uitstekende open source NVDA).

Maar er is niets op tegen, om ze nu vast te gaan gebruiken. Op het moment dat screenreaders, zoekmachines, enz. ze gaan herkennen, is de pagina dan al hierop voorbereid. Extra werk is het eigenlijk niet. Het intypen van <nav> gaat even snel als het intypen van <div>, en zeker sneller dan <div id="menu">, zoals nu vaak gebeurt.

WAI-ARIA

Los van semantische elementen is er nog een hulpmiddel om pagina's beter toegankelijk te maken voor screenreaders en dergelijke: WAI-ARIA-ondersteuning. WAI-ARIA staat voor Web Accessibility Initiative – Accessible Rich Internet Applications.

WAI-ARIA is een hele serie codes die bijvoorbeeld aangeven, welk deel van een pagina een menu, een header, een footer, enz. is. Daarnaast kan WAI-ARIA bij bijvoorbeeld een formulier aangeven of iets is aangevinkt of niet. Voor blinden zijn dit soort zaken uiterst belangrijk (en dus ook voor zoekmachines).

Screenreaders en dergelijke kunnen al jaren WAI-ARIA-codes herkennen. Dat is nog niet het geval met de nieuwe semantische elementen uit html5, en dat zal ook nog wel even duren, want screenreaders zijn peperduur (behalve het uitstekende NVDA).

Een van de groepen met codes binnen WAI-ARIA bestaat uit de zogenaamde landmarks. Daarmee worden belangrijke onderdelen van een pagina gemarkeerd. De landmarks komen gedeeltelijk overeen met de nieuwe semantische html5-elementen. Omdat screenreaders deze landmarks al wel herkennen, zet ik ze bij de corresponderende html-elementen. In de toekomst zijn ze niet meer nodig, maar dat zal nog wel even duren.

Een screenreader kan niet alleen van kop naar kop, maar ook van landmark naar landmark springen. Daardoor kan bijvoorbeeld het menu snel worden gevonden.

In dit voorbeeld gebruik ik de landmark navigation. Elke landmark wordt voorafgegaan door role=, op dezelfde manier als dat bij classes of id's gebeurt:

<nav role="navigation">

Omdat de checkbox voor een screenreader geen enkel nut heeft, is in de html aria-hidden="true" toegevoegd. Dit voorkomt dat de screenreader meldt dat er een checkbox is in te vullen. Om dezelfde reden is dit toegevoegd aan de bij de checkbox horende <label>.

Voor iOS zijn twee sluitkruisjes aangebracht. Het kruisje zelf is gewoon de letter 'X'. Voorlezen daarvan heeft ook geen enkel nut, daarom is ook bij de menubalk voor browservensters smaller dan 740 px aria-hidden="true" aangebracht.

Op de pagina met links vind je onder het kopje Toegankelijkheid → Forums, richtlijnen, links, artikelen en dergelijke meer info over WAI-ARIA.

:hover, :focus en :active voor muis, toetsenbord, touchpad en touchscreen

:hover

Omdat :hover mogelijk niet werkt, als css uitstaat, ontbreekt of onvolledig is geïmplementeerd, moet je nooit belangrijke informatie alleen met behulp van :hover tonen.

Je hovert over een element, als je met behulp van muis of touchpad de cursor boven dat element brengt. Hoveren kan over álle elementen. Het wordt veel gebruikt om iets van uiterlijk te laten veranderen, een pop-up te laten verschijnen, en dergelijke.

In dit voorbeeld wordt :hover gebruikt in browservensters breder dan 740 px om de teksten in de menubalk te onderstrepen, de links en de pop-ups binnen de menubalk te positioneren, de pop-up zichtbaar te maken en om de standaard-cursor weer te geven boven de link die bij de huidige pagina komt.

Zodra de cursor boven een van de knoppen komt, wordt de in die knop zittende tekst onderstreept, de bijbehorende link boven de knop geplaatst en de pop-up geopend. Op touchscreens gebeurt dit als de knop wordt aangeraakt. Bij gebrek aan een cursor wordt deze natuurlijk niet aangepast.

:focus

Omdat :focus mogelijk niet werkt, als css uitstaat, ontbreekt of onvolledig is geïmplementeerd, moet je nooit belangrijke informatie alleen met behulp van :focus tonen.

De meeste mensen gaan met een muis naar een link, invoerveld, en dergelijke. Waarna ze vervolgens klikken om de link te volgen, tekst in te voeren, of wat ze ook maar willen doen.

Er is echter 'n tweede manier om naar links, invoervelden, en dergelijke te gaan: met behulp van de Tab-toets (sommige browsers gebruiken andere toetsen, maar het principe is hetzelfde). Met behulp van de Tab-toets kun je naar links, invoervelden, en dergelijke 'springen'. Waar je staat, wordt door alle browsers aangegeven met een of ander kadertje. De link en dergelijke met het kadertje eromheen heeft focus. Dat wil zeggen dat je die link volgt, als je op de Enter-toets drukt, of dat je in dat veld tekst kunt gaan invoeren, enz.

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

Normaal genomen wordt ook een checkbox, zoals in dit voorbeeld wordt gebruikt, meegenomen in de tab-volgorde. Maar omdat de checkbox hier met display: none; is verborgen, gebeurt dat niet.

In dit voorbeeld wordt :focus gebruikt bij de links binnen het menu en de bijbehorende onderstreping, die aangeeft of een link al is bezocht of nog niet. Zodra een link focus heeft, wordt deze samen met de bijbehorende onderstreping binnen de menubalk gezet.

Omdat :focus hier voor touchscreens verder geen nut heeft, zijn daar geen aanpassingen voor nodig.

:active

Omdat :active mogelijk niet werkt, als css uitstaat, ontbreekt of onvolledig is geïmplementeerd, moet je nooit belangrijke informatie alleen met behulp van :active tonen.

:active wordt hier niet gebruikt. Het is het moment dat een element door de gebruiker wordt geactiveerd, bijvoorbeeld tijdens het indrukken van de muis boven een link.

Aanpassingen voor touchscreens

Het gebruik van :hover om een pop-up te laten verschijnen, levert op touchscreens nogal wat problemen op. Op internet zijn waanzinnig veel methodes te vinden, om dit voor elkaar te krijgen. De meeste blijken niet, slecht of alleen op één systeem te werken.

Ik ben bijvoorbeeld voor iOS een methode tegengekomen om een pop-up te sluiten door een plaatje (een <img>) aan te raken. Op dit moment werkt dat, maar het kan prima zijn dat dit helemaal niet de bedoeling is van Apple. Als dit in een komende versie van iOS wordt aangepast aan wat Apple eigenlijk wilde, werkt deze methode plotseling niet meer.

Dit is geen vage angst of zo, in het verleden is dit op grote schaal gebeurd. Mensen gebruikten fouten in Internet Explorer om een of andere bug of afwijking voor alleen (een bepaalde versie van) die browser te repareren. Als Microsoft de fout dan in een nieuwe versie had gerepareerd, donderde de hele lay-out grotelijks in elkaar.

De hier gebruikte methode is gebaseerd op de officiële documentatie van Microsoft en Apple. Hierdoor is er een grote kans dat deze methode ook blíjft werken.

Android schittert hier door afwezigheid, omdat ik geen officiële documentatie hierover heb kunnen vinden.

Windows 8

Binnen Windows 8 werkt het met muis, toetsenbord en/of touchpad op de gebruikelijke manier. Op een touchscreen werkt het in Opera, Firefox en Google Chrome ook op de gebruikelijke manier. In Internet Explorer 10 werkt het helemaal niet, omdat de links niet binnen de menubalk worden geplaatst.

Voor Internet Explorer 10 is een kleine aanpassing nodig. Om het in Internet Explorer 10 op een touchscreen goed te laten werken, moet overal in de html, waar :hover iets moet doen – in dit geval de links binnen de menubalk plaatsen – , aria-haspopup="true" worden toegevoegd.

Hierdoor wordt bij de eerste aanraking van een knop de link binnen de menubalk geplaatst (en de bijbehorende pop-up geopend). Als je het scherm buiten de menubalk aanraakt, wordt de pop-up weer gesloten. Maar als je de knop – die nu feitelijk een link is geworden – nogmaals aanraakt, wordt de link gevolgd.

In dit geval moeten alle <li>'s in de html de toevoeging aria-haspopup="true" krijgen, want bij aanraken van deze knoppen moet de link binnen de menubalk worden gezet.

De links zelf staan binnen een <li> en moeten in de html de toevoeging aria-haspopup="false" krijgen, omdat je anders, na het aanraken van de knop, ook nog twee keer de link moet aanraken. In totaal zou je dan drie keer de knop moeten aanraken, voordat de link wordt gevolgd.

Ik mag graag woest worden over Microsoft, maar in dit geval vind ik dit een heel elegante oplossing. Microsoft maakt gebruik van een al bestaande standaard: WAI-ARIA. Dit is volgens mij stukken beter dan de oplossingen van Apple en Android. Over die bestaande standaard WAI-ARIA kun je op de pagina met links onder het kopje Toegankelijkheid meer vinden.

iOS

Voor iOS zijn in dit geval maar een paar kleine aanpassingen nodig. Een <li> reageert normaal genomen niet op een aanraking. Door het toevoegen van onclick="void(0)" bij elke <li>, reageert de <li> ook op iOS op een aanraking.

Als de link binnen de menubalk staat en de bijbehorende pop-up is geopend, kan deze niet meer worden gesloten op iOS. Daarvoor is een ander element nodig dat op aanraking reageert. Dit is de functie van div#sluitbalk. Binnen deze div staan twee sluitkruisjes span.sluiten, die beide ook een onclick="void(0)" hebben gekregen. Hierdoor reageren deze op aanraken: door het aanraken van een sluitkruisje, sluit de pop-up (en wordt de link weer buiten het scherm gepositioneerd, maar dat zie je niet).

Android

In Android zijn verder geen speciale aanpassingen nodig. Dat wil zeggen: de hele code is eigenlijk één grote aanpassing. Alleen voor Android is het nodig de link helemaal buiten de menubalk te plaatsen. iOS en Windows 8 kun je ook laten werken met aria-haspopup en onclick, maar dat geldt niet voor Android.

De enige manier die ik heb gevonden om dit, zonder JavaScript, werkend te krijgen in Android, is het buiten de menubalk plaatsen van de links.

Beschrijving van code en css

De code die te maken heeft met de basis van dit voorbeeld is onderstippeld blauw. 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 ontbreekt bijvoorbeeld de navigatie voor de site. 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, kun je bovenaan de pagina de hele handel 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.

<meta charset="utf-8">

Zorgt dat de browser letters met accenten en dergelijke goed kan weergeven.

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.

In html5 hoeft deze regel niet langer te zijn, dan wat hier staat.

<meta name="viewport" content="width=device-width, initial-scale=1">

Mobiele apparaten variëren enorm in breedte. En dat is een probleem. Sites waren, in ieder geval tot voor kort, gemaakt voor desktopbrowsers. En die hebben, in vergelijking met bijvoorbeeld een smartphone, heel brede browservensters. Hoe moet je op 'n smartphone een pagina weergeven die is gemaakt voor de breedte van een desktop? Je kunt natuurlijk wachten tot álle sites zijn omgebouwd voor smartphones, tablets, enz., maar dan moet je waarschijnlijk heel erg lang wachten.

Mobiele browsers gokken erop dat een pagina een bepaalde breedte heeft. Safari voor mobiel bijvoorbeeld gaat ervan uit dat een pagina 980 px breed is. De pagina wordt vervolgens zoveel versmald dat hij binnen het venster van het apparaat past. Op een iPhone wordt de pagina dus veel smaller dan op een iPad. Vervolgens kan de gebruiker inzoomen op het deel van de pagina dat hij of zij wil zien.

Dit betekent ook dat bij het openen van de pagina de tekst meestal heel erg klein wordt weergegeven. (Meestal, want niet alle browsers en apparaten doen het op dezelfde manier.) Niet erg fraai, maar bedenk maar 'ns 'n betere oplossing voor bestaande sites.

Nieuwe sites of pagina's kunnen echter wel rekening houden met de veel kleinere vensters van mobiele apparaten. Dit menu bijvoorbeeld past zich aan de breedte van het venster aan, ook bij heel smalle vensters. Maar die stomme mobiele browser weet dat niet, dus die gaat ervan uit dat ook het heel smalle menu 980 px breed is, en verkleint dat dan. Dat is ongeveer even behulpzaam als de gedienstige kelner die behulpzaam de stoel naar achteren trekt, net als jij wilt gaan zitten.

Om de door de browser aangeboden hulp vriendelijk maar beslist te weigeren, wordt deze tag gebruikt. Hiermee geef je aan dat de pagina is geoptimaliseerd voor mobiele apparaten.

Een iPad in portretstand bijvoorbeeld is 768 px breed. De kreet width=device-width zegt tegen de mobiele browser dat de breedte van de weer te geven pagina gelijk is aan de breedte van het apparaat. Voor een iPad in portretstand dus 768 px. En dat klopt, want de weer te geven pagina past zich automatisch aan de breedte van het apparaat aan, omdat de pagina altijd 100% breed is. Als het apparaat 300 px breed is, is de pagina ook 300 px breed, maar nog altijd 100%.

Simpeler gezegd: je zegt tegen het mobiele apparaat dat de pagina geen vaste breedte heeft, en dat het dus niet nodig is om de weergave aan te passen.

Steeds meer mobiele apparaten krijgen een hogere resolutiedichtheid: er staan meer pixels in een inch dan bij een monitor voor de desktop het geval is. Als een lijn 4 px breed is, en de pixels staan vier keer zo dicht op elkaar als op de desktop, zou de lijn maar 1 px breed zijn op een mobiel apparaat. Het is wel een supermooie en strakke lijn, omdat je met vier dicht bij elkaar staande pixels fantastisch scherp kunt weergeven. Alleen is de lijn helaas nauwelijks te zien, omdat hij in al z'n pracht maar 1 px breed is.

Ook niet echt geweldig. Daarom geven ook deze apparaten de breedte weer, alsof de resolutie een standaarddichtheid heeft. Een retina-scherm (een scherm met een hoge resolutiedichtheid) jokt een beetje. Ook een venster van 2048 of 4096 px breed beweert 1024 px breed te zijn. Hierdoor ziet een lijn van 4 px breed er ook op zo'n scherm als 4 px breed uit, en niet als 1 of 2 px breed.

Die hoge resolutiedichtheid heeft wel zin, maar dan op een andere manier. Letters bijvoorbeeld worden al jaren getekend aan de hand van wiskundige formules, het zijn allang geen statische afbeeldingen meer. Die formules kunnen prima met die hoge resolutiedichtheid uit de voeten: een ronding in een letter is in een hogere resolutie veel fijner dan in een lagere resolutie. Ook voor hoge kwaliteit afbeeldingen is een hoge resolutiedichtheid zinvol. Het enige waar het niet zinvol is, is bij het aangeven van een maat. Een lijn van 4 px breed moet 4 px breed zijn, en niet 1 px breed in superkwaliteit.

Er staat nog een tweede deel in de tag: initial-scale=1. Sommige mobiele apparaten zoomen een pagina gelijk in of uit. Ook weer in een poging behulpzaam te zijn. Ook dat is hier niet nodig, want de pagina past zich aan het apparaat aan. Er is ook een instructie om zoomen helemaal onmogelijk te maken, maar die gebruik ik niet. De bezoeker kan zelf nog gewoon zoomen, wat belangrijk is voor mensen die wat slechter zien.

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

<!-- Instellingen voor Internet Explorer --> <!--[if IE]> <link rel="stylesheet" href="../../css/naam-van-ie-stylesheet.css"> <![endif]-->

Dit stukje code 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 regels aanpast voor je eigen bestand. De hele style, die onder deze regels in de <head> staat, wordt dan in het externe bestand geplaatst, waar 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 dat in dit voorbeeld tussen <style> en </style> staat (zonder deze begin- en eindregel).

De bovenste regel is voor de algemene stylesheet, geldig voor alle browsers. Dit is gewoon 'n link die naar 'n bestand elders verwijst, waar de css in staat. Op de plaats van "../../css/naam-van-stylesheet.css" moet je pad naar en naam van jouw stylesheet invullen.

Het eigenaardige stukje code daaronder heet een 'conditional comment' en wordt door alle browsers gezien als commentaar, omdat het tussen <!-- en --> staat. Maar Internet Explorer herkent het, door de extra toevoegingen, als speciaal voor Internet Explorer bedoeld en zal het dus uitvoeren. Het is veiliger dan een zogenaamde 'hack', waarbij vaak gebruik wordt gemaakt van 'n fout (bug) in de browser. Dit is opzettelijk aangebracht door Microsoft en zal dus blijven bestaan, terwijl 'n bug gerepareerd kan worden. Op deze manier kun je 'n stylesheet alleen voor Internet Explorer opnemen.

Dit stukje geldt voor alle versies van Internet Explorer, maar je kunt het ook per versie aangeven. Met ingang van Internet Explorer 10 werken conditional comments niet meer.

De link verwijst naar een aparte stylesheet voor Internet Explorer, waarin je css speciaal voor die browser zet. Op de plaats van "../../naam‑van‑ie‑stylesheet.css" moet je pad naar en naam van je stylesheet voor Internet Explorer invullen.

De link naar het aparte stylesheet voor Internet Explorer moet ná de link naar het algemene stylesheet komen, omdat de opdrachten voor Internet Explorer die uit de algemene stylesheet dan in principe overrulen.

<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;
	}

css voor alle breedtes

body

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

background: #ff9;

Achtergrondkleur.

color: black;

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

Hoewel dit de standaardkleur is, geef ik de kleur toch op. Hierboven heb ik een achtergrondkleur opgegeven. 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 in een eigen stylesheet, is er nog niets aan de hand, want dan veranderen achtergrond- en voorgrondkleur geen van beide.

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

margin: 0; padding: 0;

Verschillende browsers hebben verschillende standaardinstellingen hiervoor. Door ze gewoon op 0 te zetten, zijn ze overal hetzelfde.

#checkbox-voor-smal

Het element met id="checkbox-voor-smal". Dit is een <input>-element type checkbox. Als de checkbox is aangevinkt, is het menu zichtbaar. Als de checkbox is uitgevinkt, is het menu niet zichtbaar.

display: none;

Verberg de checkbox.

Verderop in de html staat label#toon-menu, dat met for aan deze checkbox is gekoppeld. Als je op dit <label> klikt of dit aanraakt, heeft dat hetzelfde effect, als wanneer je rechtstreeks deze checkbox aanklikt of aanraakt. Alleen kun je het <label> opmaken en tekst geven. Die tekst kun je wijzigen, afhankelijk van of de checkbox wel of niet is aangevinkt.

#menu

Het element met id="menu". Dit is de <nav> waarbinnen het hele menu staat.

width: 0; overflow: hidden;

Breedte van 0 geven. Dat is 'n beetje smal. Feitelijk zo smal, dat er helemaal geen breedte is. En dat is precies de bedoeling.

Normaal genomen zou je het menu toch zien, omdat overflow standaard op visible staat. Wat niet past binnen de breedte of hoogte, zie je toch. Dat is normaal genomen ook, wat je wilt. Mogelijk wordt de lay-out verstoord, maar je kunt in ieder geval alles zien.

In dit geval is dat niet de bedoeling. hidden zorgt ervoor dat wat niet past, ook echt niet wordt getoond. Bij een breedte van 0 zie je dus gewoon niets.

Bij #checkbox-voor-smal:checked + #menu wordt het menu zichtbaar gemaakt, door er een breedte aan te geven.

position: absolute;

Om het menu op een bepaalde plaats neer te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een relatieve, absolute of fixed positie heeft. Als die er niet is, zoals hier het geval is, wordt gepositioneerd ten opzichte van het venster van de browser.

top: 40px;

40 px vanaf de bovenkant neerzetten. De menubalk aan de bovenkant krijgt bij #menubalk-voor-smal een hoogte van 40 px. Het menu komt hier dus precies onder te staan.

bottom: 0;

In principe is dit menu bedoeld voor kleinere touchscreens. Grotere schermen krijgen verderop een heel ander menu. Als geen bottom wordt opgegeven, wordt het menu niet hoger dan nodig is, om de tekst erin weer te kunnen geven.

Dat levert knoppen op die prima geschikt zijn voor babyvingertjes, maar waar 'n bootwerker niet echt gelukkig van wordt. Op deze manier loopt het menu door tot de onderkant van het browservenster. Bij #menu li wordt aan de knoppen van het menu een hoogte in procenten gegeven, zodat de knoppen altijd groot genoeg en netjes verdeeld zijn.

-webkit-transition: 0.5s; transition: 0.5s;

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

Hierboven heb ik breedte van 0 opgegeven. Als ik nu bij :hover, :focus, :checked, en dergelijke een andere breedte opgeef, zorgt transition ervoor dat die breedte niet in één keer wordt veranderd bij hoveren en dergelijke, maar langzaamaan. Als de breedte van 0 wordt veranderd naar 90%, vindt die verandering geleidelijk aan plaats: geleidelijk van 0 naar 90%.

Internet Explorer 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.5s. Als er maar één waarde wordt opgegeven, bepaalt die over hoeveel tijd de verandering wordt uitgesmeerd. Dat is hier vrij kort: 'n halve seconde. Een eventuele tweede waarde, die hier ontbreekt, geeft een eventueel uitstel aan het begin van de verandering 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,5 seconde duurt, is het verschil nauwelijks te zien, dus dat wordt hier niet gebruikt.

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 :checked, 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, :checked, 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.

Als alle eigenschappen mogen worden vertraagd door transition, is er geen enkel risico voor de toekomst. Dat is hier het geval. Verderop bij #checkbox-voor-smal:checked + #menu verander ik de breedte. Verder verandert er niets. In dit geval mag dus alles vertraagd worden veranderd. Als dat niet zo zou zijn, zou ik moeten opgeven, voor welke eigenschappen transition geldt.

Als er bij #checkbox-voor-smal:checked + #menu eigenschappen staan die niet mogen worden vertraagd, zou ik altijd opgeven, voor welke eigenschappen transition geldt. Ook als transition nu nog niet werkt voor die andere eigenschappen, want mogelijk verandert dat in de toekomst.

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

transition: width 0.5s;

Nu geldt transition alleen voor width, wat er in de toekomst mogelijk ook verandert. Maar hier is dat dus niet nodig, omdat bij #checkbox-voor-smal:checked + #menu alleen width wordt gebruikt.

#menu ul

Alle ongeordende lijsten binnen een element met id="menu". Er is hier maar een <ul>, waarbinnen het menu staat.

height: 100%;

Een hoogte in procenten is altijd ten opzichte van de ouder. Dat is hier #menu, dat bij #menu op 40 vanaf de bovenkant tot onderaan het browservenster is neergezet. De <ul> staat dus ook 40 px vanaf de bovenkant tot onderaan het venster.

list-style-type: none;

De bolletjes en dergelijke die je automatisch ziet bij een <ul>, zijn hier niet welkom.

margin: 0; padding: 0;

De standaardwaarden hiervan verschillen bij verschillende browsers. Door ze op 0 te zetten, zijn ze overal hetzelfde.

#menu li

Alle lijst-items binnen het element met id="menu". Dit zijn de <li>'s waarbinnen de links van het menu zitten.

background: white;

Witte achtergrond. Hieronder wordt als achtergrond een gradiënt opgegeven. Maar oudere of simpele browsers die geen gradiënten kennen, negeren dit. Voor deze browsers wordt een witte achtergrondkleur opgegeven. Browsers die gradiënten wel kennen, gebruiken de regel hieronder, omdat deze later in de css staat en dus deze regel overrulet.

background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fff), color-stop(100%, #bbb)); background: -webkit-linear-gradient(top, #fff 0%, #bbb 100%); background: linear-gradient(to bottom, #fff 0%, #bbb 100%);

Het is wat lastig te zien, maar hier staat eigenlijk drie keer hetzelfde: background: linear-gradient (to bottom, #fff 0%, #bbb 100%);. Waarom het er drie keer staat, staat bij De voorvoegsels -moz-, -ms-, -o- en -webkit-. Hieronder wordt alleen de derde vorm uitgelegd, want dat is de vorm volgens de uiteindelijke standaard.

Je kunt een gradiënt zelf uitvogelen, maar makkelijker is het om gebruik te maken van een gradiënt-editor. Ik heb gebruik gemaakt van de gradiënt-editor op colorzilla.com. Deze levert ook gelijk de oudere vormen, zodat je je daar zelf niet in hoeft te verdiepen. Hier heb ik dat niet gedaan, maar je kunt zelfs code voor oudere versies van Internet Explorer laten maken. (Nachtmerrie-code die gebruik maakt van een eigen techniek van Microsoft: filters.)

linear-gradient valt in een aantal delen uiteen.

to bottom: de kant waar de gradiënt naartoe gaat. Omdat alleen de onderkant is opgegeven, loopt de gradiënt loodrecht van boven naar onder.

Na de richting staan twee keer twee waarden, gescheiden door een komma. De eerste waarde is steeds de kleur, de tweede de plaats waar die kleur staat.

#fff 0%: de kleur #fff (wit) op 0% vanaf de bovenkant neerzetten (dat is helemaal bovenaan).

#bbb 100%: de kleur #bbb (lichtgrijs) op 100% vanaf de bovenkant neerzetten (dat is helemaal onderaan).

Er zijn twee plaatsen opgegeven die een bepaalde kleur moeten krijgen: boven- en onderaan. De overgang tussen die kleuren verloopt geleidelijk, dat regelt de browser verder. Dit is een hele simpele gradiënt, maar je kunt ook tig kleuren op tig plaatsen aangeven. En ook nog in allerlei richtingen.

width: 35%;

Een breedte in procenten wordt altijd genomen ten opzichte van de ouder. Dat is hier #menu. Die breedte ligt hier wat ingewikkeld, omdat de breedte van #menu niet altijd hetzelfde is. Bij #menu is een breedte van 0 gegeven. Bij #checkbox-voor-smal:checked + #menu is de breedte 90%. Deze verandering in breedte duurt 0,5 seconden, waardoor het menu vanaf de linkerkant naar binnen lijkt te schuiven.

Er moeten twee <li>'s naast elkaar komen te staan. Dus zou je hier 50% breedte op moeten geven, zou je denken. Want dan vult elke <li> steeds de helft van de breedte van #menu, hoe breed die ook is.

Zo simpel blijkt het niet te werken bij gebruik van transition om de breedte geleidelijk te veranderen. Als je hier gewoon 50% invult, komt er tijdens het openen maar één <li> op elke regel te staan. Als het menu open is, verspringt het dan naar twee <li>'s naast elkaar. Als je een hele kleine breedte aan de <li>'s geeft, komen er tijdens het openen meer dan twee <li>'s naast elkaar te staan en krijg je 'n hele serie verspringing tijdens het openen.

Een breedte van 35% blijkt beide vormen van verspringen te voorkomen. Bij #checkbox-voor-smal:checked + #menu li wordt de uiteindelijke breedte dan 49,5% (geen 50%, omdat er ook nog 'n border bij komt).

height: 20%;

Een hoogte in procenten is altijd ten opzichte van de ouder. Dat is hier de <ul>, die bij #menu ul op 40px van de bovenkant tot aan de onderkant van het browservenster is neergezet. Elke <li> vult dus een vijfde van deze hoogte.

(Omdat er maar vier <li>'s boven elkaar staan, zou je ook 25% kunnen nemen, maar dit is groot genoeg voor vingers en ik vind het mooier.)

max-height: 50px;

In iets hogere vensters worden de knoppen wel érg hoog. Daarom wordt er een maximumhoogte aan gegeven. Dit geeft bovendien de mogelijkheid om de tekst op de knoppen verticaal te centreren. Daarvoor wordt hieronder bij #menu a een regelhoogte opgegeven.

overflow: hidden;

Binnen elke <li> staat een <a> met tekst. Als de tekst niet binnen de <li> past, omdat deze tijdens het openen nog te smal is, wordt de tekst toch getoond. Normaal genomen is dat ook wat je wilt. Mogelijk wordt de lay-out wat verstoord, maar in ieder geval kun je alles zien.

Hier is dat echter lelijk, omdat de tekst hier tijdens het openen korte tijd buiten de <li> staat. En uiteindelijk is de tekst gewoon zichtbaar, als het menu is geopend. Daarom wordt de tekst die niet binnen de <li> past verborgen.

float: left;

Een <li> is een blok-element. Dat betekent onder andere dat elke <li> op een nieuwe regel komt te staan. Door ze naar links te floaten, komen er zoveel mogelijk op dezelfde regel te staan. Omdat elke <li> bij #checkbox-voor-smal:checked + #menu li een breedte van 49,5% krijgt, komen er twee naast elkaar te staan.

text-align: center;

Tekst horizontaal centreren.

border: black solid;

Als de browser geen gradiënten kent, is de achtergrond effen wit. Daardoor is de grens tussen de knoppen, en dus tussen de daarin zittende links, niet te zien. Waardoor je niet weet, waar je de knoppen precies moet aanraken of -klikken. Door een randje tussen de knoppen aan te brengen, zie je de grens van de knoppen.

Hier worden alleen kleur en stijl opgegeven, gelijk hieronder wordt de dikte opgegeven.

border-width: 1px 0 0 1px;

Hier gelijk boven zijn kleur en stijl opgegeven. Boven en links een dikte van 1 px, rechts en onder geen border.

Het apart opgeven van de dikte voorkomt hier twee volledige regels voor border-top en border-left. Hierdoor wordt wat css uitgespaard.

-webkit-transition: 0.5s; transition: 0.5s;

Bij #checkbox-voor-smal:checked + #menu li wordt, als de checkbox is aangevinkt, de breedte van 35% naar 49,5% veranderd. Deze regel zorgt ervoor dat de verandering niet in één keer, maar geleidelijk gedurende 'n halve seconde plaatsvindt. De verandering van breedte en het gebruik van transition is nodig, om te zorgen dat ook tijdens het openen en sluiten van het menu altijd twee <li>'s naast elkaar staan.

De uitleg is precies hetzelfde als bij -webkit-transition: 0.5s; transition: 0.5s;, alleen wordt de breedte hier niet naar 50%, maar naar 49,5% veranderd.

#menu a

Alle links binnen het element met id="menu". Dit zijn de links binnen het menu.

color: black;

Voorgrondkleur, waaronder de kleur van de tekst, zwart. Normaal genomen krijgt tekst binnen een link een afwijkende kleur. Dat vind ik hier niet mooi.

display: block;

Van zichzelf is een <a> een inline-element. Door er 'n blok-element van te maken, kunnen eigenschappen als hoogte worden gebruikt.

height: 100%;

Een hoogte in procenten wordt altijd ten opzichte van de ouder genomen. Dat is hier de <li>, waar de link in zit. De <a> wordt hier dus even hoog gemaakt als de <li>.

Normaal genomen is alleen de tekst binnen link gevoelig voor klikken of aanraken. Door de link even hoog te maken als de <li>, wordt de hele hoogte van de <li> gevoelig voor aanraken of klikken. Dit is ook wat mensen verwachten, als ze zo'n menubalk met knoppen zien.

Omdat de <a> hierboven in een blok-element is veranderd, is het opgeven van een breedte niet nodig. Een blok-element wordt normaal genomen automatisch even breed als z'n ouder. Hier wordt de <a> even breed als de <li>.

line-height: 42px;

Tekst wordt automatisch in het midden van de regelhoogte gezet. Bij #menu li is aan de <li>'s een hoogte van 50 px gegeven. Als ik de regelhoogte van deze link ook 50 px maak, staat de tekst dus automatisch verticaal gecentreerd.

Maar hieronder wordt aan de bovenkant een padding van 4 px gegeven. Als de tekst in het midden moet komen, moet ik aan de onderkant ook 4 px vrij houden. Om de tekst verticaal te centreren, moet de regelhoogte dus 50 px – 2 x 4 px = 42 px worden.

text-decoration: none;

Normaal genomen worden links onderstreept. Dat is hier overbodig, omdat zo ook wel duidelijk is dat het om 'n menu met links gaat. Het is hier ook niet mooi.

padding-top: 4px;

Opera Mini negeert regelhoogte. Nu heeft ook deze browser 'n kleine afstand tussen de tekst van de link en de bovenkant van de knop.

#menubalk-voor-smal

Het element met id="menubalk-voor-smal". Dit is de div, waarbinnen de tekst 'Menu open' of 'Menu dicht' staat.

background: white;

Witte achtergrond. Hieronder wordt als achtergrond een gradiënt opgegeven. Maar oudere of simpele browsers die geen gradiënten kennen, negeren dit. Voor deze browsers wordt een witte achtergrondkleur opgegeven. Browsers die gradiënten wel kennen, gebruiken de regel hieronder, omdat deze later in de css staat en dus deze regel overrulet.

background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fff), color-stop(100%, #bbb)); background: -webkit-linear-gradient(top, #fff 0%, #bbb 100%); background: linear-gradient(to bottom, #fff 0%, #bbb 100%);

Het is wat lastig te zien, maar hier staat eigenlijk drie keer hetzelfde: background: linear-gradient (to bottom, #fff 0%, #bbb 100%). Waarom het er drie keer staat, staat bij De voorvoegsels -moz-, -ms-, -o- en -webkit-. Hieronder wordt alleen de derde vorm uitgelegd, want dat is de vorm volgens de uiteindelijke standaard.

Je kunt een gradiënt zelf uitvogelen, maar makkelijker is het om gebruik te maken van een gradiënt-editor. Ik heb gebruik gemaakt van de gradiënt-editor op colorzilla.com. Deze levert ook gelijk de oudere vormen, zodat je je daar zelf niet in hoeft te verdiepen. Hier heb ik dat niet gedaan, maar je kunt zelfs code voor oudere versies van Internet Explorer laten maken. (Nachtmerrie-code die gebruik maakt van een eigen techniek van Microsoft: filters.)

linear-gradient valt in een aantal delen uiteen.

to bottom: de kant waar de gradiënt naartoe gaat. Omdat alleen de onderkant is opgegeven, loopt de gradiënt loodrecht van boven naar onder.

Na de richting staan twee keer twee waarden, gescheiden door een komma. De eerste waarde is steeds de kleur, de tweede de plaats waar die kleur staat.

#fff 0%: de kleur #fff (wit) op 0% vanaf de bovenkant neerzetten (dat is helemaal bovenaan).

#bbb 100%: de kleur #bbb (lichtgrijs) op 100% vanaf de bovenkant neerzetten (dat is helemaal onderaan).

Er zijn twee plaatsen opgegeven die een bepaalde kleur moeten krijgen: boven- en onderaan. De overgang tussen die kleuren verloopt geleidelijk, dat regelt de browser verder. Dit is een hele simpele gradiënt, maar je kunt ook tig kleuren op tig plaatsen aangeven. En ook nog in allerlei richtingen.

color: black;

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

Hoewel dit de standaardkleur is, geef ik de kleur toch op. Hierboven heb ik een achtergrondkleur opgegeven. 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 in een eigen stylesheet, is er nog niets aan de hand, want dan veranderen achtergrond- en voorgrondkleur geen van beide.

width: 100%;

Een breedte in procenten wordt altijd genomen ten opzichte van de ouder. Dat is hier <body>, die even breed is als het venster van de browser. (Op smallere schermen zoals die van mobieltjes is dat venster even breed als het scherm.)

Deze <div>, en dus de daarin zittende menubalk, is dus even breed als het venster van de browser.

height: 40px;

Hoogte. Ik gebruik als eenheid px en geen em. In het algemeen is het beter om voor mobiele apparaten relatieve eenheden zoals em te gebruiken. Als ik hier echter px gebruik, kan ik het hieronder staande menu exact op deze menubalk laten aansluiten. Met een relatieve eenheid als em is dat veel lastiger.

#toon-menu

Het element met id="toon-menu". Dit is het <label> dat bij de checkbox hoort. Het staat in browservensters smaller dan 740 px bovenaan de pagina.

-webkit-animation: bugfix infinite 1s;

Oudere versies van Android hebben een bug, waardoor een pseudo-class die wordt gevolgd door de selector ~ ('general sibling') niet verandert. Dit gebeurt hier bij #checkbox-voor-smal:checked ~ #menubalk-voor-smal #toon-menu:after, waar de pseudo-class :checked wordt gevolgd door een ~. Hierdoor verandert 'open' niet in 'dicht', als het menu opent.

font-size: 1.4em;

Iets grotere letter.

line-height: 40px;

Regelhoogte. Bij #menubalk-voor-smal heeft de ouder van #toon-menu een hoogte van 40 px gekregen. Tekst wordt automatisch halverwege de regelhoogte gezet. Door de regelhoogte even hoog te maken als de hoogte van #menubalk-voor-smal, wordt de tekst automatisch verticaal gecentreerd in de menubalk.

(<label> is een inline-element. De regelhoogte van een inline-element kan nooit kleiner zijn dan de regelhoogte van het blok-element, waar het in staat. Wel groter. Hier heeft het #menubalk-voor-smal, het blok-element dat de ouder van #toon-menu is, geen regelhoogte, dus hier speelt dat probleem niet.)

text-decoration: underline;

Tekst onderstrepen, zodat duidelijk is dat dit (een soort) link is.

padding-left: 10px;

Kleine afstand tussen linkerkant van de tekst en zijkant van de menubalk.

@-webkit-keyframes bugfix

from {padding-left: 10px;} to {padding-left: 10px;}}

Bij #toon-menu is een animatie toegevoegd om een bug in oudere versies van Android op te lossen. Hier wordt de animatie opgegeven. Als je nou denkt dat hier niets wordt uitgevoerd, omdat de padding links van 10 px in een padding links van 10 px wordt veranderd, dan heb je helemaal gelijk.

Toch neutraliseert deze flauwekul-animatie de bug in Android.

#toon-menu:after

Doe iets achter het element met id="toon-menu". Dit is de <label>, waarbinnen 'Menu ' staat. Dit <label> hoort bij de checkbox, die het tonen en verbergen van het menu regelt.

content: "open";

Zet 'open' achter label#toon-menu. In de html is opgegeven dat in <label> altijd het woordje 'Menu ' (met spatie erachter) moet staan. Door hierachter 'open' toe te voegen, staat er nu 'Menu open'. Omdat het hele <label> in de menubalk bovenaan de pagina staat, staat er in die menubalk nu 'Menu open'.

Hier gelijk onder wordt het woordje 'open' in 'dicht' veranderd, zodra de checkbox is aangevinkt.

Omdat oudere browsers mogelijk niet goed met content uit de voeten kunnen, moet je nooit belangrijke informatie via content genereren.

#checkbox-voor-smal:checked ~ #menubalk-voor-smal #toon-menu:after

Een wat ingewikkeld ogende selector, maar als je hem in stukjes hakt, valt het hopelijk mee.

#checkbox-voor-smal: het element met id="checkbox-voor-smal". Dit is een <input>-element type checkbox.

:checked: maar alleen als de checkbox is aangevinkt.

~: de 'general sibling' selector. Het hierop volgende element moet dezelfde ouder hebben als het voorafgaande element. De structuur van de html is, vereenvoudigd weergegeven, als volgt:

<body> <input id="checkbox-voor-smal"> <nav id="menu"> (...) menu (...) </nav> <div id="sluitbalk"> (...) sluitkruisjes (...) </div> <div id="menubalk-voor-smal"> <label="toon-menu" for="checkbox-voor-smal">menu </label> </div> <div id="content"> (...) </div> </body>

Het op ~ volgende element moet dezelfde ouder hebben als het ervoor staande #checkbox-voor-smal. Aan deze eis voldoen hier alleen nav#menu, div#sluitbalk, div#menubalk-voor-smal en div#content. Het moet dus één van deze elementen zijn. Maar anders dan wanneer je de + gebruikt, hoeft het tweede element niet direct op het eerste te volgen. Als het maar dezelfde ouder heeft.

#menubalk-voor-smal: het op de ~ volgende element moet een id="menubalk-voor-smal hebben. Dat is er maar eentje: de menubalk die bovenaan de pagina staat (en die verderop wordt verborgen in browservensters breder dan 740 px).

De selector #checkbox-voor-smal + nav#menu + div#sluitbalk + div#menubalk-voor-smal zou precies hetzelfde werken in dit geval, maar de ~ maakt het 'n stuk korter (en overzichtelijker).

#toon-menu: het element met id="toon-menu". Omdat het gelijk na #menubalk-voor-smal staat, met alleen 'n spatie ertussen, moet het binnen #menubalk-voor-smal liggen. Dit is het <label>, waarin 'Menu open' of 'Menu dicht' staat.

:after: dit pseudo-element maakt het, in combinatie met content hieronder, mogelijk tekst achter het <label> te plaatsen.

De hele selector nog 'ns in normale mensentaal:

Doe iets achter label#toon-menu, dat binnen div#menubalk-voor-smal ligt. #menubalk-voor-smal moet dezelfde ouder hebben als input#checkbox-voor-smal. En er mag alleen iets gedaan worden, als #checkbox-voor-smal is aangevinkt.

Deze constructie maakt het mogelijk om een verandering aan te brengen in 'n element dat 'n heel eind onder de checkbox staat, afhankelijk van of de checkbox is aangevinkt of niet. Waarbij het geen enkel verschil maakt dat de checkbox zelf bij #checkbox-voor-smal is verborgen.

content: "dicht";

In label#toon-menu staat altijd het woordje 'Menu ' (met 'n spatie erachter). Dat is gewoon in de html opgegeven. Als de checkbox is aangevinkt, komt daar het woordje 'dicht' achter te staan.

Bij #toon-menu:after wordt opgegeven dat normaal genomen 'open' achter 'Menu ' staat. Maar zodra de checkbox is aangevinkt, wordt dit vervangen door 'dicht'.

Bij #checkbox-voor-smal:checked + #menu wordt het menu geopend, als de checkbox is aangevinkt. Als de checkbox niet is aangevinkt, zie je het menu niet. Normaal genomen, als je het menu niet ziet, staat er dus 'Menu open' in label#toon-menu. Als de checkbox is aangevinkt en het menu zichtbaar is, staat er 'Menu dicht'. Omdat het hele <label> in de menubalk bovenaan de pagina staat, staat deze tekst ook daar.

Omdat oudere browsers mogelijk niet goed met content uit de voeten kunnen, moet je nooit belangrijke informatie via content genereren.

#sluitbalk

Het element met id="sluitbalk". Dit is op iOS nodig om de pop-ups weer te kunnen sluiten.

display: none;

Dit element is alleen nodig in browservensters breder dan 740 px, dus kan het hier worden verborgen.

#checkbox-voor-smal:checked + #menu

Doe iets met het element met id="menu" dat gelijk volgt op het element met id="checkbox-voor-smal", maar alleen als #checkbox-voor-smal is aangevinkt.

Binnen #menu zit het hele menu.

width: 90%;

Een breedte in procenten wordt altijd genomen ten opzichte van de ouder. Dat is hier <body>, dat even breed is als het venster van de browser. (Op kleine apparaten als mobieltjes is dat gelijk de breedte van het scherm.) #menu krijgt hier een breedte van 90% van het venster.

Bij #menu is de hele opmaak van het menu al opgegeven. Er is daar een breedte van 0 aan het menu gegeven, waardoor het onzichtbaar is. Door een breedte aan het menu te geven, wordt het zichtbaar. Doordat bij deze verandering van breedte een transition van 'n halve seconde is opgegeven, lijkt het menu te openen vanaf de linkerkant.

#checkbox-voor-smal:checked + #menu li

Doe iets met de <li>'s binnen het element met id="menu", dat gelijk volgt op het element met id="checkbox-voor-smal", maar alleen als #checkbox-voor-smal is aangevinkt.

Binnen deze <li>'s zitten de links van het menu.

width: 49.5%;

Bij #menu li is een breedte van 35% opgegeven, en een transition van 0,5 seconde. De verandering van breedte duurt dus 'n halve seconde.

Deze combinatie van breedtes en transition is nodig om te zorgen dat er ook tijdens openen en sluiten van het menu altijd twee <li>'s naast elkaar staan.

#content

Het element met id="content". Binnen dit element staat de gewone tekst.

padding: 0 5px;

Omdat voor onder en links geen waarden zijn opgegeven, krijgen die dezelfde waarde als boven en rechts. Hier staat dus eigenlijk 0 5px 0 5px in de volgorde boven – rechts – onder – links.

Boven en onder geen padding, links en rechts 'n afstand tussen tekst en buitenkant van de div.

#content p:first-child

De paragraaf die het eerste kind is van het element met id="content". Oftewel: de eerste paragraaf met gewone tekst. Dit is de paragraaf waar de naam van de pagina staat.

font-size: 2em;

Grotere letter.

text-align: center;

Tekst horizontaal centreren.

margin: 0;

Van zichzelf heeft een <p> aan boven- en onderkant een marge. Die is hier niet welkom.

css voor vensters breder dan 740 px

@media screen and (min-width: 740px)

De css die hier tot nu toe staat, geldt voor alle browservensters. De css die hieronder staat, geldt alleen voor vensters breder dan 740 px. Voor een deel is dit nieuwe css, voor een deel wordt hierboven staande css aangepast.

Browsers die dit niet begrijpen, gebruiken de hieronder staande css niet, maar alleen wat hierboven staat. Misschien is het resultaat daarvan niet mooi, maar het werkt in ieder geval.

@media: geeft aan dat het om css gaat die alleen van toepassing is, als aan bepaalde voorwaarden wordt voldaan. Al langer bestond de mogelijkheid, om met behulp van zo'n regel css voor bijvoorbeeld printers op te geven. css3 heeft dat uitgebreid tot bepaalde fysieke eigenschappen, zoals de breedte en hoogte van het venster van de browser.

screen: deze regel geldt alleen voor schermweergave. Als je wilt printen, is het beter een stylesheet daarvoor te baseren op de algemene css die hierboven staat.

and: er komt nóg een voorwaarde, waaraan moet worden voldaan.

(min-width: 740px): het browservenster moet minstens 740 px breed zijn. Is het venster smaller, dan wordt de css die binnen deze media-regel staat genegeerd.

Gelijk na deze regel komt een { te staan, en aan het einde van de css die binnen deze regel valt een bijbehorende afsluitende }. Die zijn in de regel hierboven weggevallen, maar het geheel ziet er zo uit:

@media screen and (min-width: 740px) { body {color: silver;} (...) rest van de css voor deze @media-regel (...) footer {color: gold;} }

Voor de eerste css binnen deze media-regel staat dus een extra {, en aan het eind staat een extra }.

#menu

Het element met id="menu". Dit is de <nav> waarbinnen het hele menu staat.

Voor dit element geldt ook de bij #menu opgegeven css, voor zover die hier niet wordt veranderd.

width: auto;

Bij #menu is een breedte van 0 opgegeven. Hier wordt de standaard-instelling weer opgegeven: auto.

In het geval van een blok-element zoals een <nav> wil dit zeggen, dat het blok-element normaal genomen even breed wordt als z'n ouder. Dat is hier <body>. Waardoor #menu even breed wordt als het venster van de browser.

overflow: visible;

Bij #menu is overflow op hidden gezet. Hier wordt het weer op de standaardwaarde gezet. Zou je dat niet doen, dan worden de pop-ups niet getoond, want die passen niet binnen #menu.

margin-top: 60px;

Wat ruimte tussen menu en bovenkant van het venster van de browser.

position: relative;

Bij #menu is een absolute positie opgegeven om het menu te kunnen positioneren. Hier gebeurt dat op een andere manier, dus de absolute positie is niet meer nodig.

De standaardinstelling van position is static, maar hieronder wordt een z-index opgegeven. En een z-index werkt alleen maar bij een absolute, fixed of relatieve positie.

top: 0;

Bij #menu is top: 40px; opgegeven. Dat is hier niet meer nodig.

z-index: 10;
Afbeelding 2: zonder z-index wordt de pop-up onder andere elementen gezet
Afbeelding 2: links zonder z-index, rechts met z-index.

Normaal genomen wordt latere html over eerdere heengezet. In dit geval komt de tekst van de pagina over de pop-up te staan, omdat #content na #menu komt in de html.

Door een hogere z-index te geven aan het menu, komt #menu en alles daarbinnen, waaronder de pop-ups, toch boven de andere elementen op de pagina te staan.

De tekst 'een menu met' links op de afbeelding hoort bij de tekst op de pagina zelf en staat, zonder z-index, over de pop-up. Rechts heeft #menu een z-index en staat de pop-up over de tekst op de pagina heen.

Een z-index van 1 zou ook voldoende zijn, maar nu kun je nog nummers tussenvoegen, als er later meer elementen een z-index moeten krijgen.

Een z-index werkt alleen maar, als het element absoluut, fixed of relatief is gepositioneerd. Hierboven is #menu relatief gepositioneerd, dus dat is geregeld.

#menu ul

Voor dit element geldt ook de bij #menu ul opgegeven css, voor zover die hier niet wordt veranderd.

Alle ongeordende lijsten binnen het element met id="menu". Dat is er hier maar eentje. Het menu staat erin.

max-width: 900px;

In brede browservensters kan het menu heel breed worden. Daarom wordt de maximumbreedte beperkt tot 900 px.

margin: 0 auto;

Omdat voor onder en links geen waarde is opgegeven, 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 rechts geen marge, links en rechts auto, wat in dit geval betekent: evenveel. Het menu staat dus altijd horizontaal gecentreerd, ongeacht de breedte van het venster van de browser.

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

#menu li

Voor dit element geldt ook de bij #menu li opgegeven css, voor zover die hier niet wordt veranderd.

Alle lijst-items binnen het element met id="menu". Dit zijn de <li>'s, waarbinnen de links van het menu zitten.

background: blue;

Achtergrond blauw.

height: 34px;

Hoogte.

overflow: visible;

Bij #menu li is overflow op hidden gezet. Hier wordt het weer op de standaardwaarde gezet. Zou je dat niet doen, dan worden de pop-ups niet getoond.

border: none;

Bij #menu li is een border aan de <li>'s gegeven. Weghalen.

padding-bottom: 5px;

Padding aan de onderkant. De blauwe achtergrondkleur loopt, anders dan bij een marge, bij een padding gewoon door.

Onderaan de menubalk staan gekleurde strepen van 5 px hoog. De padding valt hieronder. Zonder padding zou bij inzoomen (vergroten) soms een kier tussen de blauwe achtergrondkleur en de gekleurde strepen ontstaan.

position: relative;

De links binnen het menu (en daarmee ook de gekleurde strepen en pop-ups) moeten worden gepositioneerd ten opzichte van #menu. Dat kan alleen als #menu zelf absoluut, relatief of fixed is gepositioneerd. Omdat er verder geen waarden bij top en dergelijke worden opgegeven, heeft dit op #menu zelf geen enkele invloed.

-ms-user-select: none;

Waarom deze eigenschap wordt voorafgegaan door -ms-, kun je vinden bij De voorvoegsels -moz-, -ms-, -o- en -webkit-.

user-select is nog geen onderdeel van 'n standaard. Waarschijnlijk zal dat geen tien jaar meer duren, want alle browsers herkennen deze eigenschap al (voorafgegaan door het voorvoegsel dat bij de browser hoort).

user-select: none; zorgt ervoor dat de gebruiker geen tekst kan selecteren. In dit geval dus geen tekst die binnen de <li> staat. Op een touchscreen heeft Internet Explorer 10 de neiging de tekst te selecteren, waardoor de link niet in de balk wordt gezet en dus niet kan werken. Deze regel blokkeert het selecteren van de tekst, waardoor alles werkt, zoals het wordt verondersteld te werken.

Omdat dit probleem alleen in Internet Explorer 10 speelt, gebruik ik de vorm voor Opera, Firefox, enz. niet. Ook de vorm zonder het voorvoegsel -ms- gebruik ik niet, omdat niet duidelijk is, of dit probleem in toekomstige versies van Internet Explorer nog bestaat.

#menu li:nth-child(odd)

Voor dit element geldt ook de bij #menu li (voor smalle vensters) en #menu li (voor vensters breder dan 740 px) opgegeven css, voor zover die hier niet wordt veranderd.

Met de pseudo-class :nth-child() kun je een element dat op een bepaalde plaats staat selecteren: de eerste, de tweede, de derde, enz. Eventueel van achteraf geteld. Deze selector kent ook een aantal sleutelwoorden, waaronder odd, wat 'oneven' betekent.

:nth-child(odd) betekent: alle oneven elementen. De eerste, de derde, de vijfde, enz. En omdat er li voor staat, heeft het alleen effect op <li>'s. Die ook nog binnen het element met id="menu" moeten staan. Dit zijn de <li>'s waarbinnen de links van het menu staan.

In normale mensentaal: elke oneven <li> binnen het menu.

Internet Explorer 8 kent deze selector niet, maar daar speelt het hieronder beschreven afrondingsprobleem niet, dus die krijgt verderop eigen css om de <li>'s 12,5% breed te maken.

width: 12%;

Er staan acht <li>'s met in elk een <a> binnen het menu. Als je ze allemaal even breed wilt maken, zou je ze 12,5% breed moeten maken. Dit levert echter 'n probleem op in op webkit gebaseerde browsers zoals Google Chrome, Safari en Android browser.

Als je in deze browsers bij 'n breedte in procenten decimalen gebruikt, worden deze naar beneden afgerond. Waardoor 8 x 12,5 geen 100, maar 96% wordt. In browservensters smaller dan 900 px moet de menubalk de volle breedte vullen, maar in deze browsers houd je rechts 'n lelijke kier van met een breedte van 4% over.

Inmiddels is dit gerepareerd in de desktopversies van Google Chrome en Safari, maar nog niet op iOS en Android. Om die lelijke kier te voorkomen wordt afwisselend 'n breedte van 12 en 13% gebruikt. 4 x 12 + 4 x 13 is samen ook 100%, en dit wordt niet afgerond. Als je goed kijkt, kun je zien dat de ene onderstreping iets langer is dan de andere, maar je moet wel verrekte goed kijken om dat te zien. Feitelijk denk ik dat, als je het niet weet, het gewoon helemaal niet opvalt.

#menu li:nth-child(even)

{width: 13%;}

Hiervoor geldt precies hetzelfde verhaal, als gelijk hierboven staat, maar nu voor de even <li>'s.

#menu li:first-child

Voor dit element geldt ook de bij #menu li (voor smalle vensters) en #menu li (voor vensters breder dan 740 px) opgegeven css, voor zover die hier niet wordt veranderd.

De <li>'s die eerste kind zijn en binnen het element met id="menu" staan. Omdat er maar één <ul> binnen #menu staat, is er maar één serie <li>'s, en kan er dus maar eentje 'n eerste kind zijn. Inderdaad, de meest linkse.

border-top-left-radius: 10px;

Linkerbovenhoek afronden. In tegenstelling tot wat de naam van deze eigenschap suggereert, wordt ook de achtergrondkleur afgerond. Omdat maar één waarde is opgegeven, wordt zowel horizontaal als verticaal over 10 px afgerond, waardoor een gelijkmatige ronding ontstaat.

#menu li:last-child

Voor dit element geldt ook de bij #menu li (voor smalle vensters) en #menu li (voor vensters breder dan 740 px) opgegeven css, voor zover die hier niet wordt veranderd.

De <li>'s die laatste kind zijn en binnen het element met id="menu" staan. Omdat er maar één <ul> binnen #menu staat, is er maar één serie <li>'s, en kan er dus maar eentje het laatste kind zijn. Inderdaad, de meest rechtse.

border-top-right-radius: 10px;

Rechterbovenhoek afronden. In tegenstelling tot wat de naam van deze eigenschap suggereert, wordt ook de achtergrondkleur afgerond. Omdat maar één waarde is opgegeven, wordt zowel horizontaal als verticaal over 10 px afgerond, waardoor een gelijkmatige ronding ontstaat.

#menu li:before

Doe iets vóór elke <li> die binnen het element met id="menu" staat. Dat 'iets doen' is hier het neerzetten van wat tekst, die bij elke <li> anders moet zijn. De tekst zelf wordt verderop apart voor elke <li> opgegeven. Maar er is 'n aantal gemeenschappelijke eigenschappen, en die kan ik hier in één keer opgeven voor alle <li>'s.

De tekst zelf is de tekst die je binnen de menubalk ziet staan, als die nog niet is aangeraakt of als je daar nog niet over hovert.

color: white;

Voorgrondkleur wit, waardoor ook de tekst wit wordt.

font-weight: bold;

Vette letter.

line-height: 34px;

Bij #menu li hebben de <li>'s een hoogte van 34 px gekregen. Tekst wordt automatisch halverwege de regelhoogte neergezet. Door de regelhoogte even hoog te maken als de <li>, wordt de tekst automatisch verticaal gecentreerd.

text-align: center;

Tekst horizontaal centreren.

#menu li:first-child:before

Voor dit pseudo-element geldt ook de bij #menu li:before opgegeven css, voor zover die hier niet wordt veranderd.

Doe iets vóór elke <li> die een eerste kind is en binnen het element met id="menu" staat. Omdat er maar één <ul> binnen #menu staat, is er maar één serie <li>'s, en kan er dus maar eentje 'n eerste kind zijn: de <li> waarbinnen de eerste link staat.

De pseudo-class :first-child wordt hier samen met het pseudo-element :before gebruikt, maar dat kan gewoon. Je kunt meerdere van dit soort pseudo-gevallen achter elkaar zetten.

Hieronder wordt met behulp van content tekst gegenereerd. Bij deze <li> gaat het om het woord 'Home', bij de andere <li>'s gaat het om 'Pagina 1' tot en met 'Pagina 7'.

Deze zelfde tekst staat ook in de links. Normaal genomen staan de links buiten de menubalk, pas bij aanraken van of hoveren over 'n knop wordt de link binnen de balk geplaatst. Dit is nodig om te voorkomen dat op een touchscreen bij de eerste aanraking de link wordt gevolgd.

Als de tekst op de normale manier zou worden neergezet, niet met behulp van :before en content, zouden screenreaders twee keer het woord 'Home' lezen. Maar met content gegenereerde tekst wordt door de meeste screenreaders genegeerd, waardoor dit meestal niet zal gebeuren.

content: "Home";

Zet het woord 'Home' in de <li>.

Omdat oudere browsers mogelijk niet goed met content uit de voeten kunnen, moet je nooit belangrijke informatie via content genereren.

speak: none;

Deze eigenschap is nog vrij nieuw. Hij wordt nog niet gevalideerd door de css-validator. De meeste browsers, screenreaders, en dergelijke kennen hem ook nog niet, maar VoiceOver in OSX schijnt hem al te kennen.

De waarde none voorkomt voorlezen. Als een screenreader toch de door content gegenereerde tekst zou herkennen, voorkomt deze regel het voorlezen ervan.

#menu li:nth-child(2):before

{content: "Pagina\0000a01"; speak: none;} #menu li:nth-child(3):before {content: "Pagina\0000a02"; speak: none;} #menu li:nth-child(4):before {content: "Pagina\0000a03"; speak: none;} #menu li:nth-child(5):before {content: "Pagina\0000a04"; speak: none;} #menu li:nth-child(6):before {content: "Pagina\0000a05"; speak: none;} #menu li:nth-child(7):before {content: "Pagina\0000a06"; speak: none;}

tot en met

#menu li:nth-child(8):before

{content: "Pagina\0000a07"; speak: none;}

Deze zeven regels zijn vrijwel hetzelfde als die bij #menu li:first-child:before. Daarom is de uitleg die daar staat ook grotendeels hier van toepassing. Er zijn maar twee verschillen:

:first-child is vervangen door :nth-child(...). In plaats van :first-child zou je ook kunnen gebruiken: :nth-child(1). Het eerste kind. :nth-child(2) betekent gewoon: het tweede kind. :nth-child(3) het derde kind. Enz.

content: hierachter staat geen 'Home', maar de tekst die bij deze link hoort. Tussen 'Pagina' en het nummer van de pagina staat geen spatie, maar \0000a0. Dit is de code voor een 'vaste spatie'.

Een vaste spatie ziet eruit als een spatie, maar de woorden blijven altijd bij elkaar op dezelfde regel. In html kun je &nbsp; ('no-break space') gebruiken, maar bij tekst die met behulp van content wordt gegenereerd, werkt dat niet. Hier wordt de unicode voor een vaste spatie gebruikt: 0000a0. Dit soort codes is gewoon op internet op te zoeken.

Als je echter gewoon Pagina0000a01 zou gebruiken, wordt precies dat trouwhartig op het scherm gezet. Je moet de computer laten weten dat ergens 'n unicode begint. Dat doe je met 'n zogenaamd 'escape'-teken: de \. De \ geeft aan dat de zes cijfers en letters erachter geen echte tekst zijn, maar een unicode. Waarna de unicode netjes wordt vertaald naar wat hij voor moet stellen. Hier dus een vaste spatie.

Er wordt hier 'n vaste spatie gebruikt, omdat het erg chaotisch en onduidelijk wordt, als het volgnummer van de pagina in z'n eentje op 'n nieuwe regel komt te staan. Nadeel is dat bij een heel grote lettergrootte in Safari op OSX of Firefox op de desktop het volgnummer van de pagina onder de knop rechts ervan kan verdwijnen. Maar dat gebeurt pas bij een vergroting van meer dan 170%.

Bij hoveren over of aanraken van een knop in de menubalk, moet de bijbehorende link binnen die knop worden geplaatst. Die link bevat dezelfde tekst als die in de menubalk. Daarom moet bij de tekst in de link ook een vaste spatie worden gebruikt: Pagina&nbsp;1. Ongeacht de lettergrootte staat de tekst in de link nu altijd precies boven de tekst die al in de menubalk staat.

Internet Explorer 8 kent nth-child() niet, die krijgt later eigen .css.

#menu li:hover:before

li:hover: als je over 'n <li> hovert, of deze aanraakt.

:before: doe dan iets vóór die <li>.

#menu: de <li>'s moeten binnen het element met id="menu" zitten.

In gewone mensentaal: doe iets vóór de <li>'s die binnen het menu zitten, als je over 'n <li> hovert of deze aanraakt.

De pseudo-class :hover wordt hier samen met het pseudo-element :before gebruikt, maar dat kan gewoon. Je kunt meerdere van dit soort pseudo-gevallen achter elkaar zetten.

text-decoration: underline;

Hierboven zijn met behulp van :before en content teksten in de menubalk gezet. Onderstreep deze nu, zodat ze meer op 'n link lijken.

#menu a

Voor dit element geldt ook de bij #menu a opgegeven css, voor zover die hier niet wordt veranderd.

De links die binnen het element met id="menu" zitten. Dit zijn de links van het menu.

Normaal genomen staan deze links aan de linkerkant buiten het scherm. Pas als over de menubalk wordt gehoverd, of als deze wordt aangeraakt, worden de links binnen de juiste knop geplaatst. Hierdoor kan op een touchscreen de eerste aanraking de pop-up openen, en pas de tweede aanraking de link volgen.

De tekst van de links ('Menu', 'Pagina 1', enz.) staat al binnen de menubalk. Maar deze links moeten ook tekst hebben, anders werken ze niet. Je zou ook alleen 'n vaste spatie in de links kunnen zetten of zoiets, maar als 'n browser niet uit de voeten kan met de gegenereerde tekst uit de menubalk, zie je dan helemaal geen tekst. En in browservensters smaller dan 740 px is er helemaal geen menubalk, dus ook geen tekst die daarin staat.

Daarom wordt die tekst gewoon nog 'ns herhaald binnen de links. Als de link in de menubalk wordt neergezet, komt de tekst uit de <a> exact boven de tekst in de menubalk te staan, zodat er voor het oog maar één tekst staat.

background: transparent;

Geen achtergrondkleur. Deze links staan in li>'s die al 'n donkerblauwe achtergrondkleur hebben. Ze hoeven zelf dus geen kleur te hebben.

Hieronder geef ik een witte voorgrondkleur op. Voor het geval de gebruiker een eigen stylesheet heeft, geef ik daarom hier expliciet op dat de link geen achtergrondkleur hoeft te hebben. Dat voorkomt dat de witte tekst mogelijk op 'n gele achtergrond komt te staan, of 'n andere ongelukkige combinatie.

Als de gebruiker !important heeft gebruikt, is er nog niets aan de hand. Tekst en achtergrond blijven dan gewoon op de door de gebruiker ingestelde kleuren staan.

color: white;

Voorgrondkleur wit. Dit is onder andere de kleur van de tekst. Deze witte tekst komt op de donkerblauwe achtergrond van de <li>'s, zodat er voldoende contrast is.

width: 100%;

Een breedte in procenten wordt altijd genomen ten opzichte van de ouder. Dat is hier <li>, die bij #menu li:nth-child(odd) of #menu li:nth-child(even) een breedte van 12 of 13% heeft gekregen, zodat er acht <li>'s naast elkaar in de menubalk passen.

(Die 12 en 13% is ook weer ten opzichte van de ouder. De hele keten is hier: <a> → <li> → <ul> → <nav> → <body>. En omdat onderweg geen van deze elementen een breedte heeft gekregen, is uiteindelijk de breedte van <body> bepalend: de volle breedte van het browservenster. Uiteindelijk zijn die 12 en 13% dus ten opzichte van het browservenster. De enige beperking is dat de <ul> bij #menu ul een maximumbreedte van 900 px heeft gekregen.)

font-weight: bold;

De tekst die al in de menubalk staat, en waar de links met tekst overheen komen te staan, is vet, dus deze moet ook vet zijn.

line-height: 34px;

De tekst die al in de menubalk staat, en waar de links met tekst overheen komen te staan, heeft een regelhoogte van 34 px, dus deze regelhoogte moet ook 34 px zijn.

padding: 0;

Bij #menu a is een padding van 4 px aan de bovenkant gegeven. Die moet weg, want de tekst die al in de menubalk staat, en waar de links met tekst overheen komen te staan, heeft ook geen padding.

position: absolute;

Om de link op de juiste plaats te kunnen positioneren. Er wordt gepositioneerd ten opzichte van de eerste voorouder die een fixed, absolute of relatieve positie heeft. Dat is hier de <li> waar de link in staat.

Van zichzelf is een <a> een inline-element. Door het absoluut te positioneren verandert het in een soort blok-element, waardoor eigenschappen als breedte zijn te gebruiken.

top: 0;

Normaal genomen zou de <a> onder de tekst in de menubalk komen te staan. In dit geval moet de <a>, met de daarin zittende tekst, over de tekst in de menubalk komen te staan. Dus gelijk zetten met de bovenkant van de <li> waar de <a> in zit.

left: -2000px;

Ver links buiten het scherm parkeren. Pas als over de menubalk wordt gehoverd, of als deze wordt aangeraakt, moet de link binnen de menubalk worden geplaatst. Dat gebeurt bij #menu li:hover a, #menu li:hover a span.

Je zou ook iets van display: none; kunnen gebruiken, maar dan werkt de link niet meer in de meeste screenreaders en dergelijke, dus dit is beter.

-webkit-transition: left 0s 0.24s; transition: left 0s 0.24s;

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

Hierboven is de link 2000px buiten de linkerkant van het scherm geparkeerd. Bij hoveren over of aanraken van de menubalk moet de link binnen de menubalk worden gezet. Hij kan daar niet voortdurend staan, omdat anders op touchscreens de link wordt gevolgd in plaats van dat de pop-up wordt geopend.

Bij de eerste aanraking wordt de pop-up geopend en wordt de echte link in de knop geplaatst. Bij de tweede aanraking wordt de link gevolgd. (Bij gebruik van een muis wordt de pop-up geopend bij hoveren, en bij klikken wordt de link gevolgd.)

Bij #menu li:hover a, #menu li:hover a span wordt left: 0; opgegeven, waardoor de link binnen de menubalk wordt neergezet. Als je dat echter zomaar doet, wordt de link zó snel geplaatst, dat de link toch wordt gevolgd, ook al stond hij buiten het scherm. Daarom moet de link met enige vertraging worden geplaatst.

Meestal wordt transition gebruikt om een verandering geleidelijk uit te voeren, maar hier niet.

Bij transition staan twee tijden: 0s en 0.24s. Bij twee tijden geeft de eerste tijd aan, hoe lang de verandering moet duren. In dit geval is dat 0 seconden, oftewel: direct, in één keer. De link met de daarin zittende tekst moet exact boven de al in de menubalk aanwezig zijnde tekst worden geplaatst. Dat moet inderdaad in één keer, het is hier geen gezicht als die tekst langzaam vanaf links naar binnen komt wandelen.

De tweede tijd geeft de vertraging aan: de verandering moet pas beginnen na 0,24 seconde. Pas 0,24 seconde na hoveren over of aanraken van de menubalk wordt de link binnen die balk geplaatst. Dat is zo snel, dat het bij hoveren en klikken nauwelijks of geen problemen oplevert. Nog sneller kan niet, want bij minder dan 0,24 seconde wordt in Android browser op Android 4.0.3 de link al bij de eerste aanraking van de menubalk geopend. 0,24 seconde is precies lang genoeg om ook in deze browser bij de eerste aanraking de pop-up te laten openen, en pas bij de tweede aanraking de link te volgen.

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 :checked, 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, :checked, 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.

Als alle eigenschappen mogen worden vertraagd door transition, is er geen enkel risico voor de toekomst. Dat is hier het geval. Verderop bij #menu li:hover a, #menu li:hover a span verander ik left. Verder verandert er niets. In dit geval mag dus alles vertraagd worden veranderd. Als dat niet zo zou zijn, zou ik moeten opgeven, voor welke eigenschappen transition geldt.

Als er bij #menu li:hover a, #menu li:hover a span eigenschappen staan die niet mogen worden vertraagd, zou ik altijd opgeven, voor welke eigenschappen transition geldt. Ook als transition nu nog niet werkt voor die andere eigenschappen, want mogelijk verandert dat in de toekomst.

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

transition: left 0s 0.24s;

Nu geldt deze transition alleen voor left, wat er in de toekomst mogelijk ook verandert. Maar hier is dat dus niet nodig, omdat bij #menu li:hover a, #menu li:hover a span alleen left wordt gebruikt.

Zou je denken, want in dit geval moet ik vreemd genoeg toch left opgeven, terwijl dat de enige eigenschap is die verandert. Bij #menu a:focus wordt de link binnen de menubalk gezet, als de link focus heeft. Dat moet zonder vertraging gebeuren. Hoe dat precies werkt, staat daar beschreven. Maar om een of andere reden gebeurt het alleen zonder vertraging in Firefox, Opera en de bureaublad-versie van Internet Explorer 10 op Windows 8, als left hier wordt gebruikt.

#menu a span

De spans binnen de links die in het element met id="menu" zitten. Deze spans worden gebruikt om de gekleurde lijnen aan de onderkant van de menubalk neer te zetten. Binnen elke link zit maar één span.

width: 100%;

Deze spans zijn helemaal leegt. Daarom hebben ze geen enkele breedte, tenzij je dat zelf opgeeft. Voor de onderstreping wordt een achtergrondkleur gebruikt. Die is alleen maar zichtbaar, als er een breedte is.

Een breedte in procenten is altijd ten opzichte van de ouder. Dat is hier de <a>, waar de span in staat. En dat komt goed uit, want de streep moet even breed zijn als de <a>. Als de span 100% van de breedte van de bijbehorende <a> heeft, is de span en dus de streep altijd even breed als de <a>, waar de span bij hoort.

height: 5px;

Omdat de span helemaal leeg is, is er geen hoogte. Voor de onderstreping wordt een achtergrondkleur gebruikt. Die is alleen maar zichtbaar, als er een hoogte is.

background: green;

Groene achtergrond. Deze achtergrondkleur zorgt voor de onderstreping onder de link. Voor bezochte links en de link die bij de huidige pagina hoort wordt deze kleur verderop veranderd.

position: absolute;

Om de span, en dus de onderstreping, op de juiste plaats neer te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een relatieve, absolute of fixed positie heeft. Dat is hier de <a>, waar de span in zit.

Een span is van zichzelf een inline-element. Door de span absoluut te positioneren, verandert de span in een soort blok-element, waardoor ook eigenschappen als hoogte gebruikt kunnen worden.

top: 34px;

34 px vanaf de bovenkant neerzetten.

De span, en dus de onderstreping, moet gelijk onder de link komen te staan. Bij #menu a hebben de <a>'s een hoogte van 100% gekregen: even hoog als de <li>'s waar ze in staan. Bij #menu li hebben deze <li>'s een hoogte van 34 px gekregen, dus de <a> is ook 34 px hoog.

left: 2000px;

Bij #menu a zijn de <a>'s, waarbinnen deze spans zitten, 2000 px naar links neergezet, ver buiten het scherm. De <a>'s moeten pas bij hoveren over of aanraken van de menubalk op het scherm worden gezet.

Maar de onderstreping moet altijd zichtbaar zijn. Door de spans 2000 px naar rechts te plaatsen, wordt de verplaatsing van de <a>'s met 2000 px naar links geneutraliseerd, en zijn de onderstrepingen dus altijd zichtbaar.

-webkit-transition: 0s 0.24s; transition: 0s 0.24s;

De spans moeten altijd zichtbaar zijn, zodat de onderstrepingen dat ook zijn. Hierboven zijn ze om die reden 2000 px naar rechts verplaatst. Maar als over de menubalk wordt gehoverd, of als deze wordt aangeraakt, worden de <a>'s waar de spans in zitten 2000 px naar rechts verplaatst. De spans komen aan de rechterkant ver buiten het scherm te staan.

Bij aanraken van of hoveren over de menubalk moeten de spans daarom niet meer naar 2000 px naar rechts worden verplaatst, want die correctie is niet meer nodig. Hetzelfde geldt trouwens als de <a> focus heeft. Daarom wordt bij #menu li:hover a, #menu li:hover a span en #menu a:focus span left: 0; opgegeven.

Omdat de <a> nu binnen de menubalk staat, kan de daarin zittende span gewoon op de normale plaats worden neergezet.

Bij het binnen de menubalk zetten van de <a>'s is met behulp van transition een kleine vertraging ingebouwd, waardoor de eerste aanraking op touchscreens de pop-up opent, en pas de tweede aanraking de link volgt. Deze zelfde vertraging moet worden in gebouwd bij de spans, omdat de verplaatsing van de onderstreping anders plaatsvindt, voordat de <a> is verplaatst. Waardoor de onderstreping (heel kort) rechts buiten het scherm verdwijnt.

Deze transition werkt vrijwel hetzelfde als die bij #menu a. De uitleg staat bij -webkit-transition: left 0s 0.24s, transition: left 0s 0.24s;. Het enige verschil is dat hier left niet nodig is.

#menu #hier span

Voor dit element geldt ook de bij #menu a span opgegeven css, voor zover die hier niet wordt veranderd.

De spans binnen het element met id="hier", dat weer binnen het element met id="menu" moet staan. Hier is dat maar één span, die zorgt voor de onderstreping.

De huidige pagina krijgt een grijze onderstreping. Door aan de <a> die bij deze pagina hoort een id="hier" te geven, kan aan de in die <a> zittende span een andere kleur worden gegeven.

Bij #menu a span hebben de spans een groene achtergrondkleur gekregen, wat een groene onderstreping oplevert.

Hieronder krijgen spans die bij een bezochte link horen een rode achtergrondkleur met #menu a:visited span.

Deze selector heeft meer specificiteit ('gewicht') dan de andere twee. Daardoor overrulet deze selector de andere twee selectors, ook al staat #menu a:visited span later in de css.

#menu a span en #menu a:visited span hebben beide maar één id: #menu.

Deze selector heeft twee id's: #menu en #hier. Een selector met meer id's heeft altijd meer specifiteit, meer gewicht, dan een selector met minder id's. De huidige pagina krijgt dus altijd de hieronder opgegeven grijze kleur, of de link nu is bezocht of niet.

background: #999;

Grijze achtergrondkleur.

#menu a:visited span

Voor dit element geldt ook de bij #menu a span opgegeven css, voor zover die hier niet wordt veranderd.

De spans binnen de links die in het element met id="menu" zitten, maar alleen als de link al is bezocht. Deze spans worden gebruikt om de gekleurde lijnen aan de onderkant van de menubalk neer te zetten. Binnen elke link zit maar één span.

Omdat het kinderlijk eenvoudig bleek om met behulp van wat JavaScript en css uit te lezen, welke sites waren bezocht, kun je bij bezochte links nog maar heel weinig veranderen met behulp van css. Eén van de dingen die nog kan worden veranderd, is de kleur van de achtergrond.

background: red;

Rode achtergrondkleur.

#menu li:hover a, #menu li:hover a span

Twee selectors, gescheiden door 'n komma.

De eerste: doe iets met de links binnen de <li>'s die in het element met id="menu"zitten. Maar alleen als over die <li> wordt gehoverd, of als deze wordt aangeraakt. Dit zijn de links die binnen het menu zitten.

De tweede: deze is precies hetzelfde, maar geldt voor de spans binnen de links. Deze spans zorgen voor de onderstreping.

De opmaak voor deze elementen is al bij #menu a en #menu a span opgegeven, hier worden ze alleen op de juiste plaats gezet.

left: 0;

Bij #menu a zijn de links met left: -2000px; ver buiten de linkerkant van het scherm geparkeerd. Omdat de in de <a>'s zittende spans, die voor de onderstrepingen zorgen, altijd zichtbaar moeten zijn, zijn deze bij #menu a span met left: 2000px; juist 2000 px naar rechts verplaatst.

Bij hoveren over of aanraken van een knop in de menubalk, wordt de bijbehorende <a> binnen het scherm gezet. Omdat gepositioneerd wordt ten opzichte van de <li> waar de <a> in zit, kan dat heel simpel met left: 0;.

De in de <a> zittende spans waren 2000 px naar rechts geplaatst, om ze altijd zichtbaar te houden. Als de <a> binnen de <li> staat, is deze correctie niet meer nodig. De span wordt gepositioneerd ten opzichte van de <a> waar hij in zit, dus ook hier werkt het simpele left: 0;.

#menu a:focus

Voor dit element geldt ook de bij #menu a opgegeven css, voor zover die hier niet wordt veranderd.

De links binnen het element met id="menu", maar alleen als die links focus hebben.

Een link kan focus krijgen, als de gebruiker er met de Tab-toets of op soortgelijke wijze naar toe is gegaan. Meer over :focus kun je vinden bij :hover, :focus en :active voor muis, toetsenbord, touchpad en touchscreen.

background: white;

Achtergrondkleur wit. Bij #menu a is een doorzichtige achtergrond opgegeven, hier wordt deze wit. Omdat de link bij focus binnen de menubalk wordt gezet, verbergt deze witte achtergrondkleur de blauwe achtergrondkleur van de <li>, waarbinnen de link zit.

color: black;

Voorgrondkleur, waaronder de tekstkleur, zwart. Bij #menu a is een witte voorgrondkleur opgegeven. Hierboven is de achtergrondkleur in wit veranderd. Een witte tekst op een witte achtergrond leest mogelijk wat lastig, dus maken we hem zwart.

height: 39px;

39 px hoog. Bij #menu a hebben de <a>'s een hoogte van 100% gekregen, even hoog als hun ouder <li>. <li> heeft bij #menu li een hoogte van 34 px gekregen, dus de <a>'s zijn ook 34 px hoog. Daar komt nog de onderstreping van 5 px aan de onderkant bij. Samen 39 px.

Door de <a> hier 39 px hoog te maken, komt de outline die hieronder wordt gegeven niet alleen om de <a>, maar ook om de onderstreping te staan. Wat ik iets mooier vind.

outline: black solid 1px;

Dunne zwarte outline rondom de hele link. Door de outline wordt de <a> aan alle kanten 1 px groter. Daarom is een outline hier beter dan een border, want een outline wordt gewoon over de elementen ernaast heen gezet. Een border zou de elementen ernaast 1 px verplaatsen, wat een springerig effect geeft.

left: auto;

Bij #menu a is met behulp van transition opgegeven dat de <a> met 0,24 seconde vertraging binnen het menu wordt gezet. Dat gaat prima bij aanraken of hoveren, maar is wat verwarrend bij gebruik van de Tab-toets om de links focus te geven. Door de vertraging van 0,24 seconde duurt het even, voor je ziet, welke link focus heeft. Als je de Tab-toets snel achter elkaar indrukt, is dat verwarrend.

Als je transition gebruikt bij de eigenschap left, hoort dat alleen te werken, als je bij :focus, :hover, en dergelijke een absolute waarde in px of zo, een waarde in procenten of calc() gebruikt. Door auto te gebruiken bij :focus, wordt de hele transition en dus de vertraging genegeerd.

Tegen de specificatie in werkt dit helaas niet in Safari op OS X en in Google Chrome overal. Daar duurt het toch 0,24 seconde, voor je ziet, welke link focus heeft.

#menu a:focus:after

Doe iets na elke <a> die focus heeft en in het element met id="menu" zit.

De pseudo-class :focus wordt hier samen met het pseudo-element :after gebruikt, maar dat kan gewoon. Je kunt meerdere van dit soort pseudo-gevallen achter elkaar zetten.

Een link kan focus krijgen, als de gebruiker er met de Tab-toets of op soortgelijke wijze naar toe is gegaan. Meer over :focus kun je vinden bij :hover, :focus en :active voor muis, toetsenbord, touchpad en touchscreen.

display: none;

Bij #menu a:after wordt css voor een pop-up gegeven, die geopend wordt bij hoveren over of aanraken van een <li> in de menubalk. Deze pop-up opent dus niet door aanraken van of hoveren over de <a>, maar over de <li>. Omdat de <li> geen focus kan krijgen (niet zonder het 'n stuk ingewikkelder te maken), heeft deze pop-up bij a:focus geen zin. Maar hij geeft wel problemen, omdat hij in sommige browsers de link iets hoger maakt.

Deze pop-up wordt gegenereerd met behulp van :after. Door de hele pop-up gewoon te verbergen, verberg je ook de problemen. Hmmm, doet me aan m'n voorlaatste psychiater denken...

#menu a:focus span

Voor dit element geldt ook de bij #menu a span opgegeven css, voor zover die hier niet wordt veranderd. Voor bezochte links geldt ook de bij #menu a:visited span opgegeven css, voor de link die bij de huidige pagina hoort ook de bij #menu #hier span opgegeven css.

De spans binnen de links die in het element met id="menu" zitten, maar alleen als de link focus heeft. Binnen elke link zit maar één span. Deze spans worden gebruikt om de gekleurde lijnen aan de onderkant van de menubalk neer te zetten.

Een link kan focus krijgen, als de gebruiker er met de Tab-toets of op soortgelijke wijze naar toe is gegaan. Meer over :focus kun je vinden bij :hover, :focus en :active voor muis, toetsenbord, touchpad en touchscreen.

right: 0;

De in de <a> zittende spans waren 2000 px naar rechts geplaatst, om ze altijd zichtbaar te houden. Als de <a> binnen de <li> staat, is deze correctie niet meer nodig. Hieronder wordt de left: 2000px; dan ook veranderd in left: auto;, de standaardinstelling.

Bij #menu a span is de span absoluut gepositioneerd, waardoor deze in een soort blok-element is veranderd. 'n Soort, niet helemaal. Je kunt weliswaar breedte en zo gebruiken, maar er zijn nog restanten van z'n inline-oorsprong: hij wordt achter de tekst binnen de link gezet. Dat komt omdat gelijk hieronder left op auto wordt gezet, waardoor er in horizontale richting geen positie meer wordt opgegeven.

Afbeelding 3: rode streep bij focus is te kort

Op de afbeelding zou de rode streep even breed moeten zijn als de witte link, maar hij vult alleen de lege ruimte na de '2'. De lengte is wel goed, maar dat zie je hier niet omdat het deel van de rode streep rechts van de link verdwijnt onder de ernaast staande groene streep.

Om dit op te lossen zou je hier display: block; kunnen gebruiken, dan wordt het 'n echt blok-element en wordt het keurig links neergezet. Hier heb ik voor 'n andere oplossing gekozen. De lengte van de span is goed, dus als je hem vanaf rechts neerzet, en niet vanaf links, komt hij ook goed te staan.

En omdat de span exact even lang is als de link, waar hij onder moet staan, voldoet right: 0; hier prima.

left: auto;

Bij #menu a span is met behulp van transition opgegeven, dat de span met 0,24 seconde vertraging binnen het menu wordt gezet. Dat gaat prima bij aanraken of hoveren, omdat ook de <a> met diezelfde vertraging binnen de menubalk wordt gezet. De onderstreping komt dus zogezegd op hetzelfde moment aan als de bijbehorende <a>.

Als de link focus heeft, is er geen vertraging: de <a> wordt gelijk in de menubalk gezet. Als de onderstreping wel vertraging zou hebben, zou deze 0,24 seconde na de link aankomen. Dat ziet er niet uit.

Als je transition gebruikt bij de eigenschap left, hoort dat alleen te werken, als je bij :focus, :hover, en dergelijke een absolute waarde in px of zo, een waarde in procenten of calc() gebruikt. Door auto te gebruiken bij :focus, wordt de hele transition en dus de vertraging genegeerd. De onderstreping komt nu op hetzelfde moment aan als de bijbehorende <a>.

Tegen de specificatie in werkt dit helaas niet in Safari op OS X en in Google Chrome overal. Daar duurt het toch 0,24 seconde, voor de onderstreping op z'n plaats staat. Maar daar duurt het ook 0,24 seconde voor de link op z'n plaats staat, dus de onderstreping blijft wel voortdurend bij de bijbehorende link. Die vertraging is wel wat verwarrend, maar dat geldt voor de hele <a>, inclusief de span met onderstreping.

#menu #hier:hover

Het element met id="hier", dat binnen het element met id="menu"zit, maar alleen als je over #hier hovert. Dit is de <a> uit het menu die bij de huidige pagina hoort.

cursor: default;

Omdat dit geen echte link is, moet de cursor niet in 'n handje veranderen. Omdat 'n touchscreen geen cursor heeft, heeft dit geen effect op 'n touchscreen.

#menu a:after

Doe iets achter de links in het element met id="menu". Bij hoveren over of aanraken van een <li> in de menubalk moet een kleine pop-up verschijnen met meer info over de link. De inhoud van die pop-up wordt met behulp van :after en content gemaakt.

Omdat de tekst in de pop-up bij elke <a> anders is, wordt die verderop voor elke link apart opgegeven met behulp van content. De opmaak is voor alle pop-ups hetzelfde, dus die kan ik hier in één keer voor allemaal opgeven.

background: yellow;

Gele achtergrond.

color: black;

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

Hoewel dit de standaardkleur is, geef ik de kleur toch op. Hierboven heb ik een achtergrondkleur opgegeven. 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 in een eigen stylesheet, is er nog niets aan de hand, want dan veranderen achtergrond- en voorgrondkleur geen van beide.

display: block;

Met behulp van :after gegenereerde content is van zichzelf een inline-element. Door er een blok-element van te maken, kunnen eigenschappen als breedte en hoogte worden gebruikt.

width: 92%;

Een breedte in procenten is altijd ten opzichte van de ouder. Dat is hier de <a>. De pop-up moet even breed worden als de link, waar hij bij hoort. Omdat hieronder rechts en links nog 3% padding wordt opgegeven, is het totaal 3 + 92 + 3 = 100% breedte. Oftewel: even breed als de link waar de pop-up bij hoort.

Omdat de onderstreping dezelfde breedte heeft, staat de pop-up netjes onder de onderstreping.

min-width: 6.5em;

Omdat de breedte is opgegeven in procenten, kan die in smallere browservensters wat te klein worden, om alle tekst weer te kunnen geven. Om dat te voorkomen, wordt een minimumbreedte opgegeven.

Als eenheid wordt em genomen, omdat die eenheid gebaseerd is op de lettergrootte. Bij een grotere letter is de minimumbreedte daardoor breder dan bij een kleinere letter.

height: 0;

Helemaal geen hoogte. Bij #menu li:hover a:after wordt de hoogte veranderd in 5,8 em. Met behulp van transition duurt die verandering 1 seconde, waardoor de pop-up geleidelijk aan opent vanaf de bovenkant. (Daarvoor is ook nog een aanpassing van top nodig, die iets verderop staat.)

overflow: hidden; Afbeelding 4: de tekst in de pop-up wordt te snel zichtbaar

Standaard staat overflow op visible: als iets niet binnen het element past, laat het dan toch zien. Normaal genomen is dat ook, wat je wilt. Mogelijk wordt de lay-out verstoord, maar in ieder geval kun je alles zien.

Hier is dat niet zo. Als je alle tekst ziet, zodra de pop-up opent, ziet dat er tijdens het openen uit als op de afbeelding. De tekst is in één keer zichtbaar, de bijbehorende achtergrondkleur en border zijn pas na 'n seconde op de juiste hoogte.

Daarom wordt hier het teveel aan tekst verborgen. Zodra de pop-up helemaal open is, past de tekst erin, en is dus de volledige tekst zichtbaar.

font-size: 0.9em;

Iets kleinere letter. Als eenheid gebruik ik em, zodat ook gebruikers van Internet Explorer de lettergrootte kunnen aanpassen.

font-weight: normal;

Bij #menu a is een vette letter opgegeven. Die wordt ook gebruikt bij :after. Dat is bij zo'n kleine letter niet mooi, dus terug naar 'n normale dikte.

line-height: normal;

Bij #menu a is een regelhoogte van 34 px opgegeven. Dat is hier natuurlijk veel te veel. normal is de standaardwaarde, dat is ongeveer 1,2 em.

text-align: left;

Bij #menu li is alle tekst binnen <li>'s horizontaal gecentreerd, dus ook de tekst van deze pop-ups. Hier wordt de tekst weer gewoon links uitgelijnd.

border: black solid 1px;

Randje rondom de pop-up.

border-radius: 0 0 8px 8px;

De naam van deze eigenschap is wat slecht gekozen, want er worden niet alleen borders afgerond, maar ook dingen als achtergronden.

Je kunt aparte waarden opgegeven voor horizontaal en verticaal, maar dat gebeurt hier niet. Hierdoor worden deze hoeken horizontaal en verticaal even groot, als delen van een cirkel. Bij twee ongelijke waarden voor 'n hoek wordt deze ellipsvormig.

De vier waarden corresponderen met de vier hoeken, zoals gebruikelijk bij css met de klok mee: linksboven – rechtsboven – rechtsonder – linksonder. Links‑ en rechtsboven geen hoek, rechts- en linksonder een ronde hoek van 8 px.

padding: 10px 3%;

Omdat voor links en onder geen waarde is opgegeven, krijgt links automatisch dezelfde waarde als rechts. Hier staat dus eigenlijk 10px 3% 10px 3% in de volgorde boven – rechts – onder – links.

Van de 10 px padding aan de bovenkant valt 5 px weg onder de onderstreping.

Links en rechts een padding van 3%. Een padding in procenten wordt altijd genomen ten opzichte van de ouder. Dat is hier de <a>. In een smaller browservenster wordt de <a> smaller, en de padding dus ook. Hierdoor houdt de padding altijd de juiste verhouding.

Aan de onderkant 10 px padding. Dat is wat veel, maar er is wat verschil in lettergrootte tussen de diverse browsers. Daardoor past in de ene browser wat minder tekst op dezelfde regel als in de andere browser. Waardoor bij een kleinere padding in sommige browsers een deel van de tekst onder de gele achtergrond en het zwarte randje komt te staan.

position: relative;

Dit maakt het mogelijk de pop-up te verplaatsen ten opzichte van de positie, waar hij normaal genomen zou komen te staan.

top: -17px;

Normaal genomen wordt de pop-up gelijk onder de link gezet. Dat gebeurt hier pas bij #menu li:hover a:after, als over de <li> met de daarin zittende link wordt gehoverd, of als de <li> wordt aangeraakt.

Door de pop-up eerst hoger te zetten en pas bij hoveren over of aanraken van de menubalk gelijk onder de link te zetten, opent de pop-up gelijkmatiger. Met behulp van transition duurt die verplaatsing 1 seconde, waardoor de pop-up geleidelijk aan opent vanaf de bovenkant. (Daarvoor is ook nog een aanpassing van height nodig, die iets hierboven staat.)

Bij 'n kleinere waarde dan 17 px blijft in Safari op OSX een klein stukje van de pop-up geopend, wat dan even later met 'n schok sluit.

z-index: -1;

De pop-up komt tijdens het openen over de blauwe achtergrondkleur van de menubalk en over de onderstreping te staan. Als de pop-up helemaal open is, staat hij onder de menubalk, maar nog steeds over de onderstreping.

Een negatieve z-index plaatst de pop-up helemaal onderaan, onder de blauwe achtergrondkleur en onder de onderstreping.

Een z-index werkt alleen, als het element absoluut, fixed of relatief is gepositioneerd. Hierboven is relatief gepositioneerd, dus dat is geregeld.

-webkit-transition: 1s 0.24s; transition: 1s 0.24s;

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

Iets hierboven is de pop-up 17 px naar boven verplaatst en heeft een hoogte van 0 gekregen. Bij hoveren over of aanraken van de menubalk moet de pop-up worden geopend. Dat gebeurt door de pop-up 17 px naar omlaag te verplaatsen, gelijk onder de link, en door er een hoogte van 5,8 em aan te geven. Dit gebeurt bij #menu li:hover a:after.

De link waar de pop-up in zit, staat normaal genomen links buiten het scherm geparkeerd. Deze link wordt pas bij aanraken van of hoveren over de menubalk binnen het scherm gezet. Met een vertraging van 0,24 seconde. Daarom moet de pop-up ook met een vertraging van 0,24 seconde beginnen met openen. Anders is hij al gedeeltelijk open, voordat de link met de pop-up binnen het scherm staat.

Bij transition staan twee tijden: 1s en 0.24s. Bij twee tijden geeft de eerste tijd aan, hoe lang de verandering moet duren. In dit geval is dat 1 seconde.

De tweede tijd geeft de vertraging aan het begin aan: de verandering moet pas beginnen na 0,24 seconde. Pas 0,24 seconde na hoveren over of aanraken van de menubalk wordt de link binnen die balk geplaatst, en pas dan moet de pop-up beginnen te openen.

Sneller kan niet, want bij minder dan 0,24 seconde wordt in Android browser op Android 4.0.3 de link al bij de eerste aanraking van de menubalk geopend. 0,24 seconde is precies lang genoeg om ook in deze browser bij de eerste aanraking de pop-up te laten openen, en pas bij de tweede aanraking de link te volgen.

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 :checked, 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, :checked, 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.

Als alle eigenschappen mogen worden vertraagd door transition, is er geen enkel risico voor de toekomst. Dat is hier het geval. Verderop bij #menu li:hover a:after verander ik de hoogte en top. Verder verandert er niets. In dit geval mag dus alles vertraagd worden veranderd. Als dat niet zo zou zijn, zou ik moeten opgeven, voor welke eigenschappen transition geldt.

Als er bij #menu li:hover a:after eigenschappen staan die niet mogen worden vertraagd, zou ik altijd opgeven, voor welke eigenschappen transition geldt. Ook als transition nu nog niet werkt voor die andere eigenschappen, want mogelijk verandert dat in de toekomst.

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

transition: height 1s 0.24s, top 1s 0.24s;

Nu geldt deze transition alleen voor height en top, wat er in de toekomst mogelijk ook verandert. Maar hier is dat dus niet nodig, omdat bij #menu li:hover a:after alleen height en top worden gebruikt.

Normaal genomen wordt een transition ook in omgekeerde volgorde in hetzelfde tempo afgelegd. Als er niet meer over de menubalk wordt gehoverd, of als 'n andere knop in de balk wordt aangeraakt, zou het ook weer 1 seconde duren om de pop-up te sluiten. Dat is niet echt geweldig, want als je door de menubalk beweegt begint dat 'n beetje op het Nationale Ballet te lijken. Niets tegen ballet, maar het zou hier wat druk zijn.

Geleidelijk openen is mooi (vind ik), maar het sluiten mag wel vlug gebeuren. Geen enkele reden de bezoeker te irriteren met 'n wachttijd van 0,24 seconde en dan nog 1 seconde om volledig te sluiten.

Dat gebeurt hier echter niet. De link, waar de pop-up in zit, wordt na 0,24 seconde weer links buiten het scherm geparkeerd. En daar kan de pop-up rustig sluiten, zonder dat iemand dat ziet. Het duurt dus maar 0,24 seconde voor de pop-up weer is verdwenen. Dat is zo kort, dat je de vertraging nauwelijks ziet.

Dat het sluiten inderdaad 1 seconde duurt, kun je zien als je de cursor snel heen-en-weer over de menubalk beweegt, of snel achter elkaar de verschillende knoppen aanraakt. Als je 'n voor de tweede keer over 'n knop hovert of deze aanraakt, kun je zien dat de pop-up nog niet helemaal gesloten was.

#menu li:hover a:after

Doe iets achter de <a>'s die binnen een <li> zitten, die weer binnen het element met id="menu" zitten, maar alleen als over de <li> wordt gehoverd, of als deze wordt aangeraakt.

Er wordt hier een pop-up geopend, waarvoor de opmaak al bij #menu a:after is opgegeven.

height: 5.8em;

Bij #menu a:after is een hoogte van 0 opgegeven, waardoor de pop-up normaal genomen onzichtbaar is. Hier wordt er een hoogte aan gegeven. Omdat transition is gebruikt, duurt het 1 seconde voor de hoogte is bereikt, waardoor de pop-up vanaf de bovenkant opent. (Hiervoor is ook een verandering in top nodig, die hieronder wordt gegeven.)

Eenheid moet percentage, getal of calc() zijn, auto werkt niet bij transition. Dat komt hier wat ongelukkig uit, want als auto gebruikt zou kunnen worden, zou de pop-up altijd precies de juiste hoogte krijgen voor de erin zittende tekst.

Er is wat verschil in lettergrootte en zo tussen de verschillende browsers en systemen. Met een hoogte van 5,8 em past de tekst in elke browser op elk systeem binnen de pop-up.

top: 0;

Bij #menu a:after is top: -17px; opgegeven. In combinatie met de hierboven opgegeven verandering in hoogte, opent de pop-up hierdoor geleidelijk vanaf de bovenkant. Het geleidelijk openen gedurende 1 seconde komt door het gebruik van transition bij #menu a:after.

#menu li:first-child a:after

Voor dit pseudo-element geldt ook de bij #menu a:after en #menu li:hover a:after opgegeven css, voor zover die hier niet wordt veranderd. Bij die twee selectors is de opmaak voor de pop-ups al gegeven. Hier wordt de tekst voor de pop-up opgegeven.

Doe iets achter de <a>'s die in de <li> zitten, die een eerste kind zijn en binnen het element met id="menu" zitten. Omdat er binnen #menu maar één <ul> zit, is er ook maar één li eerste kind. Binnen deze <li> zit de eerste link van het menu.

content: "Ruimte voor informatie over de homepage";

Omdat de tekst van de pop-up voor elke link anders is, kan die niet voor alle links tegelijk worden opgegeven, zoals de rest van de opmaak.

Dit is de tekst die bij de eerste link hoort.

Omdat oudere browsers mogelijk niet goed met content uit de voeten kunnen, moet je nooit belangrijke informatie via content genereren.

#menu li:nth-child(2) a:after

content: "Ruimte voor informatie over de inhoud van pagina 1"; #menu li:nth-child(3) a:after content: "Ruimte voor informatie over de inhoud van pagina 2"; #menu li:nth-child(4) a:after content: "Ruimte voor informatie over de inhoud van pagina 3"; #menu li:nth-child(5) a:after content: "Ruimte voor informatie over de inhoud van pagina 4"; #menu li:nth-child(6) a:after content: "Ruimte voor informatie over de inhoud van pagina 5";

tot en met

#menu li:nth-child(7) a:after

content: "Ruimte voor informatie over de inhoud van pagina 6";

Deze zes regels zijn vrijwel hetzelfde als die bij #menu li:first-child a:after. Daarom is de uitleg die daar staat ook grotendeels hier van toepassing. Er zijn maar twee verschillen:

:first-child is vervangen door :nth-child(...). In plaats van :first-child zou je ook kunnen gebruiken: :nth-child(1). Het eerste kind. :nth-child(2) betekent gewoon: het tweede kind. :nth-child(3) het derde kind. Enz.

content: hierachter staat de tekst die bij de betreffende link hoort.

Internet Explorer 8 kent nth-child() niet, die krijgt later eigen css.

#menu li:nth-child(8) a:after

content: "Ruimte voor informatie over de inhoud van pagina 7";

Dit deel van deze selector is precies hetzelfde als de zes selectors hier gelijk boven.

float: right;

Dit is een extra regel, die bij de zeven selectors voor de eerste zeven links niet staat.

Zet de pop-up zover mogelijk naar rechts. In dit geval wordt de pop-up tegen de rechterkant van de <a> gezet.

Normaal genomen zie je daar niets van, maar wel bij een grotere letter. Bij #menu a:after is aan de pop-up een breedte van 100% gegeven (een breedte van 94% + links en rechts een padding van 3%). Daar is ook een minimumbreedte van 6,5 em gegeven.

Als de lettergrootte wordt vergroot, neemt de minimumbreedte toe, omdat em gebaseerd is op de lettergrootte. Op een gegeven moment wordt de pop-up hierdoor breder dan de <a>, waar hij bij hoort. Dat is geen probleem bij de eerste zeven pop-ups, want die worden dan gewoon iets breder dan de bijbehorende <a>.

Deze laatste pop-up zou echter rechts buiten de menubalk uit kunnen gaan steken. In een smal vensters zou de pop-up daardoor ook rechts buiten het browservenster uit kunnen steken, waardoor hij zonder scrollen niet volledig zichtbaar is.

Door de meest rechtse pop-up naar rechts te floaten, wordt hij vanaf rechts neergezet en kan dus nooit rechts buiten de <a> uitsteken. Als de pop-up breder wordt dan de <a>, steekt hij aan de linkerkant uit, waar hij gewoon zichtbaar is.

#menu #hier:after

Doe iets na het element met id="hier", dat in het element met id="menu" zit. De <a> die bij de huidige pagina hoort, heeft een id="hier". Het gaat hier dus om de link die bij de huidige pagina hoort.

Bij #menu li:hover a:after wordt opgegeven dat een pop-up moet openen bij hoveren over een <li>. Die css geldt ook voor a#hier, want ook dat is een <a> die gewoon binnen een <li> zit. Normaal genomen zou dus ook bij hoveren over of aanraken van de knop die bij de huidige pagina hoort een pop-up openen. Dat wil ik niet. Deze selector voorkomt dat.

De selector #menu li:hover a:after heeft maar één id: #menu. Deze selector heeft twee id's: #menu en #hier. Een selector met meer id's heeft altijd meer specifiteit, meer gewicht, dan een selector met minder id's. Daardoor overrulet de css hieronder die van #menu li:hover a:after.

display: none;

Niets tonen. Hierdoor wordt de bij deze <a> horende pop-up niet weergegeven.

#sluitbalk

Voor dit element geldt ook de bij #sluitbalk opgegeven css, voor zover die hier niet wordt veranderd.

Het element met id="sluitbalk". Dit is een div die je niet ziet. Hij zorgt voor het tonen en verbergen van de twee erin zittende sluitkruisjes, die nodig zijn om op iOS de pop-ups te kunnen sluiten.

max-width: 900px;

Bij #menu ul is opgegeven dat de menubalk een maximumbreedte van 900 px heeft. #sluitbalk moet ervoor zorgen dat de twee sluitkruisjes links‑ en rechtsonder de menubalk komen te staan. Daarom mag #sluitbalk niet breder worden dan de menubalk.

margin: 0 auto;

Omdat voor links en onder geen waarde is opgegeven, 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 hetzelfde betekent als evenveel. Ongeacht de breedte van het venster van de browser staat #sluitbalk altijd horizontaal gecentreerd.

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

position: relative;

Dit maakt het mogelijk de div te verplaatsen ten opzichte van de positie, waar hij normaal genomen zou komen te staan.

top: 38px;

38 px naar omlaag verplaatsen.

Zonder deze verplaatsing zouden de in #sluitbalk zittende sluitkruisjes niet zichtbaar zijn, omdat ze worden afgedekt door de menubalk.

Er zijn nog ongeveer 73 andere mogelijkheden om dit op te lossen, maar ik heb voor deze oplossing gekozen. #sluitbalk is een fatsoenlijke div van goede komaf. 'n rechtstreeks kind van <body>, 'n betere afkomst kun je niet hebben.

(Tja, ik kan 't ook niet helpen, maar bij css is je afkomst nou eenmaal heel belangrijk.)

Goed, #sluitbalk is dus van uitstekende komaf. Maar helaas gaat hij met de verkeerde vriendjes #menu en de daarin zittende <ul> en <li>'s om en raakt daardoor aan lager wal. Of in dit geval eigenlijk: aan hoger wal. Normaal genomen zou een div namelijk gewoon onder het element ervoor worden neergezet. Dat is hier nav#menu, waarin de menubalk staat. Dat zou precies de goede plaats zijn.

Afbeelding 5: sluitbalk even zichtbaar gemaakt

Op de afbeelding hiernaast is #sluitbalk even iets breder gemaakt en heeft 'n rode outline gekregen en 'n hoogte van 1 px, zodat hij zichtbaar wordt. Op deze manier kun je zien dat #sluitbalk niet onder nav#menu staat, maar op dezelfde hoogte.

De verklaring is wat ingewikkeld.

Een blok-element als nav#menu krijgt normaal genomen automatisch precies genoeg hoogte, om de inhoud ervan weer te kunnen geven. Die inhoud is hier de <ul>.

Die <ul> is ook een blok-element, en krijgt normaal genomen dus ook genoeg hoogte om de inhoud ervan weer te kunnen geven.

De inhoud van de <ul> bestaat uit 8 <li>'s, die elk een hoogte van 34 px en een padding onderaan van 5 px hebben, samen 39 px. Dus zou de <ul> en vervolgens nav#menu 39 px hoog moeten zijn, waardoor #sluitbalk hier netjes onder zou komen te staan.

De <li>'s zijn echter bij #menu li gefloat, en dan tellen ze niet meer mee voor de hoogte van de ouder <ul>. Waardoor <ul> dus geen hoogte heeft. En dus nav#menu ook niet.

#sluitbalk staat dus wel degelijk onder nav#menu, maar nav#menu heeft gewoon geen hoogte.

Door #sluitbalk 38 px omlaag te verplaatsen, komt deze op de goede plaats te staan, en de daarin zittende sluitkruisjes ook. Het menu heeft bij #menu li een hoogte van 34 px en een padding onderaan van 5 px gekregen, samen 39 px. Door 1 px minder naar omlaag te verplaatsen, valt de border van 1 px aan de bovenkant van de sluitkruisjes weg onder de menubalk, wat ik iets mooier vind.

.sluiten

De elementen met class="sluiten". Dit zijn de twee spans, waarin de sluitkruisjes staan die zichtbaar worden bij hoveren over of aanraken van de menubalk. Deze elementen zijn nodig om op iOS de pop-ups te kunnen sluiten.

Het zijn er twee, eentje links‑ en eentje rechtsonder de menubalk. Daardoor is er altijd minstens eentje zichtbaar, ongeacht welke pop-up is geopend.

background: white;

Achtergrond wit.

color: red;

Voorgrondkleur, waaronder de tekstkleur, rood.

width: 0.5em; height: 0.5em;

Hoogte en breedte. Door als eenheid em te nemen, veranderen hoogte en breedte in alle browsers mee met de lettergrootte.

overflow: hidden; font-size: 3em; line-height: 0.35em;

Het sluitkruisje is gewoon een opgeblazen letter 'X'. Deze letter is in sommige browsers iets te groot voor de span, waar hij in staat. Daarom wordt overflow op hidden gezet, waardoor wat niet binnen de span is, niet is te zien. Tekst wordt automatisch in het midden van de regelhoogte gezet.

Deze combinatie, samen met de hierboven opgegeven hoogte en breedte, leveren in alle browsers een acceptabel sluitkruisje op.

border: black solid 1px;

Randje rondom het sluitkruisje. Bij #sluitbalk is div#sluitbalk, waar deze spans in zitten, 38 px omlaag verplaatst. De menubalk is 39 px hoog. Hierdoor valt de border aan de bovenkant weg onder de menubalk, wat ik iets mooier vind.

position: absolute;

Om de sluitkruisjes op de juiste plaats neer te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een absolute, fixed of relatieve positie heeft. Dat is hier #sluitbalk.

Een span is van zichzelf een inline-element. Door de span absoluut te positioneren, verandert deze in een soort blok-element, waardoor je eigenschappen als hoogte en breed kunt gebruiken.

left: 0; Afbeelding 6: sluitkruisje wordt foutief neergezet als inline-element

De spans zijn hierboven in een soort blok-element veranderd door ze absoluut te positioneren. Een 'soort' blok-element. Het wordt namelijk nog neergezet alsof het een inline-element is: achter #sluitbalk. De hoogte is wel goed, want de span staat bovenin #sluitbalk, en die is bij #sluitbalk op de juiste hoogte gezet.

Met left: 0; wordt de span helemaal links in #sluitbalk neergezet.

Er zijn twee spans met 'n sluitkruisje. De tweede wordt hieronder aan de rechterkant neergezet.

.sluiten + .sluiten

Voor dit element geldt ook de bij .sluiten opgegeven css, voor zover die hier niet wordt veranderd.

Een element met class="sluiten" dat gelijk volgt op een ander element met class="sluiten". Er zijn maar twee elementen met class="sluiten": de spans met de sluitkruisjes. Alleen de tweede daarvan voldoet aan deze selector.

left: auto;

Bij .sluiten zijn de spans met left: 0; aan de linkerkant van #sluitbalk neergezet. Deze span met sluikruisje moet aan de rechterkant worden neergezet. Om dat mogelijk te maken moet left terug naar de standaardinstelling auto.

right: 0;

De span en dus het sluitkruisje helemaal rechts in #sluitbalk zetten.

#menu:hover + #sluitbalk

Voor dit element geldt ook de bij #sluitbalk (voor browservensters smaller dan 740 px) en #sluitbalk (voor vensters breder dan 740 px) opgegeven css, voor zover die hier niet wordt veranderd.

#menu is de <nav> waarin het hele menu zit. Bij hoveren over of aanraken van de <nav>, moet iets gebeuren met het in de html gelijk daarop volgende element met id="sluitbalk".

Op deze manier kun je iets laten gebeuren met een element, zonder dat je over dat element zelf hoeft te hoveren of het hoeft aan te raken.

display: block;

Bij #sluitbalk is deze div verborgen, omdat hij geen enkele functie heeft in browservensters smaller dan 740 px. Nu mag hij bij hoveren over of aanraken van de menubalk worden getoond. Hoewel, getoond... Je ziet niets van deze div, hij wordt alleen gebruikt om de erin zittende sluitkruisjes op hun plaats te zetten, gelijk onder de menubalk.

#menubalk-voor-smal

Het element met id="menubalk-voor-smal". Dit is de menubalk die in browservensters smaller dan 740 px bovenaan de pagina staat.

display: none;

In vensters breder dan 740 px heeft deze balk geen enkele functie, dus verbergen.

#content

Voor dit element geldt ook de bij #content opgegeven css, voor zover die hier niet wordt veranderd.

Het element met id="content". Binnen dit element staat de gewone tekst.

max-width: 900px;

Maximumbreedte.

padding: 70px 0 0;

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

Bovenaan een padding van 70 px voor wat afstand tussen tekst en menubalk.

Bij #content is links en rechts een padding van 5 px opgegeven, die is hier niet nodig.

Onderaan geen padding.

margin: 0 auto;

Omdat voor onder en links geen waarde is opgegeven, 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 hetzelfde betekent als evenveel. Ongeacht de breedte van het browservenster staat #content en dus alles erin altijd horizontaal gecentreerd.

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

.kopje

De elementen met class="kopje". Dit zijn de twee vette kopjes in de tekst. Normaal genomen zou ik hier 'n <h> gebruiken, net als voor de naam van de pagina. In dit geval doe ik het wat simpeler, want om nou <h>'s te gaan gebruiken op 'n pagina met zo weinig inhoud...

(Dat 'simpeler' is voornamelijk omdat het er op de site iets anders uit ziet. Als ik hier <h>'s gebruik, worden dat heel andere <h>'s dan die op de site worden gebruikt, en ik houd de code uit de download het liefst zoveel mogelijk hetzelfde als die op de site.)

font-weight: bold;

Vette letter.

margin-bottom: 0;

Van zichzelf heeft een <p> een marge aan boven- en onderkant. Hier wil ik het kopje gelijk boven de tekst laten staan, dus de marge aan de onderkant wordt verwijderd.

.kopje + p

Een paragraaf die gelijk volgt op een element met class="kopje". Dit zijn de <p>'s die gelijk op het vette kopje in de tekst volgen.

margin-top: 0;

Van zichzelf heeft een <p> een marge aan boven- en onderkant. Hier wil ik het kopje gelijk boven de tekst laten staan, dus de marge aan de bovenkant van de direct op het kopje volgende <p> wordt verwijderd.

Speciaal voor Internet Explorer 8

<!--[if IE 8]> <style> @media screen and (min-width: 740px) { #menu li {width: 12.5%;} #menu li + li:before {content: "Pagina\0000a01";} #menu li + li + li:before {content: "Pagina\0000a02";} #menu li + li + li + li:before {content: "Pagina\0000a03";} #menu li + li + li + li + li:before {content: "Pagina\0000a04";} #menu li + li + li + li + li + li:before {content: "Pagina\0000a05";} #menu li + li + li + li + li + li + li:before {content: "Pagina\0000a06";} #menu li + li + li + li + li + li + li + li:before {content: "Pagina\0000a07";} #menu li + li a:after {content: "Ruimte voor informatie over de inhoud van pagina 1";} #menu li + li + li a:after {content: "Ruimte voor informatie over de inhoud van pagina 2";} #menu li + li + li + li a:after {content: "Ruimte voor informatie over de inhoud van pagina 3";} #menu li + li + li + li + li a:after {content: "Ruimte voor informatie over de inhoud van pagina 4";} #menu li + li + li + li + li + li a:after {content: "Ruimte voor informatie over de inhoud van pagina 5";} #menu li + li + li + li + li + li + li a:after {content: "Ruimte voor informatie over de inhoud van pagina 6";} #menu li + li + li + li + li + li + li + li a:after {content: "Ruimte voor informatie over de inhoud van pagina 7";} #menu:hover + #sluitbalk {display: none;} } </style> <![endif]-->

Dit eigenaardige stukje code heet een 'conditional comment' en wordt door alle browsers gezien als commentaar, omdat het tussen <!-- en --> staat. Maar Internet Explorer herkent het, door de extra toevoegingen, als speciaal voor Internet Explorer bedoeld en zal het dus uitvoeren. Het is veiliger dan een zogenaamde 'hack', waarbij vaak gebruik wordt gemaakt van 'n fout (bug) in de browser. Dit is opzettelijk aangebracht door Microsoft en zal dus blijven bestaan, terwijl 'n bug gerepareerd kan worden.

De style voor Internet Explorer moet ná de normale komen, omdat de opdrachten voor Internet Explorer dan over de normale heen gaan.

Dit stukje geldt voor Internet Explorer 8, maar je kunt het ook voor andere versies aangeven. Met ingang van versie 10 van Internet Explorer werken conditional comments niet meer.

In plaats van de style kun je ook 'n normale link naar 'n extern css-bestand aanbrengen:

<!--[if IE 8]> <link rel="stylesheet" href="../../css/naam‑van‑ie‑stylesheet.css"> <![endif]-->

Op de plaats van "../../css/naam-van-ie-stylesheet.css" vul je pad naar en naam van jouw stylesheet voor Internet Explorer 8 in. De css voor Internet Explorer 8 komt dan apart in die stylesheet te staan, zodat het de andere browsers niet stoort.

Het is belangrijk dat de spaties in <!--[if IE 8]> en <![endif]--> precies zo worden overgenomen, zoals ze hier staan.

De toevoeging type="text/css" bij <style> of <link> is bij html5 niet meer nodig, omdat dit de standaardinstelling is.

@media screen and (min-width: 740px)

Dit technische pareltje van Microsoft kan niet uit de voeten met een aantal selectors. Daarom krijgt deze browser wat eigen css. Omdat die selectors alleen worden gebruikt in browservensters breder dan 740 px, is die eigen css ook alleen bedoeld voor die vensters.

Daar zorgt deze regel voor. Verdere uitleg bij @media screen and (min-width: 740px).

#menu li

Alle lijst-items binnen het element met id="menu". Dit zijn de <li>'s waarbinnen de links van het menu zitten.

width: 12.5%;

Bij #menu li:nth-child(even) en #menu li:nth-child(odd) hebben de <li>'s afwisselend een breedte van 12 en 13% gekregen, om in een aantal browsers afrondingsfouten door het gebruik van decimalen te voorkomen.

Internet Explorer kent die afrondingsfouten niet, dus de <li>'s kunnen een breedte van 12,5% krijgen. Omdat er acht <li>'s zijn, is dat samen 100%, de volle breedte van de menubalk.

Hiermee wordt gelijk het gebruik van de pseudo-class nth-child() omzeild. Dat is nodig, omdat Internet Explorer 8 die selector niet kent.

#menu li + li:before {content: "Pagina\0000a01";} #menu li + li + li:before {content: "Pagina\0000a02";} #menu li + li + li + li:before {content: "Pagina\0000a03";} #menu li + li + li + li + li:before {content: "Pagina\0000a04";} #menu li + li + li + li + li + li:before {content: "Pagina\0000a05";} #menu li + li + li + li + li + li + li:before {content: "Pagina\0000a06";} #menu li + li + li + li + li + li + li + li:before {content: "Pagina\0000a07";}

Bij alle andere browsers wordt bij #menu li:nth-child(2):before t//m #menu li:nth-child(8):before voor de tweede tot en met achtste <li> een tekst opgegeven. Internet Explorer 8 kent nth-child() niet. Daarom wordt hier in plaats van li:nth-child(2) (de tweede <li>) li + li gebruikt. Het is Microsoft namelijk wel gelukt om Internet Explorer 1 + 1 op te laten tellen. En niet alleen dat is gelukt, nee, 1 + 1 levert zelfs de juiste uitkomst op: 2. Dit lukt zelfs tot wel 8! In plaats van li:nth-child(2), de tweede <li>, wordt hier dus <li> + <li> gebruikt. Wat hetzelfde betekent. Je komt er dus wel, alleen wordt het bij acht <li>'s wat lang...

Voor de rest is dit hetzelfde als bij de algemene css, waar de rest van het verhaal staat.

Er bestaan polyfills om Internet Explorer 8 te laten werken met selectors zoals :nth-child(), onder andere selectivizir.js, maar die werken niet in combinatie met :before en :after.

#menu li + li a:after {content: "Ruimte voor informatie over de inhoud van pagina 1";} #menu li + li + li a:after {content: "Ruimte voor informatie over de inhoud van pagina 2";} #menu li + li + li + li a:after {content: "Ruimte voor informatie over de inhoud van pagina 3";} #menu li + li + li + li + li a:after {content: "Ruimte voor informatie over de inhoud van pagina 4";} #menu li + li + li + li + li + li a:after {content: "Ruimte voor informatie over de inhoud van pagina 5";} #menu li + li + li + li + li + li + li a:after {content: "Ruimte voor informatie over de inhoud van pagina 6";} #menu li + li + li + li + li + li + li + li a:after {content: "Ruimte voor informatie over de inhoud van pagina 7";}

Dit zijn aanpassingen voor #menu li:nth-child(2) a:after tot en met #menu li:nth-child(8) a:after uit de algemene css. Het verhaal is exact hetzelfde als hier gelijk boven, maar nu met :after in plaats van :before.

#menu:hover + sluitbalk {display: none;}

Bij hoveren over of aanraken van de menubalk moeten de sluitkruisjes worden getoond. De rest van het verhaal staat bij #menu:hover + sluitbalk.

Omdat Internet Explorer 8 het geestig vindt de sluitkruisjes helemaal bovenaan de pagina te zetten, wordt #sluitbalk en dus de daarin zittende spans met de sluitkruisjes gewoon helemaal niet getoond. Deze sluitkruisjes zijn alleen nodig voor iOS, dus het niet tonen is geen enkel probleem.

Html5-elementen en Internet Explorer 8

Tegen de standaard in kun je in Internet Explorer 8 (en ouder) geen css gebruiken bij onbekende elementen. Volgens de standaard hoort de browser niets te doen met een onbekend element, maar moet je er wel css aan toe kunnen kennen. Microsoft wist dit weer 'ns beter en de gevolgen daarvan zullen nog jaren blijven spelen.

In dit voorbeeld wordt het voor Internet Explorer 8 onbekende html5-element <nav> gebruikt. De css voor dit element zou dus niet werken in Internet Explorer 8.

Maar als je via JavaScript dit element eerst even 'voorstelt' aan de browser, blijkt het plotsklaps wél herkend te worden. En kan dus gewoon css voor dit element worden gebruikt. (In feite wordt het element aan de DOM toegevoegd, een soort inhoudsopgave van onder andere alle html-elementen in een pagina.)

Internet Explorer 9 kent <nav> wel, dus hier speelt dit probleem niet meer. (Internet Explorer 9 herkent trouwens, zoals het hoort, ook onbekende elementen, zodat je daar hoe dan ook css en zo bij kunt gebruiken.)

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

Het eigenlijke JavaScript is heel kort en simpel. Voor dit voorbeeld kun je in de <head> het volgende neerzetten:

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

Deze code geldt alleen voor Internet Explorer 8. Uitleg zie bij Speciaal voor Internet Explorer 8.

<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.

Het eigenlijke JavaScript bestaat uit:

document.createElement("nav");

Door het toevoegen van zo'n regel voor een onbekend element, kan dat element nu gewoon worden gebruikt in Internet Explorer 8.

Dit JavaScript is uiterst beperkt: alleen het hier gebruikte html5-element <nav> wordt 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 8 het JavaScript op html5shiv te gebruiken. Dit script herkent veel meer nieuwe html5-elementen dan alleen <nav>. Voordeel van dit uitgebreidere script is ook, dat standaard-instellingen als display: block; bij bijvoorbeeld <header> (hier niet gebruikt) ook al worden doorgegeven aan Internet Explorer 8, zodat die niet in de css hoeven.

Het gebruik van JavaScript betekent helaas ook dat de css in Internet Explorer 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 8 (of ouder) 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> en dergelijke door een gewone <div> moeten vervangen.

Een andere mogelijkheid is het gebruik van <noscript>, zoals ik op de site heb gedaan. Meer hierover kun je gelijk hieronder vinden bij Media queries en Internet Explorer 8.

Media queries en Internet Explorer 8

In css3 zijn de @media-regels fors uitgebreid. Met behulp van @media kunnen nu dingen als de breedte en hoogte van het browservenster worden opgevraagd. Afhankelijk van het resultaat kan dan bepaalde css juist wel of juist niet worden gebruikt.

Helaas kan Internet Explorer 8 (en ouder) hier niet mee overweg, en omdat Microsoft bestaande browsers nooit update (op veiligheidsupdates na), zal dit ook niet veranderen. Wat Microsoft kennelijk niet kan, heeft een aantal programmeurs zelf dan maar geprobeerd voor elkaar te krijgen. Met behulp van JavaScript kan ook deze browser gebruik maken van media queries.

Helemaal probleemloos werkt dit bepaald niet. Omdat de code van deze browser geheim is en er bergen afwijkingen en bugs in zitten, werkt dit JavaScript ook niet altijd, of soms zelfs helemaal niet.

Er zijn twee veel gebruikte JavaScripts om media queries te kunnen gebruiken: css3-mediaqueries-js en respond.js. Als de ene niet probleemloos of helemaal niet werkt, wil de andere nog wel 'ns werken. Hieruit blijkt weer dat je de roestbakken die Microsoft abusievelijk browser noemt, uiterst goed moet testen.

In dit voorbeeld wordt css3-mediaqueries.js gebruikt.

In de <head> staat het volgende stukje code:

<!--[if IE 8]> <script src="012-files-dl/css3-mediaqueries.js"></script> <![endif]-->

Deze code geldt alleen voor Internet Explorer 8. Uitleg zie bij Speciaal voor Internet Explorer 8.

De toevoeging type="text/javascript" bij <script> is bij html5 niet meer nodig, omdat dit de standaardinstelling is.

.css3-mediaqueries.js is het in de download bijgesloten JavaScript, dat ervoor zorgt dat Internet Explorer 8 met media queries uit de voeten kan.

Omdat dit soort scripts regelmatig wordt bijgewerkt, is het uitermate belangrijk dat je zelf dit script ophaalt van css3-mediaqueries-js en niet gewoon het script uit de download gebruikt.

Het gebruik van JavaScript betekent helaas ook dat de css in Internet Explorer 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 8 (of ouder) gebruiken. Dus het aantal mensen waarbij in deze verouderde browsers JavaScript uit zal staan, is waarschijnlijk te verwaarlozen.

Een andere mogelijkheid is het gebruik van <noscript>, zoals ik op de site heb gedaan. Dit moet dan alleen voor Internet Explorer 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 IE 8]> <noscript> <div style="border: dotted red 10px; padding: 5px; background: white;"> Helaas, deze pagina werkt niet goed 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 Microsoft en installeer 'n échte browser zoals Firefox, Google Chrome of Opera. </div> </noscript> <![endif]-->

Los van dat deze browser bij <noscript> alleen css binnen 'n inline-style kan verwerken, moet ook nog 'n extra <div> worden gebruikt. Als je de style met <noscript style="..."> zou aangeven, wordt een deel van de inhoud van <noscript> altijd getoond in Internet Explorer 8, ook al staat JavaScript aan.

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 screenreader gebruiken, of voor motorisch gehandicapte mensen die moeite hebben met het bedienen van een muis. Een spider van een zoekmachine (dat is het programmaatje dat de site indexeert voor de zoekmachine) is te vergelijken met een blinde. Als je je site goed toegankelijk maakt voor gehandicapten, is dat 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 16 juli 2013.

Onder dit kopje staat alleen maar, hoe en waarin is getest. Eventuele problemen, ook die met betrekking tot zoomen en lettergroottes, staan hieronder bij Bekende problemen. Het is belangrijk dat te lezen, want uit een test kan ook prima blijken dat iets totaal niet werkt!

Eventuele opmerkingen over de toegankelijkheid specifiek voor dit voorbeeld staan onderaan Toegankelijkheid en zoekmachines onder het kopje Specifiek voor dit voorbeeld.

Dit voorbeeld is getest op de volgende systemen:

Er is steeds getest met de laatste versie van de browsers op de hierboven genoemde controledatum, 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 resoluties groter dan 800x600 is ook in- en uitzoomen en - voor zover de browser dat kan - een kleinere en grotere letter getest. Er is ingezoomd en vergroot tot zover de browser kan, maar niet verder dan tot 200%.

Er is getest met behulp van muis en toetsenbord, behalve op de iPad en Android, waar een touchscreen is gebruikt. Op Windows 8 is zowel met een touchscreen als met een combinatie van toetsenbord en touchpad getest.

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. (NVDA is getest in combinatie met Firefox.) 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 specifiek voor 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 'n Blackberry. De kans is (heel erg) groot dat dit voorbeeld niet (volledig) werkt op niet-geteste systemen en apparaten. Om het wel (volledig) werkend te krijgen, zul je vaak (kleine) wijzigingen en/of (kleine) aanvullingen moeten aanbrengen, bijvoorbeeld met JavaScript.

Er is ook geen enkele garantie dat iets werkt in een andere tablet of smartphone dan hierboven genoemd, omdat fabrikanten in principe de software kunnen veranderen. Dit is anders dan op de desktop, waar browsers altijd (vrijwel) hetzelfde werken, zelfs op verschillende besturingssystemen. Iets wat in Android browser werkt, zal in de regel overal werken in die browser, maar een garantie is er niet. De enige garantie is het daadwerkelijk testen op een fysiek apparaat. En aangezien er duizenden mobiele apparaten zijn, is daar eigenlijk geen beginnen aan.

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

Bekende problemen

Waarop en hoe is getest, kun je gelijk hierboven vinden bij Getest in.

Als je hieronder geen oplossing vindt voor een probleem dat met dit voorbeeld te maken heeft, kun je op het forum proberen een oplossing te vinden voor je probleem. Om forumspam te voorkomen, moet je je helaas wel registreren, voordat je op het forum een probleem kunt aankaarten.

Deze lijst is behoorlijk lang, maar dat komt voornamelijk omdat ik hem zo volledig mogelijk probeer te krijgen. De meeste problemen zijn onbelangrijke details.

De css valideert niet

Er worden drie eigenschappen gebruikt die (nog) niet valideren. Omdat precies bekend is, waarom de css niet valideert, lijkt dat me in dit geval geen enkel probleem. Valideren is alleen een hulpmiddel, het zou geen doel op zichzelf moeten zijn.

  • Door het gebruik van @-webkit-keyframes valideert de css niet. @keyframes zou wel worden gevalideerd, maar deze regel is alleen nodig voor 'n aantal oudere op webkit gebaseerde browsers, dus het is 'n beetje al te dogmatisch om alleen voor het valideren alle browsers met deze regel op te zadelen.
  • Door het gebruik van -ms-user-select valideert de css niet. user-select wordt door alle browsers herkend, als het juiste bij de browser horende voorvoegsel (zoals -ms-) wordt gebruikt. Maar het is geen onderdeel van een standaard. Omdat het al door alle browsers wordt herkend, zal het vermoedelijk over niet al te lange tijd wel onderdeel van een of andere css-module zijn.

    Omdat het hier alleen nodig is voor Internet Explorer 10 op een touchscreen, gebruik, ik alleen de vorm met -ms-.

  • De tekst die in de menubalk staat wordt met behulp van content gegenereerd. Diezelfde tekst staat echter ook binnen de links. De meeste screenreaders en dergelijke lezen gegenereerde tekst niet, dus meestal zal het niet dubbel worden voorgelezen. Voor de zekerheid staat bij de gegenereerde tekst in de lijst-items speak: none;. Dit wordt echter nog niet gevalideerd. De meeste screenreaders en dergelijke herkennen het ook nog niet.

Gebruik van de muis en klikken

De links worden pas bij hoveren over 'n knop binnen de knop geplaatst, met een vertraging van 0,24 seconde. In theorie kun je binnen die 0,24 seconde al klikken, waardoor je niet op een link klikt. Want die staat er nog niet. Bij uitproberen bleek het vrijwel onmogelijk binnen die 0,24 seconde te klikken. Je moet echt in 'n soort jachthouding gaan zitten, het vangen van 'n vlo is makkelijker.

Kiertje rechts van menubalk in sommige browsers in vensters smaller dan 900 px

In browservensters smaller dan 900 px moet de menubalk het hele venster vullen. Door afrondingsverschillen blijft echter rechts van de menubalk een miniem kiertje open in sommige browsers. Dit gebeurt op Android 4.03. in Android browser, Chrome voor mobiel en Opera (maar niet in de nieuwe op Blink gebaseerde versie van Opera); op iOS in Opera, Chrome for iOS en Safari; op linux in Opera; op OSX in Safari; op Windows 7 in Opera; op Windows XP in Opera.

Alle browsers: tekst kopiëren uit pop-up kan niet

In bredere browservensters verschijnt bij hoveren over of aanraken van een knop een pop-up met extra info. Deze tekst wordt getoond met behulp van de css-eigenschap content. Hierdoor kan deze tekst niet worden gekopieerd. (In 'n enkele browser kán het wel, maar gaat het zo lastig, dat kopiëren alleen geschikt is voor masochisten die met succes de vervolgcursus voor gevorderden hebben gevolgd.)

Safari en Google Chrome bij gebruik van Tab-toets om van link naar link te gaan

Als je de Tab-toets gebruikt om van link naar link te gaan, wordt de link gelijk binnen de knop gezet, zonder vertraging van 0,24 seconde. Zou die vertraging er wel zijn, dan duurt het heel even voor je kunt zien, welke link focus heeft, en dat is wat verwarrend. Zelfs bij zo'n korte vertraging.

Om dit voor elkaar te krijgen wordt bij :focus voor left de waarde auto gebruikt. Volgens de standaard hoort transition niet te werken bij de waarde auto, waardoor er geen vertraging is. Safari en Google Chrome vertragen toch, waardoor het in deze browsers even duurt voor je ziet welke link focus heeft (om precies te zijn: 0,24 seconde).

Dit speelt alleen op de desktop, want alleen daar wordt de Tab-toets hiervoor gebruikt. Voor Firefox, Opera en de bureaublad-versie van Internet Explorer 10 op Windows 8 moet left bij transition staan, anders vertragen ook deze.

Android browser 4.0.3

Normaal genomen kan ook in deze browser de bestemming van een link worden gekopieerd. Door de link iets langer aan te raken, opent een contextueel menu met onder andere deze mogelijkheid. Door de gebruikte constructie kan in deze browser de link niet worden gekopieerd.

Internet Explorer 8

  • Internet Explorer 8 kent de pseudo-class :checked niet. Deze pseudo-class wordt alleen gebruikt in browservensters smaller dan 740 px. Omdat deze versie van Internet Explorer niet of nauwelijks nog op dit soort kleine (mobiele) apparaten voorkomt, heb ik geen polyfill gebruikt.

    In een 1280 px breed venster speelt dit probleem ook, als je zoomt tot meer dan 150%. De menubalk verdwijnt dan, maar het menu voor smalle vensters werkt niet.

    Als je dit wel wilt laten werken, kun je op de pagina met links onder CSS → Bugs en hacks → Dingen mogelijk maken specifiek voor Internet Explorer links naar polyfills hiervoor vinden.

  • Bij hoveren over de menubalk wordt de tekst niet onderstreept. Omdat dit niet echt heel belangrijk is en omdat Internet Explorer 8 ook een aflopende zaak is, heb ik dit niet echt geprobeerd op te lossen.
  • De pop-ups en de menubalk hebben geen ronde hoeken, omdat Internet Explorer 8 border-radius niet kent. Als je wel ronde hoeken wilt, kun je op de pagina met links onder CSS → Bugs en hacks → Dingen mogelijk maken specifiek voor Internet Explorer links naar polyfills hiervoor vinden.
  • Als je de lettergrootte verandert, terwijl de pagina al op het scherm staat, krijgt de tekst die met behulp van content wordt gegenereerd pas na herladen van de pagina de nieuwe lettergrootte.

Internet Explorer 8 en 9

  • Deze browsers kennen geen gradiënten. Daarom hebben ze, waar gradiënten worden gebruikt, een egale achtergrondkleur. Gradiënten worden overigens alleen in browservensters smaller dan 740 px gebruikt. Als je toch gradiënten wilt gebruiken in deze browsers, kun je met de gradiënt generator op colorzilla.com een zogenaamd filter aanmaken voor deze browsers.
  • Pas versie 10 van Internet Explorer kent transition. Bewegingen gaan daardoor niet geleidelijk, maar in één keer. Op de pagina met links kun je onder CSS → Bugs en hacks → Dingen mogelijk maken specifiek voor Internet Explorer links naar polyfills hiervoor vinden.

Internet Explorer 8, 9 en 10 (bureaublad-versie)

Bij een grotere letter (niet bij zoomen) is de pop-up iets breder dan de bijbehorende knop. Hierdoor steekt hij aan de rechterkant iets uit.

Opera

In Opera op Android 4.0.3 en in alle versies van Opera op de desktop werkt transition niet in combinatie met content. Hierdoor openen de pop-ups in één keer.

Opera is voor de weergave-machine aan het overstappen van Presto naar Blink. Voor Android is de nieuwe versie al klaar. In de nieuwe versie met Blink werkt transition in combinatie met content wel. Ik neem aan dat het dus binnenkort in elke versie van Opera werkt.

Opera Mini

In Opera Mini op iOS wordt bij klikken op een link de nieuwe pagina wel geopend, maar deze staat om een of andere duistere reden volledig links buiten het scherm. Hij is door vegen wel op het scherm te zetten, maar je weet helemaal niet dat er iets links buiten het scherm staat. Dit maakt deze constructie feitelijk onbruikbaar in Opera Mini op iOS.

Opera Mini op Android 2.3.6 werkt wel, hoewel gradiënten en dergelijke missen.

Safari op iOS en OSX en Chrome for iOS

transition in combinatie met content werkt niet. Hierdoor openen de pop-ups in één keer.

Safari op OSX en Firefox op de desktop bij andere lettergrootte

Alleen in Safari op OSX en Firefox op de desktop kun je de tekst zo sterk verkleinen en vergroten, dat onderstaande problemen zich kunnen voordoen. In andere browsers speelt dit dus niet.

  • Als de letters worden verkleind tot minder dan 70%, valt een deel van de pop-up weg achter de menubalk. Dit speelt niet bij zoomen, alleen bij een kleinere lettergrootte. Kleiner dan 70% is érg klein, dus ik vond dit niet de moeite waard om naar 'n oplossing te zoeken.
  • Als de letters tot 120% of meer worden vergroot, ontstaat er een kier(tje) tussen menubalk en pop-up. Bij zoomen speelt dit niet.
  • Als de letters tot meer dan 170% worden vergroot, past de tekst van de links niet meer binnen de knop. Hierdoor kan het laatste deel van de tekst onder de knop rechts ervan komen te staan, waardoor dit niet meer is te lezen. Bij zoomen speelt dit niet.

Wijzigingen

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

:

Nieuw opgenomen.

10 augustus 2008:

Bij Bekende problemen stukje over verdwijnende letters bij vergroten lettergrootte toegevoegd.

4 oktober 2008:

Bij Bekende problemen tekst over Internet Explorer 7 en zoomen toegevoegd.

6 april 2009:

Tekst aangepast aan de nieuw verschenen Internet Explorer 8. De code is hetzelfde gebleven.

16 juli 2013:

De code en de tekst zijn volledig herschreven. Daarom is er geen beginnen aan alle wijzigingen hier te noteren. Een samenvatting: