Skip links en inhoudsopgave

Uitleg menu voor kinderen met tekening en pop-ups. Elk puzzelstukje is een link

Laatst aangepast: .

Afbeelding 1: menu in de vorm van een puzzel

Korte omschrijving

Achter elk puzzelstukje zitten een link naar een andere pagina en een – voor (de meeste) kinderen – grappige pop-up. Link en pop-up worden pas zichtbaar bij hoveren over of aanraken van een puzzelstukje.

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.

Alle code is geschreven in een afwijkende lettersoort en -kleur. De code die te maken heeft met de basis van dit voorbeeld (essentiële code), is in de hele uitleg onderstippeld blauw. Alle niet-essentiële code is bruin. (In de inhoudsopgave staat alles in een gewone letter vanwege de leesbaarheid.)

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

Boven een afbeelding van een puzzel wordt een ongeordende lijst <ul> geplaatst. Elk lijst-item <li> binnen die <ul> wordt even groot gemaakt als een puzzelstukje. Hierdoor ontstaat een rooster, waarvan elk vakje precies één puzzelstukje bestrijkt.

Binnen elke <li> staat een link naar een achterliggende pagina. (Ik overdrijf: dat geldt maar voor vier <li>'s, want de andere acht zijn nooit afgemaakt.) Gelijk na deze link staat een <span>, waarbinnen een pop-up staat. Link en pop-up zijn normaal genomen niet zichtbaar. De <span> wordt op verschillende manieren verborgen, de <a> wordt links buiten het scherm geparkeerd. Omdat de <a> gewoon aanwezig is, kunnen schermlezers en dergelijke de links gewoon voorlezen.

Als er over de <li> wordt gehoverd of als deze wordt aangeraakt, opent de in de <li> zittende <span> met de pop-up. Als je de Tab-toets gebruikt om van link naar link te gaan, verschijnt de bij de <a> horende <span> met pop-up, zodra de de <a> focus heeft. Ook de <a> zelf verschijnt, zodra deze focus heeft. De <a> ziet eruit als een knop.

Deze beschrijving is tamelijk simpel, de praktische uitwerking was wat lastiger, omdat elk systeem z'n eigen geniale allerbeste fantastische manier heeft om hover en dergelijke af te handelen. Bovendien blijkt Internet Explorer nogal van slag te raken, als er een afbeelding in de pop-up zit. Voor elke pop-up moest een eigen oplossing worden gevonden, want geen enkele oplossing werkte voor elke pop-up. iOS is een geval apart, want dat systeem begint te niezen als het 'hover' hoort. Daar was dus weer een andere oplossing voor nodig met een minieme hoeveelheid JavaScript.

Kortom: zodra je met pop-ups gaat werken en geen JavaScript wilt gebruiken (of althans zo weinig mogelijk), dan is uitgebreid testen op verschillende systeem absoluut noodzakelijk. Alsmede het in bezit hebben van een ruime hoeveelheid scheldwoorden, kalmerende middelen, alcohol en huisgenoten of op z'n minst huisdieren om de schuld te kunnen geven.

De voorvoegsels -moz-, -ms- 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-.

(Google Chrome is van webkit overgestapt op een eigen weergave-machine: blink. Blink zou geen voorvoegsels gaan gebruiken. Het is echter een aftakking van webkit, dus het zal nog wel even duren voor -webkit- hier helemaal uit is verdwenen. Ook Opera gebruikt inmiddels Blink, inclusief het daar nog in gebruikte -webkit-. Hierdoor is het tot voor kort door Opera gebruikte voorvoegsel -o- niet meer nodig.)

Internet Explorer: -ms-, naar de maker: Microsoft.

In dit voorbeeld worden hyphens, linear-gradient, transform en transition-delay 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 Android browser herkent -webkit-linear-gradient. Zodra Android browser 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.

hyphens

Op dit moment moet je nog het volgende schrijven:

{-moz-hyphens: ...; -ms-hyphens: ...; -webkit-hyphens: ...; hyphens: ...;}

In de toekomst kun je volstaan met:

{hyphens: ...;}

linear-gradient:

Op dit moment moet je nog het volgende schrijven:

{-webkit-linear-gradient: ...; linear­-gradient: ...;}

In de toekomst kun je volstaan met:

{linear-gradient: ...;}

Internet Explorer 9 kent linear-gradient helemaal niet, die negeert deze regel gewoon.

(De syntax van linear-gradient is nogal fors gewijzigd tijdens de proefperiode. Voor oudere op webkit gebaseerde browsers was er een syntax die begon met -webkit-gradient(linear. Die gebruik ik niet meer, want er zijn steeds minder browsers die die syntax gebruiken. Die krijgen gewoon geen gradiënt.)

transform:

Op dit moment moet je nog het volgende schrijven:

{-ms-transform: ...; -webkit-transform: ...; transform: ...;}

In de toekomst kun je volstaan met:

{transform: ...;}

transition-delay

Op dit moment moet je nog het volgende schrijven:

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

In de toekomst kun je volstaan met:

{transition-delay: ...;}

Inmiddels is de algemene mening dat 'vendor prefixes', zoals ze in het Engels heten, geen groot succes zijn. Eén van de grootste problemen: veel sitemakers gebruiken alleen de -webkit-variant. Daar kwamen ze in het verleden nog mee weg, omdat Apple op mobiel zo'n beetje 'n monopolie had. Inmiddels is dat niet meer zo, maar deze gewoonte bestaat nog steeds. Waardoor 'n site alleen in op webkit georiënteerde browsers goed is te bekijken.

Dit is zo'n groot probleem, dat andere browsers soms de variant met -webkit- ook maar zijn gaan implementeren, naast de standaard. Want als 'n site het niet goed doet in 'n bepaalde browser, krijgt in de regel niet de site maar de browser de schuld.

Voorlopig zijn we echter nog niet van deze voorvoegsels af. Als je ze gebruikt, gebruik dan álle varianten, en eindig met de variant zonder voorvoegsel, zoals die uiteindelijk ooit gebruikt gaat worden. Als je alleen de -webkit-variant gebruikt, ben je in feite 'n onbetaalde reclamemaker voor Apple.

Semantische elementen en WAI-ARIA

Deze twee onderwerpen zijn 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, schermlezers, 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 door 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 schermlezers, 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 schermlezer 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.)

Html5 heeft een aantal nieuwe elementen, die speciaal zijn bedoeld om de opbouw van een pagina aan te geven. In dit voorbeeld wordt hiervan alleen <nav> gebruikt.

Deze tag gedraagt zich als een gewone <div>, maar dan een <div> met een semantische betekenis: navigatie. Hierdoor kunnen schermlezers, zoekmachines, en dergelijke gelijk zien dat hierin links zijn ondergebracht, waarmee je naar andere pagina's en dergelijke kunt gaan.

Omdat <nav> alleen aangeeft dat hierin een of andere vorm van navigatie is ondergebracht, maar niet wat voor navigatie, staat gelijk onder de openingstag <nav> een <h1> De <h1> geeft aan, wat voor soort navigatie hier staat: 'Menu met spelletjes'. Deze <h1> wordt links buiten het scherm geparkeerd, zodat je hem niet ziet. Maar schermlezers en dergelijke lezen de kop gewoon voor, ook al zie je hem niet, zodat duidelijk is wat voor soort navigatie hier staat.

In het voorbeeld staat maar één soort navigatie, maar bijvoorbeeld op de site staat niet alleen het puzzelmenu, maar ook de navigatie voor de site zelf. Door op de site beide <nav>'s van een verborgen kop te voorzien, kunnen schermlezers en dergelijke achterhalen, om welke navigatie het gaat.

(Normaal genomen zul je hier geen <h1> voor gebruiken, maar een <h2> of nog lager. Maar op deze pagina is de <h1> de enige kop.)

Met behulp van dit soort nieuwe semantische elementen kan bijvoorbeeld een schermlezer in één keer een heel menu passeren en gelijk naar de echte inhoud gaan. Alleen hadden deze nieuwe elementen tot voor kort één probleem: ze hadden in de praktijk nog weinig nut, omdat schermlezers en dergelijke ze nog niet herkenden. Daarom werd een zogenaamde WAI-ARIA-code toegevoegd aan de <nav>. Dat is een al veel langer bestaande code, die schermlezers en dergelijke wel herkennen. Voor een <nav> ziet dat er zo uit:

<nav role="navigation">

Inmiddels is dit behoorlijk veranderd. Het advies is nu, om deze speciale toevoeging niet meer te gebruiken, omdat de meeste schermlezers en dergelijke een <nav> inmiddels herkennen.

WAI-ARIA-codes

WAI-ARIA wordt vaak ingekort tot ARIA. Voluit betekent het Web Accessibility Initiative – Accessible Rich Internet Applications.

Er worden in dit voorbeeld twee WAI-ARIA-codes gebruikt: aria-hidden en aria-label.

aria-hidden

Met behulp van aria-hidden="true" kan een deel van de code worden verborgen voor schermlezers en dergelijke, zodat dit niet wordt voorgelezen. Op de normale weergave op het scherm heeft dit verder geen enkele invloed.

In dit geval kunnen de pop-ups nogal verwarrend zijn, als ze worden voorgelezen. Bij het negende stukje over de mail bijvoorbeeld kun je gelijk zien, dat het om een steeds herhaalde tekst gaat, die steeds kleiner wordt. En zie je ook gelijk dat je een e-mail kunt versturen.

Een schermlezer echter leest die tekst volledig voor, en van een eindeloos herhaalde tekst worden mensen waarschijnlijk niet gelukkiger. Om die reden wordt de tekst van de eerste en negende pop-up (de krokodil en de mail) verborgen. Van de tweede pop-up worden de dansende letters verborgen. Bij alle drie gebeurt dit met de volgende code :

<span aria-hidden="true">

Hiermee wordt de inhoud van de <span>, de pop-up, verborgen.

Bij de zesde pop-up, de uitgang, is er geen <span>. De afbeelding wordt daar verborgen met:

<img src="014-pics/menu-014-uitgang.jpg" width="260" height="125" alt="Afbeelding 2: " aria-hidden="true">

In principe is alt="" al voldoende, omdat daarmee wordt aangegeven dat het om een onbelangrijke afbeelding gaat, maar sommige schermlezers en dergelijke geven dan toch nog aan dat hier een afbeelding staat. (In ieder geval in het verleden was dat zo.) Dus voor de zekerheid wordt hier ook aria-hidden="true" toegevoegd aan de <img>.

aria-label

De links worden niet verborgen voor schermlezers, dus deze worden gewoon voorgelezen. Alleen is de tekst van de links niet overal even duidelijk, omdat deze wat speels is (of in ieder geval is dat speelse geprobeerd...).

De tekst in de eerste link is voor iedereen wat vreemd: 'Ja! Krokodillen aaien! Leuk!' Of je nou kunt zien of niet. Dus dat wordt niet aangepast.

Hetzelfde geldt voor de tekst van de tweede link: Letterdans.

De tekst in de derde link (bij het zesde stukje) is 'Wegwezen!' In combinatie met de afbeelding met 'Uitgang' is dat wel duidelijk, maar zonder die afbeelding niet. Daarom wordt in deze link een aria-label toegevoegd:

<a href="014-files-dl/menu-014-uitgang-dl.html" aria-label="Verlaat dit menu">Wegwezen!</a>

Afhankelijk van schermlezer en instellingen wordt nu 'Verlaat dit menu' gebruikt, wat duidelijker is dan 'Wegwezen!'

In de vierde link, bij het negende stukje) is de tekst van de link 'E-mail'. Ook dat is mogelijk niet duidelijk, daarom wordt ook hier een aria-label toegevoegd:

<a href="014-files-dl/menu-014-mail-dl.html" aria-label="Stuur ons een mail">E&#x2011;mail</a>

Nu is duidelijk dat het om het versturen van een mail gaat, en niet om lezen of zoiets.

Tabindex

Links, invoervelden in formulieren, en dergelijke kunnen met behulp van de Tab-toets (of een soortgelijke toets) één voor één worden bezocht, in de volgorde waarin ze in de html voorkomen. Shift+Tab-toets keert de volgorde van de Tab-toets om. Dit is een belangrijk hulpmiddel voor mensen die om een of andere reden de muis niet kunnen of willen gebruiken. (En het is vaak ook veel sneller dan de muis, vooral in formulieren.)

In sommige browsers en/of besturingssystemen is dit vreemd genoeg standaard uitgeschakeld en is een zoektocht in de instellingen nodig om dit aan te zetten.

Als je met behulp van de Tab-toets een element hebt bereikt, heeft dit 'focus': als het een link is en je drukt op Enter, wordt de link gevolgd. Bij een tekstveld kun je tekst gaan invoeren. Enz. Normaal genomen wordt focus aangegeven door een lijntje rondom het element dat focus heeft. Bij de links onder de puzzelstukjes worden knop en pop-up zichtbaar, als de link focus heeft. Daarmee is dat lijntje overbodig geworden.

De Tab-toets volgt de volgorde van de elementen in de html. Het maakt niet uit, hoe ze op het scherm staan. Als je met behulp van css de elementen van plaats verwisselt op het scherm, wordt toch gewoon de volgorde in de html gevolgd.

De werking van de Tab-toets kan worden veranderd met behulp van het attribuut tabindex: <div tabindex="3">. Deze <div> zal nu als derde worden bezocht, ook al krijgt een simpele <div> normaal genomen nooit bezoek van de Tab-toets.

Normaal genomen is het gebruik van een tabindex niet nodig. Het is zeker niet bedoeld om de bezoeker als een kangoeroe op een hindernisbaan van onder via links over rechts naar boven te laten springen. Maar soms kan het handig zijn voor kleinere correcties, als de normale volgorde in de html niet optimaal is.

Schermlezers blijven altijd de volgorde van de html volgen, dus als de tabindex sterk afwijkt van de volgorde in de html, kan dat behoorlijk verwarrend zijn.

De tabindex kan drie verschillende waarden hebben: -1, 0 of een positief getal.

In principe is de volgorde bij gebruik van de Tab-toets als volgt: eerst worden alle positieve getallen in volgorde afgewerkt. Als twee tabindexen dezelfde waarde hebben, wordt de volgorde in de html aangehouden. Als alle positieve getallen zijn bezocht, worden daarna tabindexen met '0' bezocht. De '0' zorgt er dus voor dat deze als laatste worden bezocht.

tabindex="-1"

Een negatieve waarde van -1 zorgt ervoor dat het element volledig wordt genegeerd door de Tab-toets. Zelfs een link met een negatieve tabindex wordt volledig genegeerd. Normaal genomen heeft een tabindex="-1" maar één nut: je kunt dan met behulp van JavaScript toch focus aan het element geven, zonder dat gebruikers van de Tab-toets erdoor worden gehinderd.

In dit voorbeeld wordt tabindex="-1" gebruikt bij de vier <li>'s die in gebruik zijn. Voor de eerste <li> ziet dat er als volgt uit:

<li id="een">

Eigenlijk zou dit niet nodig moeten zijn, maar sommige touchscreens reageren vertraagd op een aanraking. Dat is om te kijken of er nog een tweede aanraking volgt (vergelijkbaar met een dubbelklik bij de muis). In dit voorbeeld is dat niet nodig, want er zit maar één 'klik' op de <li>, dus wachten op een mogelijke tweede aanraking is niet nodig.

Maar Internet Explorer 11 op een touchscreen in Windows 8 wacht toch op die tweede aanraking. Daardoor blijft de pop-up pas geopend, als je het scherm iets langer aanraakt. Internet Explorer 11 en UC browser op Windows phone openen de pop-up zelfs helemaal niet. Deze tabindex zorgt dat de pop-up gewoon met één korte aanraking openblijft. Omdat het een negatieve tabindex is, heeft deze verder geen invloed op de volgorde van de Tab-toets.

(In Internet Explorer doet zich het eigenaardige verschijnsel voor dat de tabindex niet nodig is als je geen <ul> met <li>'s gebruikt, maar de pop-up in een <div> onderbrengt. Maar een <ul> voor een menu is makkelijker en toegankelijker, dus dat is geen goede oplossing.)

tabindex="0"

Wordt gebruikt bij de <li>'s die nog geen pop-up en dergelijke hebben:

<li tabindex="0"></li>

Het heeft hier twee functies:

* Sommige mensen kunnen of willen de muis niet gebruiken om links en dergelijke af te lopen, maar gebruiken hiervoor de Tab-toets. Een <li> wordt normaal genomen genegeerd bij gebruik van de Tab-toets. Door tabindex="0" toe te voegen, wordt de link toch bezocht en opent de in de <li> zittende tekst ook bij gebruik van de Tab-toets. Een tabindex met de waarde 0 wordt bezocht na alle andere tabindexen met een positieve waarde. Omdat die hier niet aanwezig zijn. worden alle <li>'s gewoon in volgorde bezocht.

* Het lost een probleem in Internet Explorer op touchscreens in Windows 8, en in Internet Explorer 11 en UC browser op Windows Phone op, zoals gelijk hierboven beschreven bij tabindex="-1".

tabindex="..."

Op de plaats van de puntjes moet een positief getal worden ingevuld: het volgnummer. Er is ruimte voor, afhankelijk van de browser, minimaal 32767 tabindexen, dus daar kun je aardig wat links en dergelijke mee bedienen.

Met behulp van een nummer kan de volgorde van de Tab-toets daadwerkelijk worden gewijzigd. Alle elementen met een tabindex worden in de volgorde van het nummer afgelopen. Elementen zonder tabindex of met tabindex="0" worden bezocht, nadat alle elementen met een positief volgnummer zijn afgewerkt.

Als je dat zou willen, zou je de Tab-toets als eerste naar 'n footer onderaan de pagina kunnen laten gaan, daarna helemaal naar boven en vervolgens naar het midden. En als je toevallig neoliberaal bent en alles in financiële waarde vertaalt, moet je dat vooral doen, want dit levert de fabrikanten van kalmerende middelen, psychiaters, enz. bergen extra werk op en stimuleert dus Sint Economie.

Voor alle niet-neoliberalen: niet doen. De tabindex is bedoeld voor kleine correcties, niet om van je bezoeker een door een jager achtervolgd konijn in een doolhof te maken. Een schermlezer volgt trouwens altijd de volgorde van de html, dus ook voor een schermlezer kunnen grote ingrepen uiterst verwarrend zijn.

Als je de tabindex gebruikt om de volgorde te veranderen, let er dan op dat je dat goed doet. Alle velden in een bestelformulier van een tabindex voorzien, maar dat bij de verzendknop vergeten, helpt niet bij je volgende gesprek over loonsverhoging.

De volgnummers van de tabindex hoeven niet op elkaar aan te sluiten. Het is zelfs beter als dat niet zo is. Lang geleden heb ik 'ns handmatig honderden tabindexen in zitten typen. Netjes op elkaar aansluitend, want tellen kan ik prima. Iets later moest er helemaal aan het begin eentje worden tussengevoegd. Aangezien de nummers zo fantastisch foutloos op elkaar aansloten, moest elk hoger nummer dus handmatig worden veranderd. Volgens mijn therapeut is dit de oorzaak van mijn nog steeds terugkerende angstdromen over genummerde schapen, waar zich plotseling een ongenummerde ram tussen probeert de dringen. Oftewel: zoiets doe je maar één keer.

Het beste is, als de volgorde van de html gewoon ook de meest logische volgorde voor de tabindex is. Dat is hier het geval: een positieve tabindex wordt niet gebruikt.

Muis, toetsenbord, touchpad en touchscreen

Vroeger, toen het leven nog mooi was en alles beter, waren er alleen monitors. Omdat kinderen daar niet af konden blijven met hun tengels, besloten fabrikanten dan maar touchscreens te gaan maken, omdat je die mag aanraken. Het bleek makkelijker te zijn om volwassenen ook te leren hoe je 'n scherm vies maakt, dan om kinderen te leren met hun vingers van de monitor af te blijven.

Zo ontstonden touchscreens en kreeg het begrip ellende een geheel nieuwe lading. In de perfecte wereld van vroeger, waarin alleen desktops bestonden, werkten dingen als hoveren, klikken en slepen gewoon. Zonder dat je eerst 'n cursus hogere magie op Zweinstein hoefde te volgen. Zelfs in JavaScript was het nog wel te behappen, ook voor mensen zoals ik die toevallig niet Einstein heten.

Op dit moment kun je computerschermen ruwweg in twee soorten indelen: schermen die worden aangeraakt, en schermen die worden bediend met hulpmiddelen als een toetsenbord, muis of touchpad. Omdat ook computerschermen zich kennelijk vermengen, bestaan er inmiddels ook schermen die zowel van aanraken als van muizen houden.

Hieronder staat een lijstje met dingen die zijn aangepast voor de verschillende soorten schermen, zodat dit voorbeeld overal werkt.

: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 levert hover niet al te veel problemen op, omdat hover niet wordt gecombineerd met klikken. Bij gebruik van een muis zit er een verschil tussen hoveren en klikken, maar op een touchscreen is dat verschil er niet: je raakt een touchscreen aan of niet.

In de vorige versie van dit voorbeeld waren hover en klikken beide gekoppeld aan de link. Dat leverde op touchscreens enorme problemen op. Was de aanraking bedoeld als 'hover' of als 'klik'? Elk systeem lost dit dilemma op z'n eigen manier op.

In deze versie zijn de hover en de klik van elkaar gescheiden. De hover zit op de <li>, dat opent de <a>, en de klik zit dan op die <a>. Alle touchscreens kunnen de hover nu goed afhandelen: de pop-up en de link openen. Op een touchscreen blijven ze geopend, zodat daarna de link kan worden aangeraakt.

Internet Explorer 11 op een touchscreen en UC browser op Windows Phone leveren problemen op. Bij aanraking van een <li> openen de daarin zittende pop-up en link wel, maar ze sluiten gelijk weer, omdat wordt gewacht op een mogelijke tweede aanraking (wat bij een muis een 'dubbelklik' is). Daardoor moet je in deze browsers het scherm langer aanraken voordat pop-up en link geopend blijven. Door aan de <li> ook een :focus te koppelen, blijven pop-up en link ook in deze browsers gelijk geopend.

Hiervoor moet ook een tabindex="-1" worden gegeven aan de <li>. Meer daarover is te vinden bij Tabindex.

Om hoveren op iOS goed te laten werken, is een minimale hoeveelheid JavaScript nodig. Daarover is meer te vinden bij JavaScript.

: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'. (Over het gebruik van de Tab-toets staat meer bij Tabindex.)

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.

Het kadertje dat de focus aangeeft, moet nooit zonder meer worden weggehaald. Gebruikers van de Tab-toets hebben dan geen idee meer, waar ze zijn. Maar in dit voorbeeld kan het kadertje veilig worden weggehaald, omdat bij focus een knop en een pop-up verschijnen.

Eigenlijk is de focus alleen nuttig bij gebruik van een toetsenbord, maar om een of andere mij niet geheel duidelijke reden reageert iOS er ook op. Als je op 'n element 'n :focus én 'n :hover zet, blijft die :focus op iOS van kracht, tot je 'n andere link, knop, of zoiets aanraakt. Dat is hier het geval bij de <li>'s.

Als je 'n <li> aanraakt, houdt deze dus focus. Tot je 'n andere <li> aanraakt, want dan krijgt die focus. Bij aanraken op een andere plaats sluit de pop-up niet, wat nogal irritant is. Dit is opgelost door onclick="", een klein stukje JavaScript, aan te brengen bij div#wrapper:

<div id="wrapper" onclick="">.

Je kunt daar meer over vinden bij JavaScript.

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

* De links naar de uitgang en voor het sturen naar een mail zijn niet echt duidelijk, als je de bijbehorende pop-ups niet ziet. Daarom hebben deze links met behulp van aria-label aanvullende, duidelijker tekst gekregen. Meer hierover bij WAI-ARIA-codes.

* De pop-ups zijn voor schermlezers verborgen met behulp van aria-hidden, omdat ze zonder afbeeldingen en dergelijke verwarrend zijn. Meer hierover bij WAI-ARIA-codes.

* Gelijk onder <nav> is een buiten het scherm verborgen <h1> aangebracht met daarin een omschrijving van het menu.

* De links zijn ook bereikbaar met de Tab-toets: ze worden één voor één afgelopen. Zodra een link focus heeft, openen bijbehorende pop-up en knop met link.

* Zonder afbeeldingen werkt alles wel, maar het wordt wel lastig, omdat je bijvoorbeeld ook de puzzelstukjes niet ziet.

* Zonder css zijn de links wel zichtbaar, maar de pop-ups ook. Dit is uiterst verwarrend. Maar het lijkt me niet dat mensen die een tekstbrowser zoals Lynx gebruiken, op dit soort menu's zitten te wachten.

* Alleen op iOS wordt wat JavaScript gebruikt. Maar daar is dat JavaScript ook absoluut onmisbaar, omdat de links niet verschijnen zonder JavaScript. Vrijwel niemand zal dat echter uitzetten op iOS, omdat je dan weinig meer hebt aan je (peperdure) smartphone of tablet. Meer over JavaScript bij JavaScript.

Getest in

Laatst gecontroleerd op 23 juli 2015.

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 (en oplossingen). 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 aan het begin van dit hoofdstukje 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.

Ook op Windows XP kunnen mensen surfen met Firefox, Opera of Google Chrome, dus ook daar zijn mensen niet afhankelijk van Internet Explorer 8. Ik maak één uitzondering: Android browser. Omdat Android vaak niet geüpdatet kan worden, test ik ook nog in oudere versies van Android browser.

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

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

Op de desktop is ook getest, als JavaScript uitstaat. Eventuele problemen staan hierboven bij Toegankelijkheid en zoekmachines onder het kopje Specifiek voor dit voorbeeld. (Op iOS, Android en Windows Phone is niet getest zonder JavaScript, omdat je JavaScript in een toenemend aantal mobiele browsers niet uit kunt zetten. Bovendien is een mobiel apparaat zonder JavaScript niet veel meer dan een duur en groot uitgevallen horloge.)

Naast deze 'gewone' browsers is ook getest in Lynx, WebbIE, NVDA, TalkBack en VoiceOver.

Lynx is een browser die alleen tekst laat zien en geen css gebruikt. Er is getest op Linux.

WebbIE is een browser die gericht is op mensen met een handicap. Er is getest op Windows 7.

NVDA is een schermlezer, zoals die door blinden wordt gebruikt. Er is getest in combinatie met Firefox op Windows 7.

TalkBack is een in Android ingebouwde schermlezer. Er is getest in combinatie met Chrome.

VoiceOver is een in iOS en OS X ingebouwde schermlezer. Er is getest in combinatie met Safari op iOS en OSX.

Als het voorbeeld in deze 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 hierboven bij 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 (en oplossingen) 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 (en oplossingen)

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.

Alle browsers

Bij gebruik van de Terug-toets van de browser of Alt+←, blijft de pop-up geopend.

Teruggaan vanuit een hulppagina naar het puzzelmenu kan door op de link te klikken. Maar je kunt ook 'n pagina teruggaan door de Terug-toets van de browser of alt+← te gebruiken. Als je op deze manier teruggaat, houdt de link waarmee je de hulppagina hebt bezocht meestal focus.

Normaal genomen wordt focus aangegeven met een kadertje rondom de link die focus heeft. In dit voorbeeld wordt het aangegeven doordat de pop-up en bijbehorende knop zichtbaar zijn. Die zijn dus ook nog steeds geopend, als je teruggaat met gebruik van de Terug-toets of alt+←. Dit is geen fout of zo, het is de normale werking van focus.

Alleen in alle versies van Google Chrome en UC browser op Windows 7 en en iOS verliest de link ook focus, als je met de Terug-toets of alt+← teruggaat.

Opera Mini

Het werkt niet

Tja, dat is vrij simpel: het werkt gewoon niet. Punt.

Het menu, de puzzel, staat maar voor 'n klein deel binnen het venster van de browser, de rest is onzichtbaar. Dit komt door het gebruik van transform bij het plaatsen van het menu. Opera Mini kent dit niet. Omdat het menu eerst halverwege het venster wordt neergezet met behulp van position, wat Opera Mini wel kent, blijft het hele menu gewoon daar staan: in beide richtingen halverwege het browservenster.

Je zou dat mogelijk nog wel kunnen oplossen, maar ook aanraken werkt niet. Ook dat kun je mogelijk wel oplossen, maar er zijn grenzen. Bovendien is Opera Mini bedoeld om zo snel mogelijk te surfen, waarbij je zo weinig mogelijk data gebruikt. Mensen die dat doen, zijn niet de mensen die een of ander spelletjesmenu bezoeken. En als ze dat toch doen, moeten ze even 'n browser gebruiken die voor dat soort dingen is bedoeld.

In Opera Mini op Android kun je de Weergave in één kolom inschakelen en dan zie je de pop-ups en links. Maar de links zijn niet als link herkenbaar. Persoonlijk denk ik dat deze manier alleen voor De Gevorderde Masochist Met Zelfhaat geschikt is.

Valideren

In de css wordt pointer-events gebruikt. (Niet te verwarren met de JavaScript-specificatie Pointer Events.) Deze eigenschap is in css aan komen waaien vanuit de SVG-specificatie en wordt (nog) niet herkend door de validator, wat een foutmelding oplevert.

Omdat de reden van deze fout bekend is, is dat geen probleem.

Internet Explorer 9

Internet Explorer 9 kent linear-gradient niet en negeert dit. De achtergrond van de knoppen met links is in deze browser geen gradiënt (verlopende kleur), maar effen wit.

Je kunt een gradiënt in Internet Explorer enigszins simuleren met behulp van een gradiënt filter. Dat is een eigen techniek van Microsoft die kan worden gebruikt in oudere versies van Internet Explorer, maar dat vond ik de moeite niet waard.

UC browser en Android browser op Android

Dit speelt alleen in browservensters lager dan 480 px of smaller dan 384 px, de maat van de puzzelafbeelding. In deze kleine vensters wordt div#wrapper met behulp van transform: scaleX() verkleind. De in div#wrapper zittende puzzelafbeelding mag niet buiten div#wrapper (en dus niet buiten het venster van de browser) komen, maar dat gebeurt door een bug ten onrechte wel. Hierdoor valt aan de onderkant een deel van de afbeelding weg.

Alles werkt wel, want de rest van div#wrapper is wel goed geschaald en dergelijke, maar de <li>'s corresponderen niet meer met de eronder zittende puzzelvakjes. Ook andere methodes als een extra (maximum)hoogte, het gebruik van de eenheden vw of vh, het weghalen van breedte en grootte in de html bij de afbeelding, en dergelijke hebben geen effect: de afbeelding blijft groter dan div#wrapper.

Een vaste maat in px opgeven werkt wel, maar dat is geen oplossing, omdat de bedoeling nou juist is dat de afbeelding zich aanpast aan de grootte van het venster van de browser.

Als de smartphone in de portretstand wordt gedraaid, speelt dit probleem niet meer, want dan past de afbeelding binnen het venster en corresponderen <li>'s en puzzelvakjes weer met elkaar. Omdat er in de landschapsstand links en rechts veel lege ruimte is, is het hoe dan ook logischer om het toestel in de portretstand vast te houden, dus 'n echt probleem is dit feitelijk niet.

Wijzigingen

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

:

Nieuw opgenomen.

11 augustus 2008:

De nieuwe zoomfunctie van Firefox 3 sloopte dit menu nogal. Door de veranderingen die hiervoor nodig waren bleek het vergroten/verkleinen van letters ook ineens 'n stuk beter te werken. Tja.

Het volgende is veranderd:

31 maart 2009:

Tekst aangepast aan de nieuw verschenen Internet Explorer 8. De code is niet veranderd.

26 juli 2011:

25 december 2013:

1 augustus 2015:

Inhoud van de download en licenties

De inhoud van deze download kan vrij worden gebruikt, met drie beperkingen:

* Sommige onderdelen die van 'n andere site of zo afkomstig zijn, vallen mogelijk onder een of andere licentie. Dat is hieronder bij het betreffende onderdeel te vinden.

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

* Dit voorbeeld (en de bijbehorende uitleg en dergelijke) wordt regelmatig bijgewerkt. Het is daarom niet toegestaan dit voorbeeld (en de bijbehorende uitleg en dergelijke) op welke manier dan ook te verspreiden, zonder daarbij duidelijk te vermelden dat voorbeeld, uitleg, en dergelijke afkomstig zijn 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.

menu-014-dl.html: de pagina met het menu.

menu-014.pdf: deze uitleg (aangepast aan de inhoud van de download).

menu-014-inhoud-download-en-licenties.txt: een kopie van de tekst onder dit kopje (Inhoud van de download en licenties).

014-css-dl:

menu-014-dl.css: stylesheet voor menu en hulppagina's.

014-files-dl:

menu-missende-letters-dl.zip: niet-gebruikte dansletters (zodat het alfabet compleet is). Deze letters zijn afkomstig van het niet meer bestaande calendarofupdates.com.

menu-014-dansletters-dl.html: hulppagina achter de link bij de dansletters.

menu-014-krokodil-dl.html: hulppagina achter de link bij de krokodil.

menu-014-mail-dl.html: hulppagina achter de link bij de mail.

menu-014-uitgang-dl.html: hulppagina achter de link bij de uitgang.

014-pics:

menu-014-a.gif tot en met, menu-014-c.gif, ..., tot en met menu-014-z.gif: de dansende letters. Deze zijn afkomstig van het niet meer bestaande calendarofupdates.com.

menu-014-ijspret.jpg: afbeelding waaronder het menu zit. De afbeelding komt van karenswhimsy.com/public_domain_images. Het puzzelpatroon is aangebracht met Gimp. De gebruiksvoorwaarden van de afbeelding zijn te vinden op karenswhimsy.com/image-ordering.shtm#terms.

menu-014-krokodil.gif en menu-014-olifant.png: de afbeeldingen met de bewegende krokodil en de (niet-bewegende) olifant. Deze komen van de helaas niet meer bestaande site www.davidpye.com. Het wolkje bij de krokodil is aangebracht met Gimp.

menu-014-mail.gif: de afbeelding van de mailbox komt van de niet meer bestaande site www.hellasmultimedia.com.

menu-014-uitgang.jpg: het plaatje met de uitgang. Ik heb er eerlijk waar geen flauw idee meer van, waar ik dit ooit vandaan heb gehaald. In ieder geval niet van een of ander eng bedrijf met pitbulls en deurwaarders. Maar als je dit dus verder wilt gebruiken, is dat op eigen risico.

HTML

De code is geschreven in een afwijkende lettersoort. De code die te maken heeft met de basis van dit voorbeeld (essentiële code), is in de hele uitleg onderstippeld blauw. Alle niet-essentiële code is bruin. (In de inhoudsopgave staat alles in een gewone letter vanwege de leesbaarheid.)

In de html hieronder wordt alleen de html besproken, waarover iets meer is te vertellen. Een <h1> bijvoorbeeld wordt in de regel niet genoemd, omdat daarover weinig interessants valt te melden. (Als bijvoorbeeld het uiterlijk van de <h1> wordt aangepast met behulp van css, staat dat verderop bij de bespreking van de css.)

Zaken als een doctype en charset hebben soms wat voor veel mensen onbekende effecten, dus daarover wordt hieronder wel een en ander geschreven.

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. Dit kan zonder enig probleem worden gebruikt: het werkt zelfs in Internet Explorer 6.

<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. Deze pagina 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 de al aangepaste pagina 980 px breed is, en verkleint die 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 breedte van de weer te geven tekst en dergelijke passen zich automatisch aan de breedte van het apparaat aan. Er is op deze pagina niets, wat problemen kan opleveren in een smaller browservenster.

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.

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.

<div id="wrapper" onclick="">

Het bijzondere van de html is hier onclick="". Dat stukje is feitelijk JavaScript en staat alleen voor de volledigheid ook hier vermeld. De reden van deze JavaScript-insluiper is te vinden bij JavaScript.

<h1>Menu met spelletjes</h1>

De reden dat de <h1> hier tot de essentiële code wordt gerekend, heeft te maken met toegankelijkheid voor schermlezers en dergelijke. Het menu staat in een <nav> en is daardoor herkenbaar als menu voor schermlezers en dergelijke. Maar daarmee is nog niet duidelijk, om wat voor menu het gaat. Dat staat in deze <h1> omschreven, die gelijk onder de <nav> staat: 'Menu met spelletjes'.

Met behulp van css wordt de <h1> buiten het venster van de browser geplaatst, zodat hij onzichtbaar is. Maar voor een schermlezer maakt dat niet uit: hij wordt gewoon voorgelezen.

Normaal genomen zal dit waarschijnlijk geen <h1> zijn, maar een <h2> of nog lager, omdat normaal genomen zo'n menu niet het eerste onderdeel van een pagina is. Op de site bijvoorbeeld staat in de <h1> de titel van de pagina en wordt voor het aanduiden van dit menu en het menu van de site zelf een <h2> gebruikt.

<li id="...">

tabindex="-1" komt bij meerdere tags voor: de <li>'s waarbij al een pop-up en dergelijke is gemaakt. Deze tags verschillen iets van elkaar, maar de uitleg is overal hetzelfde.

Deze negatieve tabindex is nodig, omdat anders in sommige browsers op een touchscreen de pop-up niet gelijk opent. Meer uitleg over de tabindex is te vinden bij Tabindex.

<span aria-hidden="true">

aria-hidden="true" is een zogenaamde WAI-ARIA-code, gericht op een betere toegankelijkheid voor schermlezers en dergelijke. Deze code verbergt de pop-ups voor een schermlezer. Er is meer over te vinden bij WAI-ARIA-codes.

(Deze regel komt meerdere malen voor, de uitleg is steeds hetzelfde.)

<li tabindex="0"></li>

tabindex="0" staat bij elke <li> die nog geen pop-up en dergelijke heeft. Het verhelpt een probleem bij Internet Explorer op touchscreens en UC browser op Windows Phone. Het zorgt er ook voor dat de link wordt bezocht bij gebruik van de Tab-toets. Meer uitleg is te vinden bij bij Tabindex.

<a href="014-files-dl/menu-014-uitgang-dl.html" aria-label="Verlaat dit menu">Wegwezen!</a>

aria-label="Verlaat dit menu" is een zogenaamde WAI-ARIA-code, gericht op een betere toegankelijkheid voor schermlezers en dergelijke. Omdat 'Wegwezen!', de tekst van de link, nogal onduidelijk is, wordt er extra tekst voor schermlezers en dergelijke toegevoegd. Er is meer over te vinden bij WAI-ARIA-codes.

<img src="014-pics/menu-014-uitgang.jpg" width="260" height="125" alt="Afbeelding 3: " aria-hidden="true">

aria-hidden="true" is een zogenaamde WAI-ARIA-code, gericht op een betere toegankelijkheid voor schermlezers en dergelijke. Deze code verbergt de <img> voor een schermlezer. Er is meer over te vinden bij WAI-ARIA-codes.

<a href="014-files-dl/menu-014-mail-dl.html" aria-label="Stuur ons een mail">E&#x2011;mail</a>

aria-label="Stuur ons een mail" is een zogenaamde WAI-ARIA-code, gericht op een betere toegankelijkheid voor schermlezers en dergelijke. Omdat 'E-mail', de tekst van de link, nogal onduidelijk is, wordt er extra tekst voor schermlezers en dergelijke toegevoegd. Er is meer over te vinden bij WAI-ARIA-codes.

E&#x2011;mail ziet er ietwat Russisch uit, tot je het in stukjes ontleed:

E: gewoon de letter 'E'

&#x2011;: de utf-8-code voor een 'vast koppelteken'. utf-8 is een bepaalde manier om aan te geven welke karakterset een computer moet gebruiken, zodat je veilig bijzondere tekens zoals letters met accenten kunt gebruiken. Dat is bovenaan het document bij <meta charset="utf-8"> gedaan.

2011 is het volgnummer voor een 'vast koppelteken'.

&#x: normaal genomen zou 2011 gewoon als tekst worden weergegeven. Om aan de browser duidelijk te maken dat 2011 een code is, wordt deze combinatie van drie tekens gebruikt.

Afbeelding 2: het woord e-mail over twee regels is geen gezicht

Een 'vast koppelteken' zorgt ervoor dat het deel voor en na het koppelteken altijd op dezelfde regel blijft staan. In sommige browsers wordt anders 'mail' op een nieuwe regel gezet, waardoor 'E-' als een soort mislukte mediterende vuurtoren in eenzaamheid belachelijk staat te wezen, zoals op de afbeelding is te zien.

mail: gewoon het tweede deel van het woordje E-mail.

CSS

De code is geschreven in een afwijkende lettersoort. De code die te maken heeft met de basis van dit voorbeeld (essentiële code) is in de hele uitleg onderstippeld blauw. Alle niet-essentiële code is bruin. (In de inhoudsopgave staat alles in een gewone letter vanwege de leesbaarheid.)

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.

Technisch gezien is er geen enkel bezwaar om de css in de stylesheet allemaal achter elkaar op één regel te zetten:

div#header-buiten {position: absolute; right: 16px; width: 100%; height: 120px; background: yellow;} div p {margin-left 16px; height: 120px; text-align: center;}

Maar als je dat doet, garandeer ik je hele grote problemen, omdat het volstrekt onoverzichtelijk is. Beter is het om de css netjes in te laten springen:


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

        div p {
            margin-left: 16px;
            height: 120px;
            text-align: center;
        }

Hiernaast is het heel belangrijk voldoende commentaar (uitleg) in de stylesheet te schrijven. Op dit moment weet je waarschijnlijk (hopelijk...), waarom je iets doet. Maar over vijf jaar kan dat volstrekt onduidelijk zijn. Op deze site vind je nauwelijks commentaar in de stylesheets, maar dat heeft een simpele reden: deze uitleg is in feite één groot commentaar.

Op internet zelf is het goed, als de stylesheet juist zo klein mogelijk is. Dus voor het uploaden kun je normaal genomen het beste het commentaar weer verwijderen. Veel mensen halen zelfs alles wat overbodig is weg, voordat ze de stylesheet uploaden. Inspringingen bijvoorbeeld zijn voor mensen handig, een computer heeft ze niet nodig.

Je hebt dan eigenlijk twee stylesheets. De uitgebreide versie waarin je dingen uitprobeert, verandert, enz., met commentaar, inspringingen, en dergelijke. Dat is de mensvriendelijke versie. Daarnaast is er dan een stylesheet die je op de echte site gebruikt: een gecomprimeerde versie.

Dat comprimeren kun je met de hand doen, maar er bestaan ook hulpmiddelen voor. Op de pagina met links kun je onder Gereedschap → Snelheid, testen, gzip, comprimeren links naar sites vinden, waar je bestanden kunt comprimeren.

(Stylesheets op deze site zijn niet gecomprimeerd. Omdat het vaak juist om de css gaat, wil ik dat mensen zonder al te veel moeite de css kunnen bekijken.)

css voor alle vensters

/* menu-014-dl.css */

Om vergissingen te voorkomen is het een goede gewoonte bovenaan het stijlbestand even de naam neer te zetten. Voor je het weet, zit je anders in het verkeerde bestand te werken.

/****************** Hulppagina's *****************/

Bij grotere bestanden is het vaak handig een soort 'hoofdstukjes' aan te brengen. Als je zoekt naar meerdere sterretjes, kun je zo van deel naar deel springen, wat vaak nogal wat zoekwerk kan besparen. En kan voorkomen dat je in het verkeerde deel van een bestand gaat zitten werken.

body#hulp

Het element body met id="hulp". Op de vier hulppagina's, die achter de links in het menu zitten, is een kleine hoeveelheid css gebruikt. Die wordt in dit stukje van de stylesheet opgegeven. Als je alleen body gebruikt, zou deze css ook gelden voor de pagina met het menu. Daarom hebben de hulppagina's bij body een id="hulp" gekregen. Nu geldt deze css alleen voor de hulppagina's.

background: #ff9;

Achtergrondkleur.

font-size: 150%;

Grotere letter. Als eenheid gebruik ik procenten, zodat ook gebruikers van Internet Explorer de lettergrootte kunnen veranderen.

text-align: center;

Tekst horizontaal centreren.

body#hulp p:not(:first-child)

De <p>'s die niet het eerste kind zijn op de pagina's met body id="hulp".

body#hulp

Het element body met id="hulp". Op de vier hulppagina's, die achter de links in het menu zitten, is een kleine hoeveelheid css gebruikt. Die wordt in dit stukje van de stylesheet opgegeven. Als je alleen body gebruikt, zou deze css ook gelden voor de pagina met het menu. Daarom hebben de hulppagina's bij body een id="hulp" gekregen. Nu geldt deze css alleen voor de hulppagina's.

:first-child: alleen de elementen die een eerste kind zijn. p:first-child geldt alleen voor bijvoorbeeld:

<div> <p></p> </div>

maar niet voor:

<div> <a></a> <p></p> ​</div>

In het eerste geval is de <p> het eerste kind van de <div>, in het tweede geval is de <a> het eerste kind en de <p> pas het tweede kind.

:not(): dit keert het deel dat tussen de haakjes staat om.

:not(:first-child): alleen de elementen die géén eerste kind zijn.

p:not(:first-child): alles bij elkaar betekent dit dus alleen de <p>'s die geen eerste kind zijn.

Dit is een hele grove selector, maar omdat de hulppagina's heel simpel zijn, kan die hier worden toegepast.

font-size: 80%;

Lettergrootte iets kleiner maken. Iets hierboven is de lettergrootte bij body#hulp op 150% gezet. Hiermee beperk ik dat tot de eerste <p>. Als eenheid gebruik ik procenten, zodat ook gebruikers van Internet Explorer de lettergrootte kunnen veranderen.

De lettergrootte wordt geërfd door de nakomelingen. De <p>'s erven dus in eerste instantie de lettergrootte van 150% van de body. De 80% wordt van die 150% genomen, dus de uiteindelijke lettergrootte wordt 80% van 150%. Dat is 120% van de normale lettergrootte, nog steeds iets groter dan normaal.

body#hulp a

De <a>'s op de pagina's met een body met id="hulp". Dit zijn de links van de hulppagina's terug naar het voorbeeld.

position: static;

Iets verderop bij a worden de links in het voorbeeld opgeleukt tot een heuse knop. Dat is eigenlijk bedoeld voor de puzzel, maar kan op de hulppagina's verder ook geen kwaad. Wat wel kwaad kan: de links worden verderop links buiten het scherm geparkeerd met left: -20000px;. Waarmee ze dus onzichtbaar zijn. Dat is prima in die puzzel, maar hier niet.

left: -20000px; werkt alleen maar, als het element absoluut, relatief of fixed is gepositioneerd. Verderop worden de <a>'s inderdaad absoluut gepositioneerd. Door de <a>'s op de hulppagina's statisch te positioneren, de standaardinstelling, werkt left: -20000px; niet meer op deze links en komen ze gewoon op het scherm te staan.

De css voor alle <a>'s staat verderop. Latere css overrulet normaal genomen eerdere css. Maar hier niet, omdat door het gebruik van body#hulp de selector hier meer gewicht, meer specificiteit, heeft dan de lager staande selector, die alleen uit a bestaat. Zou je ook hier alleen a gebruiken, dan zou dit niet werken, omdat dan de lager staande css deze zou overrulen en ook deze <a>'s absoluut gepositioneerd zouden worden. En dus ook links buiten het scherm geparkeerd zouden worden.

/***************** Puzzel ************************/

Bij grotere bestanden is het vaak handig een soort 'hoofdstukjes' aan te brengen. Als je zoekt naar meerdere sterretjes, kun je zo van deel naar deel springen, wat vaak nogal wat zoekwerk kan besparen. En kan voorkomen dat je in het verkeerde deel van een bestand gaat zitten werken.

html

Het element <html>. Dat is het allerbuitenste element.

height: 100%;

Het menu moet horizontaal en verticaal worden gecentreerd binnen het browservenster. Horizontaal is dat vrij simpel, verticaal is het iets lastiger.

Om het menu verticaal te kunnen centreren, moet de hoogte van het venster bekend zijn. Als je immers niet weet, hoe hoog iets is, kun je iets anders niet in het midden van die onbekende hoogte zetten.

Browservensters kunnen allerlei hoogtes hebben, van smartphones tot enorme monitors. Gelukkig hoef je niet de exacte hoogte te weten om te kunnen centreren. Centreren kan ook prima met percentages. Als je een site maakt, weet je de hoogte van het venster niet. Maar de browser weet dit, bij het daadwerkelijk weergeven van de site, wel. De browser kan daardoor de opgegeven percentages bij het vertonen omrekenen naar 'echte', absolute afstanden.

Als je niets speciaals zou doen, zou het menu gewoon linksboven in de hoek van het browservenster worden neergezet, de standaardpositie. Dat is niet de bedoeling: het moet in het midden van het venster komen te staan.

<html> heeft van zichzelf geen hoogte. Het krijgt automatisch de hoogte die nodig is om de inhoud erin weer te kunnen geven. In dit geval is dat het menu. Door <html> een hoogte van 100% te geven, krijgt <html> altijd de hoogte van het browservenster, hoe hoog dit ook is. Dat geeft de mogelijkheid om later het menu halverwege die hoogte van 100%, dus halverwege het venster, te zetten. En als je het menu dan weer de helft van de hoogte van het menu terug omhoog verplaatst, staat het in het midden van het venster, hoe hoog dit ook is.

Voor de breedte is dit allemaal niet nodig, omdat een blok-element zoals <html> standaard de volle breedte van de ouder, hier het browservenster, vult.

Als het je nu duizelt, wordt het mogelijk duidelijker bij het daadwerkelijk centreren van het menu bij nav.

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: black;

Zwarte achtergrondkleur.

height: 100%;

Als een hoogte in procenten wordt opgegeven, is dat altijd ten opzichte van de hoogte van de ouder van het element. Die ouder is hier <html>. Gelijk hierboven is voor <html> een hoogte van 100% opgegeven, even hoog als het venster van de browser, hoe hoog dat venster ook is. <body> is dus ook altijd even hoog als het venster van de browser.

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 standaard-instellingen hiervoor. Door ze gewoon op 0 te zetten, zijn ze overal hetzelfde.

#wrapper

Het element met id="wrapper". Dit is de div, waar de hele handel in staat.

Mogelijk is dit element niet absoluut noodzakelijk en zou je met allerlei aanpassingen deze <div> kunnen 'overslaan'. Maar dat maakt de code een stuk ingewikkelder. En vanwege mijn aangeboren ongeneeslijke luiheid gebruik ik dus gewoon deze <div>, waar een aantal <div>-puristen ongetwijfeld van zal gruwen.

height: 100%;

Als een hoogte in procenten wordt opgegeven, is dat altijd ten opzichte van de hoogte van de ouder van het element. Die ouder is hier <body>. Gelijk hierboven is voor <body> een hoogte van 100% opgegeven. Ook bij <body> geldt die 100% weer ten opzichte van de ouder, en die ouder is bij <body> het element <html>. Ook <html> heeft een hoogte van 100% gekregen, waardoor <html> altijd even hoog is als het venster van de browser, ongeacht hoe hoog dit is. En uiteindelijk is dus ook kleinkind div#wrapper altijd even hoog als het venster van de browser.

max-height: 100%;

De combinatie height: 100%; (gelijk hierboven) en overflow: hidden; (gelijk hieronder) zou er eigenlijk voor moeten zorgen, dat geen verticale scrollbalk verschijnt. Maar in Internet Explorer 9 en 10 en in de bureaublad-versie van Internet Explorer 11 gebeurt dat toch.

Door toe te voegen dat de hoogte nooit meer dan die 100% mag zijn, verschijnt ook in die browsers geen verticale scrollbalk.

overflow: hidden;

Standaard staat overflow op visible: ook als tekst en dergelijke niet binnen het element past, wordt dit toch weergegeven. Normaal genomen is dat ook wat je wilt. De lay-out wordt misschien wat verstoord, maar alle tekst en dergelijke is in ieder geval zichtbaar.

In dit geval wil ik echter dat alles dat niet in #wrapper past niet wordt weergegeven, want wat niet past, wordt later op andere manieren afgehandeld.

position: relative;

Om nakomelingen te kunnen positioneren ten opzichte van een element, moet dit element zelf een positie hebben. Daarom wordt hier een relatieve positie opgegeven. Omdat verder geen waarden worden opgeven voor top en dergelijke, heeft dit verder geen enkele invloed op div#wrapper zelf.

nav

Alle <nav>'s. Dat is er hier maar eentje: de <nav> waar het hele menu in zit.

width: 384px;

De afbeelding van de puzzel is 384 px breed, dus de <nav> krijgt ook die breedte. Als de verschillende links, pop-ups, en dergelijke dan worden gepositioneerd ten opzichte van de <nav>, worden ze gelijk gepositioneerd ten opzichte van de afbeelding.

max-width: 100%; Afbeelding 3: zonder maximumbreedte verdwijnt een deel van de pagina buiten het venster

Dit is een toevoeging voor browservensters die smaller dan 384 px zijn. Iets verderop wordt ook de maximumbreedte van de afbeelding tot 100% beperkt. In smallere vensters wordt hiermee voorkomen dat een deel van menu en afbeelding aan links en rechts van het venster verdwijnen. Op de afbeelding is te zien, wat er gebeurt in smallere vensters, als geen maximumbreedte wordt opgegeven.

Een maximale breedte in procenten wordt altijd genomen ten opzichte van de ouder van het element. Dat is hier div#wrapper, een blok-element dat zelf geen breedte heeft gekregen. Een blok-element dat geen breedte heeft gekregen, wordt automatisch even breed als zijn ouder. Dat is hier <body>. Ook <body> is een blok-element en heeft geen breedte gekregen, waardoor <body> even breed is als het venster van de browser. Bij een smaller venster wordt <body> daardoor ook smaller, en daarmee ook div#wrapper en uiteindelijk ook <nav>.

height: 480px; max-height: 100%;

Zelfde verhaal als hier gelijk boven voor de breedte, maar nu voor de hoogte.

Er is één verschil: de hoogte is normaal genomen niet meer, dan nodig is om de inhoud van het element weer te geven. De afbeelding van de puzzel is 480 px hoog, dus dat wordt ook de hoogte van de <nav>.

position: absolute;

Om de <nav> op de juiste plaats neer te kunnen zetten.

Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier div#wrapper.

top: 50%;

Verticaal halverwege de hoogte van de eerste voorouder met een positie zetten. Dat is hier div#wrapper, die even hoog is als het venster van de browser, ongeacht de hoogte van dat venster, zoals beschreven bij #wrapper De <nav> wordt dus altijd verticaal halverwege het venster van de browser neergezet, ongeacht hoe hoog dit is.

left: 50%;

Horizontaal halverwege de breedte van de eerste voorouder met een positie zetten. Dat is hier div#wrapper, een blok-element. Een blok-element zoals <nav> wordt normaal genomen automatisch even breed als z'n ouder. Dat is hier div#wrapper, ook een blok-element. Dat ook weer even breed wordt als z'n ouder, het blok-element <body>. En <body> wordt weer even breed als de ouder daarvan, het blok-element <html>. Hèhè, we zijn er, geen ouders meer. Bij gebrek aan ouders wordt <html> even breed als het venster van de browser, ongeacht hoe breed dit is.

<nav> wordt dus altijd horizontaal halverwege het venster van de browser neergezet, ongeacht hoe breed dit is.

-ms-transform: translate(-50%, -50%); -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%);

Hier staat in feite drie keer hetzelfde: transform: translate(-50%, -50%); Waarom dat zo is, staat bij De voorvoegsels -moz-, -ms- en -webkit-.

Hier gelijk boven is <nav> horizontaal en verticaal halverwege het venster van de browser gezet. Zonder correctie ziet dat er als volgt uit:

Afbeelding 4: puzzel staat te laag en te veel naar rechts
Afbeelding 4: de <nav> (en de daarin zittende afbeelding van de puzzel) zonder gebruik van transform.

De linkerbovenhoek staat precies in het midden van het venster. Dat oogt weliswaar indrukwekkend, maar is toch niet helemaal, wat ik in gedachten had.

Met behulp van transform zijn allerlei soorten verplaatsingen, vervormingen, en dergelijke. uit te voeren. Achter de dubbele punt staat de soort aanpassing die je wilt toepassen. Hier is dat translate(). Tussen de haakjes daarvan geef je de grootte van de verplaatsing aan. De eerste waarde is de verplaatsing in horizontale richting, de tweede in verticale richting.

Bij beide richtingen is -50% ingevuld: de <nav>, met de daarin zitten afbeelding, moet de helft van de breedte en hoogte van de <nav> worden verplaatst. En omdat er een minteken voor de waarde staat, is de richting van die verplaatsing naar boven en naar links.

Omdat de waarde in procenten is opgegeven, maken breedte en hoogte van de <nav> niet uit. Ook in kleinere browservensters, waar de <nav> smaller en/of lager is dan 384 respectievelijk 480 px, wordt de <nav> de helft van de breedte en hoogte van de <nav> verplaatst.

Hierboven is met behulp van top: 50%; left: 50%; de <nav> halverwege de breedte en hoogte van het browservenster neergezet, ongeacht de breedte van het venster. Hier wordt de <nav> met de helft van de breedte en hoogte van de <nav> teruggezet, ongeacht de breedte en hoogte van de <nav>. Oftewel: de <nav>, en alles daarin, staat altijd horizontaal en verticaal gecentreerd, in elk venster.

h1

Alle <h1>'s. Dat is er hier maar één, de <h1> met de titel van het menu.

Normaal genomen zou hier waarschijnlijk gen <h1>, maar een <h2> of <h3> of zo staan. Maar in dit geval is dit de enige <h> op de pagina, dus wordt het een <h1>.

position: absolute;

Om de <h1> op de juiste plaats neer te kunnen zetten.

Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier <nav>.

left: -20000px;

De <h1> wordt links buiten het scherm geparkeerd. Nu is hij onzichtbaar, maar schermlezers en dergelijke zien hem wel gewoon staan. Hierdoor kan een schermlezer voorlezen, waarvoor dit menu is bedoeld, zonder dat de lay-out wordt verstoord.

nav > img

Alle <img>'s binnen een <nav>. Het teken > geeft aan, dat het alleen <img>'s zijn die een direct kind van <nav> zijn. Onderstaande <img> is een direct kind van <nav>:

<nav> <img> </nav>

De <img> hieronder is geen direct van <nav>, omdat er een <span> tussen <nav> en <img> zit:

<nav> <span> <img> </span> </nav>

In dit geval is er maar één <img> die een direct kind van een <nav> is: de afbeelding met de puzzel.

max-width: 100%; max-height: 100%; Afbeelding 5: zonder maximumgrootte staan de lijst-items niet meer op de bijbehorende puzzelstukjes

In de html zijn een breedte van 384px en een hoogte van 480 px opgeven voor de afbeelding met de puzzel. Zodra in de css ook een breedte en/of hoogte is opgegeven, overrulet die de in de html opgegeven breedte en/of hoogte.

Een maximale breedte en hoogte in procenten is altijd ten opzichte van de ouder van het element. Dat is hier <nav>, die gelijk hierboven op dezelfde manier een maximale breedte en hoogte heeft opgekregen. Hierdoor kan deze <img> nooit groter worden dan <nav>.

Als in een kleiner venster de <nav> zou worden verkleind tot de breedte van het browservenster, en de afbeelding met de puzzel niet, lopen de <li>'s niet meer parallel met de puzzelstukjes. Op de afbeelding hebben de <li>'s even een blauw randje gekregen, zodat ze te zien zijn. Elke <li> hoort bij 'n puzzelstukje. Op de afbeelding is duidelijk te zien, dat dat niet meer het geval is, als de grootte van de puzzelafbeelding niet gelijk met de grootte van de <nav> mee verandert.

Door de <img> in kleinere browservensters nooit groter te laten zijn dan de <nav>, met de daarin zittende <li>'s, blijven <li>'s en onderliggende puzzelstukjes parallel lopen.

Omdat de afbeelding mogelijk alleen in horizontale of verticale richting wordt verkleind, kan dit tot een gruwelijke vervorming leiden. Dit wordt later met behulp van @media queries bij @media screen and (orientation: landscape) and (max-height: 350px) en @media screen and (orientation: landscape) and (min-height: 351px) and (max-height: 479px) enigszins gecorrigeerd.

In Android browser en UC browser op Android zit een bug, waardoor de afbeelding soms groter is dan de <nav> in smallere vensters. Meer daarover bij Bekende problemen (en oplossingen).

/********** Algemene css pop-ups en dergelijke ****************/

Bij grotere bestanden is het vaak handig een soort 'hoofdstukjes' aan te brengen. Als je zoekt naar meerdere sterretjes, kun je zo van deel naar deel springen, wat vaak nogal wat zoekwerk kan besparen. En kan voorkomen dat je in het verkeerde deel van een bestand gaat zitten werken.

ul

Alle <ul>'s. Dat is er hier maar eentje: de ongeordende lijst waar het hele menu in staat.

In het algemeen is het handig een menu in een <ul> te zetten. Dat is meestal het makkelijkst te lay-outen. En schermlezers geven aan het begin het aantal <li>'s aan, waardoor ook het aantal links gelijk bekend is.

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.

li

Alle <li>'s. Hier zijn dat alleen de <li>'s die bij het menu onder de puzzel horen.

background: rgba(0, 0, 0, 0);

Meestal wordt voor 'n kleur de hexadecimale notatie gebruikt, iets als color: #33ab01;. Daarbij worden niet alleen cijfers, maar ook letters gebruikt. 0 tot en met 9 werken precies hetzelfde als altijd, maar na de 9 komen nog A, B, C, D, E en F.

Als je telt, is 't dus: 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12, enz. Daarbij is A gelijk aan het tientallige 10, B aan 11, enz. Op deze manier kun je met twee cijfers en/of letters 256 mogelijkheden aangeven: van 00 tot en met FF.

De eerste drie getallen bij rgba() geven de kleur aan. Deze lopen van 0 tot en met 255, dus ook hiermee kun je 256 mogelijkheden aangeven. En omdat er drie getallen zijn levert dat 256 x 256 x 256 = 16.777.216 mogelijke kleuren op, net iets meer dan het aantal kleurpotloden in de gemiddelde kleurdoos van 'n kind.

De notatie bij rgba() geeft dus precies evenveel mogelijkheden als de hexadecimale.

Het eerste getal staat voor rood, het tweede voor groen en het derde voor blauw (feitelijk de Engelse namen, maar de eerste letter is toevallig in het Nederlands hetzelfde). Uit deze drie kleuren zijn alle kleuren op een monitor opgebouwd.

255 wil zeggen volledig aanwezig, 0 wil zeggen helemaal ontbrekend.

255, 255, 255 levert wit op, 0 , 0 , 0 zwart.

In plaats van getallen mag je ook percentages gebruiken, bijvoorbeeld: rgba(10%, 20%, 100%, 0.3).

Omdat in dit voorbeeld drie keer 0 is opgegeven, levert dit een zwarte kleur op.

Het vierde getal staat voor het alfa-kanaal. Hiermee wordt de doorzichtigheid aangegeven. Dit getal loopt van 0 naar 1. Volledig doorzichtig is 0, volledig ondoorzichtig is 1.

Het getal voor het alfa-kanaal wordt als decimale breuk aangegeven, dus bijvoorbeeld 0.5 wil zeggen halfdoorzichtig. Let erop dat je 'n punt gebruikt, de Amerikaanse manier om breuken aan te geven. Als je 'n komma gebruikt, denkt de browser dat er twee verschillende getallen staan.

In dit voorbeeld is deze achtergrondkleur volkomen doorzichtig: 0.

Sommige mensen zullen zeggen: ik heb het altijd al geweten, maar het is hem nu eindelijk voor iedereen zichtbaar in de bol geslagen. Eerst alle <li>'s een zwarte achtergrondkleur geven en deze dan volledig doorzichtig maken. Dat lijkt even nuttig als een re-integratieproject voor een werkloze: je maakt iemand z'n leven zwart en het resultaat is onzichtbaar.

Ik wil geen spelbederver zijn, maar helaas, het is niet mij, maar Microsoft in de bol geslagen. In Internet Explorer 9 en 10 werkt hoveren niet, als er geen achtergrondkleur (of een doorzichtige afbeelding, dat werkt ook) aanwezig is. Bij Internet Explorer 11 is het Microsoft kennelijk weer uit de bol geslagen, want daar werkt hoveren prima, ook zonder achtergrond. Blijft toch een fascinerend fenomeen, bolbliksems.

Vandaar deze onzichtbare achtergrondkleur. Hoewel je de kleur niet ziet, werkt het toch.

width: 33.3%; height: 25%;
Afbeelding 6
Afbeelding 6: de <li>'s zijn even zichtbaar gemaakt met een blauw kadertje. Elke <li> bestrijkt één puzzelstukje.

Een breedte in procenten geldt altijd ten opzichte van de ouder van het element. Dat is hier de <ul>, waarbinnen de <li>'s zitten.

Een <ul> is een blok-element, waardoor het normaal genomen automatisch even breed wordt als de ouder. De ouder van <ul> is <nav>. Deze 33,3% geldt dus ten opzichte van <nav>, en dus ook ten opzichte van de daarin zittende puzzel-afbeelding.

En dat komt goed uit. Er zitten drie puzzelstukjes naast elkaar. 33,3% is een derde, dus er passen ook drie <li>'s naast elkaar. Oftewel: precies één <li> voor elk puzzelstukje.

Voor de hoogte geldt exact hetzelfde verhaal, maar dan met vier onder elkaar.

position: absolute;

Om de <li>'s op de juiste plaats neer te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die een positie heeft. Dat is hier <nav>. Dat komt goed uit, want binnen <nav> zit ook de afbeelding van de puzzel. Dus als je positioneert ten opzichte van <nav>, positioneer je in feite ook ten opzichte van de puzzel.

Een <li> is van zichzelf een inline-element. Door het absoluut te positioneren verandert het in 'n soort blok-element. Hierdoor zijn ook eigenschappen als breedte en hoogte te gebruiken.

top: 0;

Helemaal bovenin <nav> zetten.

Normaal genomen worden elementen in de volgorde van de html op het scherm gezet. In dit geval zou dat betekenen dat de <ul> met de daarin zittende <li>'s ónder de puzzelafbeelding zou komen te staan. Maar de <li>'s moeten niet onder, maar boven de puzzel komen te staan. Daarom worden ze, net als de afbeelding, helemaal bovenin de <nav> gezet.

Nu staan álle <li>'s, alle twaalf, bovenaan. De tweede, derde en vierde rij met <li>'s moeten lager komen te staan, boven de bijbehorende puzzelstukjes. Dat wordt iets verderop geregeld. Door hier top: 0; te geven spaar ik een aparte regel voor de bovenste drie <li>'s uit.

li:nth-of-type(3n + 2)

Voor deze elementen geldt ook de eerder bij li opgegeven css, voor zover die hier niet wordt gewijzigd.

Dit is minder ingewikkeld, dan het mogelijk lijkt. Hoewel, dat zeggen ze altijd. En het is ook wel waar, maar altijd pas achteraf, als je het al begrijpt. Over naar het begrijpen dan maar.

li: da's simpel: gewoon alle <li>'s.

nth-of-type: een zogenaamde pseudo-class. nth wil zeggen 'de zoveelste', of-type betekent 'van de soort'. Aangezien dit achter een <li> staat, gaat het hier dus om één (of meer) <li>'s.

(3n + 2): tussen de haakjes staat aangegeven, om welke <li> of <li>'s het gaat.

De getallen '3' en '2' zijn gewoon getallen, daar is verder weinig geheimzinnigs aan.

De 'n' is een soort teller, die steeds met 1 wordt verhoogd. Bij de eerste keer is de 'n' 0, bij de tweede keer 0 + 1 = 1, bij de derde keer 1 + 1 = 2, enz.

3n betekent, net als in de wiskunde, 3 x de waarde van 'n'. De eerste keer is dat dus 3 x 0 = 0, de tweede keer 3 x 1 = 3, de derde keer 3 x 2 = 6, enz. Deze berekening levert een reeks getallen op, beginnend met 0, die steeds 3 hoger worden: 0, 3, 6, 9, 12, ...

Omdat er twaalf <li>'s zijn, wordt de berekening 12 keer gemaakt. De twaalfde en laatste berekening is 3 x 11 = 33. Maar alleen de uitkomsten tot en met 12 hebben nut, omdat er maar 12 <li>'s zijn.

(De laatste waarde van 'n' is geen 12 maar 11, omdat met 0 wordt begonnen. Voor mensen lastig, maar computers beginnen heel vaak te tellen met 0.)

De eerste keer is het resultaat 3 x 0 = 0. Daarachter staat nog + 2. De eerste keer is de volledige berekening dus 3 x 0 + 2 = 2. Oftewel: de tweede <li>.

De tweede keer is het resultaat 3 x 1 = 3. Daarachter staat nog + 2. De tweede keer is de volledige berekening dus 3 x 1 + 2 = 5. Oftewel: de vijfde <li>.

De derde keer is het resultaat 3 x 2 = 6. Daarachter staat nog + 2. De derde keer is de volledige berekening dus 3 x 2 + 2 = 8. Oftewel: de achtste <li>.

Enz.

In dit geval gaat het dus om de tweede, vijfde, achtste en elfde <li>. En als dat nou niet toevallig is: dat zijn precies de <li>'s die in de tweede kolom met puzzelstukjes moeten komen te staan! Komt dat even goed uit, nu kan ik die in één keer aanspreken.

(Als je 8000 <li>'s zou hebben, zou je met deze ene regel alle 8000 <li>'s op precies dezelfde manier kunnen afhandelen en alleen de tweede, vijfde, achtste, elfde, veertiende, enz. <li> kunnen aanspreken. Er zijn met behulp van deze en soortgelijke pseudo-classes nog veel ingewikkelder en handiger selectors mogelijk, waarvan een klein aantal hieronder wordt gebruikt.)

left: 33.3%;

Bij li iets hierboven zijn de <li>'s absoluut gepositioneerd. Dat heeft een nadeel: ze worden niet netjes achter of onder elkaar gezet, maar allemaal over elkaar heen. Allemaal in de linkerbovenhoek van de <nav> en daarmee ook in de linkerbovenhoek van de in de <nav> zittende puzzel-afbeelding.

Zoals gelijk hierboven uitgelegd, bestrijkt deze selector de tweede, vijfde, achtste en elfde <li>. De <li>'s die in de tweede kolom moeten komen. Elke <li> is 33,3 % breed. Als ik de <li>'s uit deze kolom dus op 33,3% vanaf links neerzet, komen ze precies achter de <li>'s uit de tweede kolom te staan.

li:nth-of-type(3n + 3)

Voor deze elementen geldt ook de eerder bij li opgegeven css, voor zover die hier niet wordt gewijzigd.

Deze selector is exact hetzelfde als die gelijk hierboven, alleen wordt er nu 3 en geen 2 bij de 3n opgeteld. Waardoor hiermee de derde, zesde, negende en twaalfde <li> worden aangesproken. Precies de <li>'s die in de derde kolom moeten komen te staan.

left: 66.6%;

Ook hier is het verhaal precies hetzelfde als gelijk hierboven, alleen moeten deze <li>'s op 66,6% vanaf links worden neergezet, omdat het om de derde kolom gaat.

li:nth-of-type(n + 4):nth-of-type(-n + 6)

Voor deze elementen geldt ook de eerder bij li opgegeven css, voor zover die hier niet wordt gewijzigd.

De ellendepukkel die mij vroeger wiskunde gaf, was een gepatenteerde kloothommel die kinderen háátte. Los daarvan had hij de irritante eigenschap om, als je eindelijk iets begreep of deed alsof je het begreep, onmiddellijk met iets nieuws te komen dat weer net iets lastiger was.

Uit pure frustratie vanwege deze uiterst traumatische onverwerkte ervaring ga ik hier hetzelfde doen. Ik maak het iets moeilijker.

Achter de <li> van deze selector staan twee pseudo-classes: nth-of-type(n + 4) en nth-of-type(-n + 6). Dat betekent alleen maar dat de <li> aan beide pseudo-classes moet voldoen. Je kunt ze dus apart bekijken, waarmee het opeens een stuk beter te behappen is.

li: alle <li>'s.

nth-of-type(n + 4): vrijwel hetzelfde als iets hierboven bij li:nth-of-type(3n + 2).

De 'n' is weer een teller die met 0 begint en steeds 1 hoger wordt. De eerste keer staat er dus 0 + 4 = 4, de tweede keer 1 + 4 = 5, de derde keer 2 + 4 = 6, enz. Dit levert de getallen 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 en 15 op. Alleen de uitkomsten 12 en lager hebben nut, want er zijn maar twaalf <li>'s.

De eerste pseudo-class stelt dus als voorwaarde dat het de vierde, vijfde, enz. tot en met de twaalfde <li> is.

nth-of-type(-n + 6): ook deze selector is weinig anders dan de eerdere, maar met een minteken voor de 'n'. De 'n' is weer een teller die met 0 begint en steeds 1 hoger wordt. Alleen is het hier iets lastiger vanwege het minteken.

Bij de eerdere pseudo-class bij li:nth-of-type(3n + 2) stond 3n: voor de 'n' staat het getal 3. Wat je uit moet leggen als 3 x n.

Bij deze selector staat geen getal voor de 'n', alleen een minteken. Als er geen getal voor de 'n' staat, staat er eigenlijk toch 'n getal: de 1. Maar dat wordt weggelaten, omdat '1n' moet worden gelezen als '1 x n', en dan is de 1 een beetje overbodig.

Hier staat echter een minteken voor de 'n', en dan kan het helpen om de 1 er wel even bij te denken: -1n: Wat je dus moet lezen als -1 x n.

Bij de eerste ronde is 'n' 0. De berekening wordt dan -1 x 0 = 0.

Bij de tweede ronde is 'n' 1. De berekening wordt dan -1 x 1 = -1.

Bij de derde ronde is 'n' 2. De berekening wordt dan -1 x 2 = -2.

Enz., de uitkomst is steeds 1 lager. Hoewel 'n' steeds 1 meer wordt, wordt de uitkomst door het minteken steeds 1 lager.

Bij de twaalfde en laatste ronde is 'n'11 en is de berekening -1 x 11 = -11.

(Omdat de 'n' met 0 begint te tellen, is de 'n' bij de twaalfde berekening 11 en geen 12.)

Bij deze uitkomst moet 6 worden opgeteld, want er staat -n + 6 tussen de haakjes.

Bij de eerste ronde staat er -1 x 0 + 6 = 6.

Bij de tweede ronde staat er -1 x 1 + 6 = -1 + 6 = 5.

Bij de derde ronde staat er -1 x 2 + 6 = -2 + 6 = 4.

Bij de twaalfde ronde staat er -1 x 11 + 6 = -11 + 6 = -5.

De uitkomst is de serie getallen 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5.

Oftewel: het gaat om de zesde, vijfde, vierde, derde, tweede en eerste <li>. De nulde en lagere <li>'s vervallen, want er bestaan geen nulde of lagere <li>'s.

:nth-of-type(n + 4):nth-of-type(-n + 6): beide pseudo-classes achter elkaar.

De <li>'s moeten binnen beide pseudo-classes vallen.

De eerste pseudo-class levert de vierde tot en met de twaalfde <li> op.

De tweede pseudo-class levert de eerste tot en met de zesde <li> op.

Alleen de vierde, vijfde en zesde <li> zitten binnen beide pseudo-classes, dus de css van deze selector geldt alleen voor de vierde, vijfde en zesde <li>. En dat zijn, niet geheel toevallig, de <li>'s die boven de tweede rij puzzelstukjes moeten komen te staan.

top: 25%;

Op 25% vanaf de bovenkant van de <nav> neerzetten. Omdat de <li>'s 25% hoog zijn, komt deze rij <li>'s precies onder de bovenste rij <li>'s te staan.

li:nth-of-type(n + 7):nth-of-type(-n + 9)

Voor deze elementen geldt ook de eerder bij li opgegeven css, voor zover die hier niet wordt gewijzigd.

Los van de getallen is deze selector precies hetzelfde als die hierboven bij li:nth-of-type(n + 4):nth-of-type(-n + 6).

nth-of-type(n + 7): de eerste pseudo-class levert hier de getallen 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 op. Er zijn maar 12 <li>'s, dus alleen de getallen 7 tot en met 12 zijn interessant.

nth-of-type(-n + 9): de tweede pseudo-class levert hier de getallen 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2 op. Alleen de getallen 1 tot en met 9 zijn interessant, want een nulde of lagere <li> is onzin.

Ook hier komen alleen de <li>'s in aanmerking, die binnen beide pseudo-classes vallen. Dat zijn alleen de zevende, achtste en negende <li>. En komt dat even goed uit: dat zijn precies de drie <li>'s die in de derde rij zitten!

top: 50%;

Op 50% vanaf de bovenkant van de <nav> neerzetten. Omdat de <li>'s 25% hoog zijn, komt deze rij <li>'s precies onder de bovenste twee rijen <li>'s te staan en vormt hiermee de derde rij.

li:nth-of-type(n + 10):nth-of-type(-n + 12)

Voor deze elementen geldt ook de eerder bij li opgegeven css, voor zover die hier niet wordt gewijzigd.

Los van de getallen is deze selector precies hetzelfde als die iets hierboven bij li:nth-of-type(n + 4):nth-of-type(-n + 6).

nth-of-type(n + 10): de eerste pseudo-class levert hier de getallen 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 op. Er zijn maar 12 <li>'s, dus alleen de getallen 10 tot en met 12 zijn interessant.

nth-of-type(-n + 12): de tweede pseudo-class levert hier de getallen 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 op.

Ook hier komen alleen de <li>'s in aanmerking, die binnen beide pseudo-classes vallen. Dat zijn alleen de tiende, elfde en twaalfde <li>. Wat precies de drie <li>'s zijn die in de vierde en onderste rij zitten.

top: 75%;

Op 75% vanaf de bovenkant van de <nav> neerzetten. Omdat de <li>'s 25% hoog zijn, komt deze rij <li>'s precies onder de bovenste drie rijen <li>'s te staan en vormt hiermee de vierde en onderste rij.

li > span

Alle <span>'s die een direct kind van een <li> zijn. Binnen deze <span>'s zitten de pop-ups.

Het teken > geeft aan dat het om directe kinderen moet gaan:

<li> <span></span> </li>

In onderstaande code is de buitenste <span> een direct kind, waarvoor deze selector dus geldt. De binnenste <span> is geen direct kind van de <li>, maar van de buitenste <span>, dus daarvoor geldt deze selector niet:

<li> <span> <span></span> </span> </li>

Het gebruik van de > geeft de mogelijkheid css op te geven die alleen de <span>'s bestrijkt, waarbinnen de volledige pop-up staat. Op die manier kun je bijvoorbeeld het tonen en verbergen van de pop-up regelen door slechts één <span> aan te passen, zonder dat dit dieper geneste <span>'s beïnvloedt.

display: none;

Verbergen. Hiermee wordt ook alles binnen de <span> en daarmee de hele pop-up verborgen. Alleen de knop met de link zit niet binnen de <span>, het verbergen daarvan wordt gelijk hieronder bij a geregeld.

position: absolute;

Om de <span> op de juiste plaats te kunnen zetten.

Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft, Dat is hier de <li>, waar de <span> een direct kind van is.

a

Afbeelding 7: de link is veranderd in 'n soort knop

Alle <a>'s. Omdat in dit geval alle <a>'s binnen het puzzelmenu zitten, kan deze simpele selector worden gebruikt.

Met behulp van css wordt het uiterlijk van de link veranderd in 'n soort knop.

background: white;

Witte achtergrond.

Hier gelijk onder wordt nog een background opgegeven, maar dan met een gradiënt, een verlopende kleur. Omdat de gradiënt onder de hier opgegeven witte achtergrond staat, 'wint' de gradiënt van deze witte achtergrond. Dus feitelijk zou je deze witte achtergrond kunnen weglaten, omdat die toch wordt overrulet.

Deze regel staat er alleen maar voor Internet Explorer 9. Die browser kent het hieronder gebruikte linear-gradient niet, en negeert daarom de regel hieronder. Waardoor de <a> helemaal geen achtergrond zou krijgen in Internet Explorer 9. Door hier een gewone witte achtergrond op te geven, heeft ook in Internet Explorer 9 de <a> in ieder geval een achtergrondkleur.

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

Hier staat in feite twee keer hetzelfde: linear-gradient(to bottom, #fff 0%, #bbb 100%); Waarom dat zo is, staat bij De voorvoegsels -moz-, -ms- en -webkit-. Hieronder wordt alleen de tweede vorm uitgelegd, want dat is de vorm volgens de uiteindelijke standaard.

Internet Explorer 9 kent linear-gradient niet en negeert deze regel daarom, zoals gelijk hierboven bij de eerste background beschreven.

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

(Overigens is het wel raadzaam die code op te schonen, omdat er wel heel erg veel code voor heel erg oude versies van verschillende browsers in staat.)

In dit geval heb ik geen gradiënt-editor gebruikt, omdat het hier allemaal mooie ronde getallen en codes zijn.

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

Normaal genomen is de kleur van de tekst in een link blauw, of rood of zo als de link is bezocht. Dat vind ik hier niet mooi: de tekst moet gewoon zwart zijn.

box-shadow: 4px 6px 4px 1px;

Schaduw aan de knop geven.

Met behulp van box-shadow kan schaduw worden gegeven aan een element. Er is geen kleur opgegeven, wat betekent dat de voorgrondkleur wordt gebruikt, hier zwart.

De schaduw is, als je verder niets opgeeft, precies even groot als het element waar de schaduw bij hoort. Dat schiet niet echt op, want dat betekent dat de schaduw precies onder het element staat en dus onzichtbaar is. Daarom wordt de schaduw met behulp van de vier getallen aangepast. De getallen die hier worden gebruikt, leveren de schaduw op, zoals die hierboven bij de afbeelding is te zien. Hieronder heb ik de waarden iets veranderd, zodat het effect van de verschillende waarden duidelijker is te zien.

Afbeelding 8: de schaduw 30 px naar rechts verschoven

4px: het eerste getal, hier 4px, geeft de verplaatsing in horizontale richting aan: 4 px naar rechts. Als dit getal 0 zou zijn, zou de linkerkant van de schaduw gelijkvallen met de linkerkant van de <a>, nu is de schaduw 4 px naar rechts verschoven. Als je hier een negatief getal invult, verschuift de linkerkant van de schaduw naar links. Om bijstaande afbeelding te krijgen, zijn de waarden 30px 0 0 0 gebruikt: alleen een horizontale verschuiving van 30 px.

Afbeelding 9: de schaduw 30 px naar omlaag verschoven

6px: voor het tweede getal geldt precies hetzelfde, maar dan in verticale richting. De bovenkant van de schaduw wordt 6 px naar beneden verplaatst. Om bijstaande afbeelding te krijgen, zijn de waarden 0 30px 0 0 gebruikt: alleen een verticale verschuiving van 30 px.

Afbeelding 10: de schaduw over een afstand van 30 px vervagend

4px: het derde getal geeft de breedte van de vervaging aan. De schaduw vervaagt hier over een afstand van 4 px. Om bijstaande afbeelding te krijgen, zijn de waarden 0 0 30px 0 gebruikt: de schaduw vervaagt over een afstand van 30 px. Negatieve getallen zijn hier niet toegestaan. De vervaging is wat moeilijk te zien, maar dat is nou juist ook het kenmerk van een vervaging.

Afbeelding 11: de schaduw aan alle kanten 30 px uitstekend

1 px: het laatste getal ten slotte geeft de breedte van de schaduw aan: die is hier maar 1 px. Op bijstaande afbeelding zijn de waarden 0 0 0 30px gebruikt: de schaduw is 30 px groter dan het element waar hij bijhoort. Omdat verder geen waarden zijn opgegeven, staat de schaduw aan alle kanten 30 px buiten het element. Bij negatieve waarden wordt de schaduw kleiner dan het element. Dat is alleen maar zinvol als je de schaduw ook verplaatst, want anders verstop je de schaduw alleen maar.

Meestal moet je even wat experimenteren, voordat je de juiste waarden hebt. Vooral de laatste waarden, die voor het vervagen en voor de breedte van de schaduw, beïnvloeden elkaar nogal.

text-decoration: none;

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

border: black solid 1px;

Zwart randje.

border-radius: 10em / 6em;

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

Je kunt voor alle vier de hoeken andere waarden opgeven. En voor elke hoek kun je dan ook nog een andere waarde voor de horizontale en de verticale richting opgeven.

De horizontale en verticale waarde wordt gescheiden door een schuine streep. Voor de streep staat de horizontale waarde, achter de streep de verticale. Als er maar één waarde is opgegeven, geldt die voor horizontaal en verticaal. (Als een element bijvoorbeeld 50 px hoog en breed is en je geeft alleen 25 px op, kun je op deze manier dus een volmaakte cirkel maken.)

Hier is de waarde in horizontale richting 10 em, in verticale richting 6 em. Omdat er maar één waarde per richting staat, geldt die voor alle vier de hoeken. In horizontale richting is de ronding haast twee keer zo lang als in verticale richting, wat een ovaal oplevert.

padding: 8px 18px;

Afstand tussen tekst en rand van de <a>. Omdat voor onder en links geen waarden zijn opgegeven, krijgen die automatisch dezelfde waarde als boven en rechts. Hier staat dus eigenlijk 8px 18px 8px 18px in de volgorde boven – rechts – onder – links. Boven en onder 8 px padding, links en rechts 18px.

Afbeelding 12: tekst staat te ver naar buiten

Dit is tamelijk veel padding. Dat heeft te maken met de hierboven opgegeven border-radius. Omdat de buitenkant van de <a> naar binnen afbuigt, is er meer padding nodig dan normaal. Bij een meer gebruikelijke padding van 3 px aan alle kanten, komt de tekst veel te dicht of zelfs buiten de knop te staan, zoals is te zien op de afbeelding.

position: absolute;

Om de knop op de juiste plaats neer te kunnen zetten.

Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier de <li>, waarbinnen de <a> zit.

left: -20000px;

De hele handel links buiten het scherm parkeren, zodat de knop onzichtbaar is. Als de knop zichtbaar moet worden, hoeft deze alleen maar binnen het scherm te worden gezet.

Er wordt geen gebruik gemaakt van display: none;, omdat schermlezers en dergelijke dan de <a> volledig negeren en de link dus niet wordt voorgelezen. Nu is de link gewoon aanwezig, alleen staat deze links buiten het scherm. Maar dat maakt voor schermlezers en dergelijke niets uit.

z-index: 10;

In de html staat de <a> voor de <span>, waarin de pop-up zit. Normaal genomen komt de <span> daardoor boven de link te staan, waardoor je deze niet meer ziet. Door de <a> een hogere z-index te geven, komt deze toch boven de <span> met de pop-up te staan, ook al staat deze lager in de html.

Een z-index werkt alleen als het element is gepositioneerd. Dat is hierboven geregeld met position: absolute;.

Dit is de laagste z-index die wordt gebruikt, dus je zou ook 1 kunnen gebruiken. Door een hoger getal te nemen, is het mogelijk om later eventueel een lagere z-index tussen te voegen, zonder dat je deze waarde hoeft te veranderen. Hier is het niet zo belangrijk, maar het is een goede gewoonte om je aan te leren. Ooit heb ik 'n paar honderd z-indexen aangebracht, netjes op volgorde, en toen moest er helemaal aan het begin eentje worden tussengevoegd...

li:empty:not(:focus):hover::after, li:empty:focus::after

Deze regel is voor de <li>'s, die nog niet in gebruik zijn. Als alle <li>'s zouden worden gebruikt, is de regel overbodig.

Dit zijn twee selectors, eentje voor en eentje na de komma. Een deel van beide selectors is hetzelfde.

Beide selectors:

li:empty: alle lege <li>'s. Beide selectors beginnen hiermee. Een element is leeg, als het geen ander element of tekst bevat. Er mag zelfs geen spatie in zitten. Dit geldt voor de <li>'s die nog niet in gebruik zijn:

<li tabindex="0"></li>

Er staat helemaal niets tussen de openings- en de sluittag. tabindex="0" telt niet mee, want dat staat bínnen de openingstag.

::after: hier eindigen beide selectors mee. Met behulp van ::after wordt bij de <li> een pseudo-element gemaakt. Hierin kan met behulp van het hieronder gebruikte content tekst worden gezet.

De eerste selector:

:not(:focus): :focus is simpel: als het element focus heeft. (Meer over wat focus is bij :focus.) Maar hiervoor staat :not(). Daarmee wordt het juist omgekeerd: als het element géén focus heeft. Deze selector geldt dus alleen, als het element, hier de <li>, geen focus heeft.

:hover: bij hoveren over het element.

:not(:focus):hover: samen betekent dit: bij hoveren over het element, over de <li>, maar alleen als de <li> geen focus heeft.

li:empty:not(:focus):hover::after: alles samen. Maak een pseudo‑element (::after) bij hoveren (:hover) over een <li>, maar alleen als die <li> leeg (:empty) is en als die <li> geen focus (:not(:focus)) heeft.

Dat hier een hele serie pseudo-elementen en pseudo-classes achter elkaar staat, is geen enkel probleem.

De :not(:focus) is nodig voor Internet Explorer 9 en 11, vreemd genoeg niet voor versie 10. Hieronder bij font-size wordt de lettergrootte verkleind. Als in Internet Explorer 9 of 11 een <li> focus heeft en er wordt gelijktijdig over gehoverd, wordt de lettergrootte twee keer toegepast: kennelijk één keer voor de :focus en één keer voor de :hover. Door de :hover alleen te laten werken als de <li> geen focus heeft, wordt dit voorkomen.

De tweede selector:

:focus: als de <li> focus heeft.

li:empty:focus::afterM: alles samen. Maak een pseudo-element (::after) als de <li> focus (:focus) heeft, maar alleen als die <li> leeg (:empty) is.

content: "Dit puzzel\00ADstukje is nog niet af. Hier kun je zelf nog iets maken.";

De tekst die in het met ::after gemaakte pseudo-element moet worden weergegeven. Dit is gewoon normale tekst, met uitzondering van \00AD. Dit is een code voor een zogenaamd 'zacht koppelteken'. Dat is een koppelteken dat je normaal genomen niet ziet, maar wel als het woord bij het koppelteken wordt afgebroken. Het betreffende woord is hier 'puzzelstukje', een tamelijk lang woord om weer te geven in een heel kleine pop-up.

Om aan te geven dat 00AD geen gewone tekst is, staat gelijk ervoor een \. Daardoor weet de browser dat de vier tekens hierna het volgnummer van een utf-8-code zijn, en wordt voorkomen dat ze gewoon worden weergegeven. 00AD is het volgnummer dat hoort bij een zacht koppelteken.

Hieronder wordt voor dit pseudo-element automatisch afbreken aangezet met hypens: auto;, maar niet elke browsers herkent dat al. Voor de wat oudere browsers is deze utf-8-code bedoeld.

background: rgba(255, 255, 255, 0.8);

Meestal wordt voor 'n kleur de hexadecimale notatie gebruikt, iets als color: #33ab01;. Daarbij worden niet alleen cijfers, maar ook letters gebruikt. 0 tot en met 9 werken precies hetzelfde als altijd, maar na de 9 komen nog A, B, C, D, E en F.

Als je telt, is 't dus: 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12, enz. Daarbij is A gelijk aan het tientallige 10, B aan 11, enz. Op deze manier kun je met twee cijfers en/of letters 256 mogelijkheden aangeven: van 00 tot en met FF.

De eerste drie getallen bij rgba() geven de kleur aan. Deze lopen van 0 tot en met 255, dus ook hiermee kun je 256 mogelijkheden aangeven. En omdat er drie getallen zijn levert dat 256 x 256 x 256 = 16.777.216 mogelijke kleuren op, net iets meer dan het aantal kleurpotloden in de gemiddelde kleurdoos van 'n kind.

De notatie bij rgba() geeft dus precies evenveel mogelijkheden als de hexadecimale.

Het eerste getal staat voor rood, het tweede voor groen en het derde voor blauw (feitelijk de Engelse namen, maar de eerste letter is toevallig in het Nederlands hetzelfde). Uit deze drie kleuren zijn alle kleuren op een monitor opgebouwd.

255 wil zeggen volledig aanwezig, 0 wil zeggen helemaal ontbrekend.

255, 255, 255 levert wit op, 0 , 0 , 0 zwart.

In plaats van getallen mag je ook percentages gebruiken, bijvoorbeeld: rgba(10%, 20%, 100%, 0.3).

Omdat in dit voorbeeld drie keer 255 is opgegeven, levert dit een witte kleur op.

Het vierde getal staat voor het alfa-kanaal. Hiermee wordt de doorzichtigheid aangegeven. Dit getal loopt van 0 naar 1. Volledig doorzichtig is 0, volledig ondoorzichtig is 1.

Het getal voor het alfa-kanaal wordt als decimale breuk aangegeven, dus bijvoorbeeld 0.5 wil zeggen halfdoorzichtig. Let erop dat je 'n punt gebruikt, de Amerikaanse manier om breuken aan te geven. Als je 'n komma gebruikt, denkt de browser dat er twee verschillende getallen staan.

In dit voorbeeld is deze achtergrondkleur een heel klein beetje doorzichtig: 0.8. Hierdoor zie je nog vaag de puzzel door de achtergrond heen.

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, is er nog niets aan de hand, want dan veranderen achtergrond- en voorgrondkleur geen van beide.

display: block;

Weergeven als blok-element, zodat eigenschappen als hoogte gebruikt kunnen worden.

box-sizing: border-box;

Standaard worden border en padding opgeteld bij de breedte van het element. In dit geval is het handiger, als ook border en padding binnen die breedte vallen.

min-height: 100%;
Afbeelding 13: door de achtergrond onder de tekst is ook een grotere letter nog leesbaar
Afbeelding 13: links is min-height: 100%; gebruikt, rechts height: 100%;. Zulke kleine dingetjes kunnen vaak al een enorm verschil maken, wat betreft toegankelijkheid.

Een hoogte in procenten wordt altijd genomen ten opzichte van de ouder van het element. Dat is hier de <li> waar het pseudo-element bij hoort.

Een blok-element wordt normaal genomen precies hoog genoeg, om de inhoud ervan weer te kunnen geven. Ik vind het mooier als de hele <li>, de ouder, wordt gevuld. De <li> is precies even groot als het puzzelstukje eronder, dus op deze manier dekt het pseudo-element het hele stukje eronder af.

In plaats van height wordt min-height gebruikt. Als de lettergrootte wordt vergroot, kan de tekst hoger worden dan 100% van de <li>. Bij gebruik van height zou de achtergrond niet meegroeien boven 100%, waardoor de tekst slecht leesbaar wordt, als deze wordt vergroot en buiten de <li> komt te staan. Nu groeit de achtergrond, als dat nodig is, mee met de tekst.

font-size: 0.85em;

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

-moz-hyphens: auto; -ms-hyphens: auto; -webkit-hyphens: auto; hyphens: auto;

Hier staat in feite vier keer hetzelfde: hyphens: auto; Waarom dat zo is, staat bij De voorvoegsels -moz-, -ms- en -webkit-.

Het in content gebruikte woord 'puzzelstukje' is heel erg lang voor zo'n klein pseudo-element. Daarom wordt automatisch afbreken aangezet.

border: black solid 2px;

Zwart randje.

padding: 5px;

Afstand tussen tekst en rand van het pseudo-element.

li:focus, nav a:focus

Als een <li> focus heeft, of als een <a> binnen een <nav> focus heeft.

outline: none;

Als een element focus heeft, wordt dit normaal genomen aangegeven door een kadertje rondom het element met focus. Dat vind ik hier niet mooi, dus haal ik het weg. Meer over focus en waarom je die niet zonder meer onherkenbaar moet maken, is te vinden bij :focus.

a:hover

Als over een <a> wordt gehoverd.

text-decoration: underline;

Onderstreep de tekst in de <a>.

li:focus > span, li:hover > span, a:focus + span

li:focus > span: doe iets met de <span>'s die een direct kind zijn van een <li>, maar alleen als die <li> focus heeft.

Het teken > geeft aan dat het om directe kinderen moet gaan:

<li> <span></span> </li>

In onderstaande code is de buitenste <span> een direct kind, waarvoor deze selector dus geldt. De binnenste <span> is geen direct kind van de <li>, maar van de buitenste <span>, dus daarvoor geldt deze selector niet:

<li> <span> <span></span> </span> </li>

Het gebruik van de > geeft de mogelijkheid css op te geven die alleen de <span>'s bestrijkt, waarbinnen de volledige pop-up staat. Op die manier kun je bijvoorbeeld het tonen en verbergen van de pop-up regelen door slechts één <span> aan te passen, zonder dat dit dieper geneste <span>'s beïnvloedt.

Deze selector is alleen nodig voor Internet Explorer 11 op een touchscreen en UC browser op Windows Phone. Zonder deze selector moeten eerste en tweede puzzelstukje langer worden aangeraakt, voordat de pop-up opent. Waarom dit niet het geval is bij het zesde en negende stukje, weet ik niet. Wat ik inmiddels wel weet: zodra er een afbeelding in een pop-up zit, gedragen deze browsers zich wat vreemd bij een touchscreen.

li:hover > span

Precies hetzelfde verhaal als hierboven. Alleen werkt dit, als over de <li> wordt gehoverd. En dit is voor álle browsers bedoeld.

a:focus + span

Als de <a> focus heeft, doe dan iets met de in de html direct daarop volgende <span>. De + geeft aan dat <a> en <span> gelijk op elkaar moeten volgen. Bovendien moeten ze dezelfde ouder hebben. Dat is hier de <li>, waar ze in zitten.

De opbouw van de html is bij elk puzzelstukje als volgt:

<li> <a></a> <span> (...) <span>'s en <img>'s, de eigenlijke pop-up (...) </span> </li>

De direct op de <a> volgende <span> is dus, net zoals hierboven bij li:hover en li:focus, de <span> waar de hele pop-up in zit.

Aangezien de knop met de <a> normaal genomen is verborgen, kan deze normaal genomen geen focus krijgen. Deze selector is bedoeld voor mensen die van link naar link springen met behulp van de Tab-toets, zodat ook bij gebruik van het toetsenbord om de links af te lopen de pop-up wordt getoond. Meer over de Tab-toets is te vinden bij Tabindex.

display: block;

Bij li > span zijn de <span>'s met de pop-up verborgen met display: none;. Hier worden ze zichtbaar gemaakt.

li:hover

Als over een <li> wordt gehoverd.

z-index: 20;
Afbeelding 14: twee pop-ups door elkaar heen geopend
Afbeelding 14: het negende stukje over de mail heeft focus, terwijl er gelijktijdig over het tweede stukje met de dansletters wordt gehoverd. Niet echt duidelijk.

Verhoog de z-index van de <li>. Hierdoor wordt ook alles dat in de <li> zit met een hogere z-index weergegeven.

Als een <li> focus heeft, worden de daarin zittende knop met de link en de pop-up getoond. Als je, terwijl die eerste <li> nog focus heeft, over een ander puzzelstukje (en dus over de daarbij horende <li>) hovert, openen de in die tweede <li> zittende knop en pop-up.

Door de z-index van de tweede <li> te verhogen tijdens het erover hoveren, zijn knop en pop-up van de tweede <li> volledig zichtbaar. Normaal genomen zal altijd het later in de html staande element over een eerder element heen worden gezet. Door de z-index bij hoveren te verhogen, worden nu ook knop en pop-up van een eerdere <li> volledig weergegeven. Als dat niet gebeurt, is het nogal verwarrend.

Een z-index werkt alleen bij een gepositioneerd element. Bij li zijn alle <li>'s absoluut gepositioneerd, dus dat is hier het geval.

/*********** Eerste puzzelstukje (krokodil) *********/

Bij grotere bestanden is het vaak handig een soort 'hoofdstukjes' aan te brengen. Als je zoekt naar meerdere sterretjes, kun je zo van deel naar deel springen, wat vaak nogal wat zoekwerk kan besparen. En kan voorkomen dat je in het verkeerde deel van een bestand gaat zitten werken.

#een span

Alle <span>'s binnen het element met id="een".

Dat is de, <span> waarbinnen de eerste pop-up zit, die met de krokodil. En alle <span>'s die daar weer binnen zitten, want het gaat om álle <span>'s binnen #een.

pointer-events: none;

Dit is nodig voor Internet Explorer 11, omdat anders de pop-up bij aanraken van een touchscreen niet geopend blijft. Deze oplossing werkt bij álle pop-ups, maar is helaas alleen bij de eerste pop-up echt praktisch bruikbaar. Als hij overal bruikbaar zou zijn, zou je gewoon iets als li span {pointer-events: none;} kunnen gebruiken. Nu moet helaas voor elke pop-up een andere oplossing worden gezocht.

pointer-events: none; zorgt ervoor dat het element totaal niet reageert op de muis. Niet op hoveren en niet op klikken. Hoveren en klikken gaat als het ware dwars door het element heen naar het eronder liggende element.

Je kunt dit zichtbaar maken door met de muis over de eerste pop-up te hoveren. Zodra je beneden het eerste puzzelstukje, beneden de eerste <li>, komt, sluit de pop-up. Ook als je nog boven de tekst in de pop-up hovert. De <span>'s, en dus de daarin zittende pop-up, reageren niet op het hoveren. Bij de andere pop-ups blijft de pop-up geopend, zolang je over de pop-up hovert, ook als je buiten het puzzelstukje komt, waar de pop-up bij hoort. Bij de eerste pop-up is dit geen probleem, bij de andere wel.

Hier iets boven bij li:hover staat een afbeelding. Als pointer-events: none; overal zou worden gebruikt, zou dat er precies zo uitzien. Als het tweede stukje met de dansletters focus heeft en is geopend, zou de pop-up van het negende stukje daar gewoon doorheen verschijnen, als je over dat negende stukje hovert. Omdat de pop-up het hoveren gewoon 'doorgeeft' aan de <li> bij het negende stukje.

Bij de eerste pop-up is dat geen probleem, bij de andere wel.

top: 0; left: -150px;

Helemaal bovenaan en 150 px naar links neerzetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is de <li>, waar deze <span> in zit: li#een.

Omdat de bovenkant van die <li> precies gelijk staat met de bovenkant van de puzzelafbeelding, komt de bovenkant van deze <span>, en dus de daarin zittende pop-up, ook precies gelijk met de bovenkant van de puzzel. Hierdoor verdwijnt ook in lagere browservensters niets aan de bovenkant van het venster, omdat de pop-up te hoog staat.

Omdat de pop-up wel 150 px links buiten de puzzel komt te staan, zou in smallere vensters wel links een deel van de pop-up wegvallen. Daarom wordt later bij @media screen and (max-width: 360px) en @media screen and (min-width: 361px) and (max-width: 670px) left aangepast voor smallere vensters.

Dit heeft alleen effect op <span>'s die zijn gepositioneerd. Bij li > span zijn de <span>'s die directe kinderen van de <li> zijn absoluut gepositioneerd. Dit heeft alleen effect op die <span>, de <span> waarbinnen de hele pop-up zit. Omdat dieper geneste <span>'s niet zijn gepositioneerd, negeren die dit gewoon.

#een-tekst

Voor dit element geldt ook de eerder bij #een span opgegeven css, voor zover die hier niet wordt gewijzigd.

Het element met id="een-tekst". Dit is de <span>, waarbinnen de tekst van de eerste pop-up zit. Binnen deze <span> zitten weer andere <span>'s, met elk een regel tekst. Hier door kan elke regel tekst precies op de juiste plaats boven de wolk worden neergezet.

display: block;

Een <span> is een inline-element. De hieronder gebruikte margin-top werkt alleen op blok-elementen. Door de <span> om te toveren in een blok-element, kan een marge aan de bovenkant worden gebruikt.

margin-top: -220px; Afbeelding 15: zonder negatieve marge aan de bovenkant komt de tekst veel te laag te staan

Een negatieve marge aan de bovenkant plaatst het element hoger. In dit geval 220px.

In de <span> met de pop-up zit een <img>: de krokodil met bijbehorende wolk. Op de afbeelding is de doorzichtige achtergrond van die afbeelding even gemaakt, zodat de afbeelding volledig zichtbaar is. De span met de tekst komt daar gewoon onder te staan, zoals het volgens de browser hoort.

Door de <span> 220 px omhoog te plaatsen, komt de <span>, en dus de hier weer in zittende <span>'s met de losse regels tekst, op de juiste hoogte te staan.

Met behulp van regelhoogte en dergelijke wordt dan hieronder voor elke regel tekst de exacte plaats bepaald.

#een-tekst span

De <span>'s binnen het element met id="een-tekst".

span#een-tekst is de <span> waarbinnen de volledige tekst bij de krokodil zit. Binnen die <span> zit elke aparte regel tekst weer in een eigen <span>. Om die laatste <span>'s gaat het hier.

De exacte plaats van elke <span> wordt hieronder voor elke <span> apart opgegeven. Een aantal eigenschappen is echter hetzelfde voor al deze <span>'s, dus die kunnen hier in één keer worden opgegeven.

background: #e7e7e7;

Achtergrondkleur. Deze kleur is hetzelfde als die van de wolk bij de krokodil. Dus eigenlijk zou je dit weg kunnen laten, want je ziet het toch niet. Maar als mensen de lettergrootte vergroten, kan de tekst buiten de wolk komen te staan. En dan is die achtergrond wel belangrijk, omdat de tekst anders nauwelijks is te lezen.

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, is er nog niets aan de hand, want dan veranderen achtergrond- en voorgrondkleur geen van beide.

display: block;

Een <span> is van zichzelf een inline-element. Hier worden ze veranderd in blok-elementen. Eigenlijk is dat hier niet nodig, maar het kan in de toekomst maandenlange wanhopige speurtochten naar de oorzaak van geheimzinnige, enge, onverklaarbare verschijnselen voorkomen.

Als ergens in een voorouder van een element een line-height is opgegeven, kan die regelhoogte later in een inline-element niet meer worden veranderd. Als in <body> een regelhoogte is opgegeven, kan die in een 97 niveaus diep geneste <span> niet worden gewijzigd. Punt. Discussie gesloten.

Daar zijn goede redenen voor, want het zou echt een zootje worden als je verschillende regelhoogtes in één regel gaat krijgen. (De lettergrootte kan wel worden veranderd. Als dat gebeurt, wordt de regelhoogte daar wel aan aangepast.)

In een blok-element kan de regelhoogte wel worden gewijzigd. Die gewijzigde regelhoogte geldt dan weer voor alle nakomelingen van het blok-element, en kan ook op z'n beurt ook weer alleen worden gewijzigd in een blok-element, niet in een inline-element.

Hier iets onder wordt de regelhoogte voor deze <span>'s aangepast. Dat kan in principe gewoon, omdat nergens eerder een regelhoogte is opgegeven. In dat geval kan ook in een inline-element de regelhoogte worden aangepast.

Maar als ooit – in het jaar 2098, wanneer dit puzzelmenu inmiddels uit 888 stukjes bestaat – door een achterachterachterkleinkind van mij argeloos ergens een regelhoogte wordt toegevoegd, leidt dit tot voornoemde wanhopige speurtocht, omdat de regelhoogte hier dan opeens niet meer werkt.

Daarom verander ik in principe een element, waarin de regelhoogte wordt aangepast, gelijk in een blok-element. Uit verantwoordelijkheidsgevoel voor de geestelijke gezondheid van mijn achterachterachterkleinkind. Als dan later ooit ergens bij een van de voorouders een regelhoogte wordt toegevoegd, blijft de in deze <span> opgegeven regelhoogte gewoon werken.

Afbeelding 16: achtergrondkleur van de tekst staat buiten de afbeelding

Dit brengt één klein nadeel met zich mee: een blok-element is normaal genomen even breed als z'n ouder. Dus ook de achtergrond van dat blok-element. Daardoor komt de achtergrondkleur rechts buiten de wolk te staan. Om dat te voorkomen, moet hieronder bij elke <span> met tekst de juiste breedte worden opgegeven.

Op de afbeelding is geen breedte opgegeven aan de <span>'s met tekst, waardoor ze de volle breedte van hun ouder span#een-tekst vullen.

font-size: 0.95em;

Iets kleinere letter, zodat alles binnen de wolk naast de krokodil past. Als eenheid gebruik ik em, zodat ook gebruikers van Internet Explorer de lettergrootte kunnen veranderen.

line-height: 1.25em;

Standaard is een regelhoogte ongeveer 1,2 em. Hier komt een iets grotere regelhoogte beter uit. Als eenheid gebruik ik em, zodat ook gebruikers van Internet Explorer de regelhoogte kunnen veranderen.

#een-tekst-1

Voor dit element geldt ook de eerder bij #een-tekst span opgegeven css, voor zover die hier niet wordt gewijzigd.

Het element met id="een-tekst-1". Dit is de <span> waarbinnen de eerste regel van de tekst uit de pop-up staat: 'Wil jij de tanden'.

width: 7.8em; Afbeelding 17: ook bij een grote letter is de tekst nog leesbaar

Breedte. Bij #een-tekst span is de <span> in een blok-element veranderd en heeft een achtergrondkleur gekregen. Als geen breedte wordt opgegeven, vult de <span> de volle breedte van z'n ouder, zoals op de afbeelding iets hierboven is te zien, waardoor de achtergrondkleur buiten de wolk komt te staan.

Als eenheid wordt em gebruikt, zodat de breedte meegroeit met een eventueel grotere lettergrootte. Hierdoor blijft de tekst goed te lezen, ook als deze zo groot wordt dat de tekst buiten de wolk komt te staan.

Op de afbeelding is de tekst tot 200% vergroot en staat dus ruim buiten de wolk. Door de breedte in em en de gekleurde achtergrond is de tekst toch nog goed te lezen, hoewel bij zo'n sterke vergroting een heel klein stukje tekst wegvalt achter de knop met de link.

margin-left: 120px; Afbeelding 18: tekst staat niet op de goede plaats

Met behulp van een marge links op de juiste plaats binnen de wolk neerzetten. Zonder marge aan de linkerkant wordt de tekst gewoon links in de ouder van de <span> (hier is dat span#een-tekst) neergezet, waardoor de tekst onder de krokodil zou verdwijnen, zoals op de afbeelding is te zien.

#een-tekst-2

{width: 6em; margin-left: 134px;} #een-tekst-3 {width: 4em; margin-left: 147px;} #een-tekst-4 {width: 3.8em; margin-left: 153px;} #een-tekst-5 {width: 3.8em; margin-left: 154px;} #een-tekst-6 {width: 6em; margin-left: 142px;} #een-tekst-7 {width: 12em; margin-left: 52px;} #een-tekst-8 {width: 10em; margin-left: 60px;}

Voor deze elementen geldt ook de eerder bij #een-tekst span opgegeven css, voor zover die hier niet wordt gewijzigd.

De elementen met id="een-tekst-2" tot en met id="een-tekst-8": de <span>'s met de tweede tot en met achtste regel tekst. De uitleg is precies hetzelfde als die bij #een-tekst-1 gelijk hierboven, alleen zijn de waarden bij de eigenschappen anders.

span#een-tekst-9

Voor dit element geldt ook de eerder bij #een-tekst span opgegeven css, voor zover die hier niet wordt gewijzigd.

De <span> met id="een-tekst-9". De <span> met de negende en laatste regel: '(Alleen voor kinderen met drie armen!)'. Deze selector is iets langer dan die van de eerste acht regels met tekst: hij begint met span.

Bij #een-tekst span wordt een lettergrootte van 0,95 em opgegeven aan alle <span>'s binnen #een-tekst. Daar valt ook deze <span> onder.

Hieronder wordt de lettergrootte van deze <span> verkleind. Normaal genomen zou de regel hieronder winnen van de regel bij #een-tekst-span, omdat hij lager in de css staat. In dit geval gebeurt dat echter alleen, als deze selector met span begint.

#een-tekst span heeft een id (#een-tekst) én een element (span) in de selector.

#een-tekst-9 (zonder span aan het begin) telt alleen een id (#een-tekst-9). Daardoor heeft de eerste regel meer specificiteit, meer 'gewicht', en wint deze toch van de tweede regel, ook al staat deze lager.

span#een-tekst-9 heeft ook een id (#een-tekst-9) én een element (span), net zoals #een-tekst span. De regel heeft nu evenveel specificiteit als #een-tekst span. En nu wint deze regel wel, omdat hij lager in de css staat.

width: 18.5em;

Breedte. Meer uitleg is te vinden bij #een-tekst-1.

font-size: 0.72em;

Iets kleinere lettergrootte dan de rest van de pop-up. Als eenheid gebruik ik em, zodat ook gebruikers van Internet Explorer de lettergrootte kunnen veranderen.

margin: 5px 0 0 38px;

Aan de bovenkant 5 px marge, rechts en onder geen marge en links 38 px. Waarmee deze regel op de juiste plaats komt te staan.

#een:focus a, #een:hover a, #een a:focus

Drie selectors.

#een: het element met id="een". Dit is de <li> waar de <a> die bij het eerste puzzelstukje hoort in zit. Met deze <a> moet iets worden gedaan.

#een:focus a: doe iets met de <a> als li#een focus heeft. (Meer over focus bij :focus.)

#een:hover a: doe iets met de <a> als over li#een wordt gehoverd.

#een a:focusM: doe iets met de <a> binnen li#een, maar alleen als de <a> focus heeft.

Deze laatste selector is voor gebruikers van het toetsenbord, meer daarover bij :focus.

top: 66px; left: 64px;

Bij a zijn alle <a>'s absoluut gepositioneerd en met left: -20000px; links buiten het scherm geparkeerd. Hier wordt de <a> weer op het scherm gezet. Met deze top en left staat de knop goed ten opzichte van de pop-up met tekst en krokodil.

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

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

Deze eigenschap zorgt voor een vertraging van 'n halve seconde bij het zichtbaar maken van de knop met de link.

Bij a is de knop met de <a> links buiten het scherm geparkeerd met left: -20000px;. Hierboven is de knop weer binnen het scherm gezet met left: 64px;.

Als je bij transition-delay geen eigenschappen opgeeft, zoals hier het getal is, geldt de eigenschap voor álle veranderingen. Hier is de enige verandering left. Hierboven staat weliswaar ook top, maar dat staat niet bij a, dus dat verandert niet. Alleen left staat bij a én hier, dus in dit geval mogen alle veranderingen onder transition-delay vallen. (Nou ja, 'alle'..., dat is er hier dus maar eentje.)

De normale toestand is left: -20000px;, zoals opgegeven bij a. Bij hoveren of focus wordt dat veranderd naar left: 64px;. Door het gebruik van transition-delay wordt dit 'n halve seconde vertraagd. 'n Halve seconde, omdat als waarde 0.5s is opgegeven.

Als je op een touchscreen het scherm toevallig precies op de plaats aanraakt, waar een knop met link verschijnt, dan wordt in sommige browsers gelijk die link gevolgd. In sommige browsers kun je dat voorkomen als je het wereldrecord vinger terugtrekken evenaart, maar dat lukt zelfs mij niet altijd, terwijl ik toch heel soepele, lenige, bevallige vingertjes heb. Kortom: dat schiet niet op.

Als je die knop nou met 'n heel kleine vertraging laat verschijnen, dan is je vinger alweer van het scherm af, voordat de link zichtbaar wordt. En kan de link dus nog niet worden aangeraakt en gevolgd, omdat de link er stomweg nog niet staat.

Een vertraging van 'n halve seconde valt nauwelijks op, omdat gelijktijdig een pop-up wordt geopend. 0,5 seconde is minimaal noodzakelijk, omdat Chrome for iOS dat nodig heeft. Andere browsers hebben aan 0,3 seconde genoeg.

Internet Explorer 9 kent transition-delay niet. Maar deze browser wordt op mobiel zo weinig (meer) gebruikt dat hij in de statistieken zelfs volledig onvindbaar is.

/********** Tweede puzzelstukje (dansletters) **********/

Bij grotere bestanden is het vaak handig een soort 'hoofdstukjes' aan te brengen. Als je zoekt naar meerdere sterretjes, kun je zo van deel naar deel springen, wat vaak nogal wat zoekwerk kan besparen. En kan voorkomen dat je in het verkeerde deel van een bestand gaat zitten werken.

#twee span

Alle <span>'s binnen het element met id="twee".

Dat is de <span>, waarbinnen de tweede pop-up zit, die met de dansletters. En alle <span>'s die daar weer binnen zitten, want het gaat om álle <span>'s binnen #twee.

top: 0; left: -141px;

Helemaal bovenaan en 150 px naar links neerzetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is de <li> waar deze <span> in zit: li#twee.

Omdat de bovenkant van die <li> precies gelijk staat met de bovenkant van de puzzelafbeelding, komt de bovenkant van deze <span>, en dus de daarin zittende pop-up, ook precies gelijk met de bovenkant van de puzzel. Hierdoor verdwijnt ook in lagere browservensters niets aan de bovenkant van het venster, omdat de pop-up te hoog staat.

Omdat de pop-up wel 150 px links en rechts iets buiten de puzzel uitsteekt, zou in smallere vensters wel links en rechts een deel van de pop-up wegvallen. Daarom wordt later bij @media screen and (max-width: 470px), (max-height: 570px) left aangepast voor smallere vensters.

Dit heeft alleen effect op <span>'s die zijn gepositioneerd. Bij li > span zijn de <span>'s die directe kinderen van de <li> zijn absoluut gepositioneerd. Dit heeft alleen effect op die <span>, de <span> waarbinnen de hele pop-up zit. Omdat dieper geneste <span>'s niet zijn gepositioneerd, negeren die dit gewoon.

#twee-tekst

Voor dit element geldt ook de eerder bij #twee span opgegeven css, voor zover die hier niet wordt gewijzigd.

Het element met id="twee-tekst". Dit is de <span>, waarbinnen de dansende letters zitten. Binnen deze <span> zit elk woord weer in een eigen <span>. Hierdoor kun je op een simpele manier de afstand tussen de woorden en dergelijke regelen.

background: #0f9;

Achtergrondkleurtje.

display: block;

Een <span> is een inline-element. Door het te veranderen in een blok-element, kunnen eigenschappen als breedte en hoogte worden gebruikt.

width: 370px;

370 px breed.

height: 380px;

380 px hoog.

border: 10px outset #0ff;

Meerkleurige rand.

padding: 10px;

Afstand tussen letters en rand van de pop-up.

#twee-tekst span

Voor deze elementen geldt ook de eerder bij #twee span opgegeven css, voor zover die hier niet wordt gewijzigd.

De <span>'s binnen het element met id="twee-tekst". Dit zijn de <span>'s waarbinnen de dansende letters zitten: voor elk woord een aparte <span>.

Omdat er ook een afbeelding en een knop met een link in de pop-up staan, worden hieronder wat correcties voor positie en dergelijke van de afzonderlijke <span>'s aangebracht. Een aantal eigenschappen is echter hetzelfde voor al deze <span>'s, dus die kunnen hier in één keer worden opgegeven.

display: inline-block;

Een <span> is een inline-element. Daardoor kun je geen eigenschappen als hoogte gebruiken. Je zou van de <span>'s blok-elementen kunnen maken, maar dan komt elke <span> op een nieuwe regel te staan. Dat is niet de bedoeling, want in elke <span> zit een woord. En elk woord, ook korte woorden, zou dan op een nieuwe regel komen te staan.

inline-block verenigt in dit geval het beste van twee werelden: de <span>'s komen naast elkaar te staan (tot de regel vol is), maar eigenschappen als hoogte en dergelijke kunnen toch worden gebruikt.

height: 50px;

Hoogte. In de <span>'s zitten afbeeldingen met letters. De hoogte van die afbeeldingen varieert nogal. De makkelijkste manier om die verschillen te corrigeren is het geven van een hoogte aan de <span>, want daar staan ze nou eenmaal allemaal in.

#twee-tekst span img

Alle afbeeldingen die in een <span> zitten die weer binnen het element met id="twee-tekst" zit. Dit zijn de dansende letters.

De afbeelding van de olifant zit niet in een <span>, dus die valt niet onder deze selector. Die olifant wordt hier gelijk onder bij #twee-tekst > img apart afgehandeld.

background: #0f9;

Zelfde achtergrondkleur als de pop-up.

De afbeeldingen hebben een doorzichtige achtergrond. Bij inzoomen (vergroten) kan het zijn dat de onderste woorden net niet meer binnen de pop-up vallen, waardoor ze geen achtergrond hebben en heel moeilijk leesbaar zijn. (Eigenlijk zou dit niet moeten gebeuren, maar door afrondingsverschillen passen in sommige browsers net niet meer alle woorden naast elkaar, waardoor de laatste regel te laag komt te staan.)

Bij een grotere lettergrootte wordt de tekst in de knop met de link vergroot, waardoor niet meer alle woorden naast elkaar passen. Ook nu komt de onderste regel buiten de pop-up te staan.

Door een achtergrondkleur aan de afbeeldingen te geven, blijven ze goed leesbaar, ook als ze buiten de pop-up staan.

margin-left: -3px;

Door alle afbeeldingen met letters iets naar links te verplaatsen, passen er meer naast elkaar. Dat kan bij deze letters makkelijk, want de letters hebben vrij veel lege ruimte aan de zijkant.

#twee-tekst > img

Alle <img>'s binnen het element met id="twee-tekst" die een direct kind van #twee-tekst zijn. Dat ze een direct kind moeten zijn, wordt aangegeven met het teken >.

Onderstaande <img> is een direct kind van #twee-tekst:

<li id="twee-tekst"> <img> </li>

De <img> hieronder is geen direct kind van #twee-tekst, omdat er een <span> tussen #twee-tekst en <img> zit:

<li id="twee-tekst"> <span> <img> </span> </li>

In dit geval is er maar één <img> die een direct kind van #twee-tekst is: de afbeelding met de olifant.

float: left;
Afbeelding 19: zonder float wordt de afbeelding gewoon in de tekst gezet
Afbeelding 19: links met float bij de <img>, rechts zonder float.

In tegenstelling tot wat veel mensen denken, is een <img> een gewoon inline-element, net zoals gewone tekst. Weliswaar een inline-element met wat bijzondere eigenschappen, maar het blijft een inline-element. Een <span> is ook een inline-element. Normaal genomen wordt de <img> dus gewoon links gezet en komen rechts daarvan één of meer <span>'s, tot de regel vol is.

Op de afbeelding rechts is de olifant eigenlijk gewoon 'n soort letter: hij staat gezellig samen met de <span> met het woord 'vinden' op één regel, netjes op dezelfde hoogte. Dat die regel wat hoog is, komt omdat de afbeelding met de olifant wat hoog is. De regelhoogte past zich aan die hoogte aan.

Op de afbeelding links is float gebruikt. De olifant wordt nu los van de rest neergezet, niet als inline-element. In de ruimte rechts van de olifant worden nu net zoveel <span>'s neergezet als er in passen. In dit geval zijn dat de twee <span>'s met de woorden 'vinden' en 'zoiets'.

margin: 5px 20px 0 0;

Marge van 5 px aan de bovenkant, 20 px rechts en onder en links geen marge.

#twee-tekst span:first-of-type, #twee-tekst span:nth-of-type(6), #twee-tekst span:nth-of-type(10)

Voor deze elementen geldt ook de eerder bij #twee span opgegeven css, voor zover die hier niet wordt gewijzigd.

Elk woord zit in een aparte <span>. In totaal zijn er elf woorden, dus er zijn elf <span>'s. Op een aantal regels staan twee woorden naast elkaar. Het eerste woord daarvan krijgt rechts een extra marge, zodat er wat afstand is tussen de twee woorden.

Er zijn elf <span>'s, die netjes op volgorde binnen #twee-tekst zitten. In totaal moeten drie woorden een marge rechts krijgen. Het simpelste zijn die woorden te bereiken via het volgnummer van de <span> waar ze in zitten.

(Er zijn vier regels met twee woorden, maar de afstand tussen 'geschikt' en 'voor' op de tweede regel is uit zichzelf groter dan bij de andere drie, dus die wordt hieronder apart afgehandeld.)

#twee-tekst: alleen bepaalde <span>'s van de tweede pop-up moeten deze marge krijgen. Zou je dit niet beperken tot #twee-tekst, dan zou élke <span> op de pagina die toevallig hetzelfde volgnummer heeft deze marge krijgen.

span:first-of-type: het eerste element van deze soort. Omdat er span aan het begin staat, gaat het hier om de eerste <span>. Dit is de <span>, waarin 'niet' zit, het linkerwoord op de eerste regel. (In plaats van :first-of-type kun je ook :nth-of-type(1) gebruiken, dat betekent precies hetzelfde.)

span:nth-of-type(6): vrijwel hetzelfde als die gelijk hierboven, maar hier gaat het om de zesde <span>. Dit is de <span>, waarin 'maar' zit, het linkerwoord op de vierde regel.

span:nth-of-type(10): ook weer vrijwel hetzelfde, maar nu voor de tiende <span>. Dit is de <span> waarin 'juist' zit, het linkerwoord op de onderste regel.

margin-right: 25px;

Marge van 25 px aan de rechterkant, zodat er wat afstand tot het volgende woord ontstaat.

#twee-tekst span:nth-of-type(3)

{margin-right: 13px;}

Voor dit element geldt ook de eerder bij #twee span opgegeven css, voor zover die hier niet wordt gewijzigd.

Exact hetzelfde verhaal als gelijk hierboven, maar dan voor de derde <span> met rechts een marge van slechts 13 px.

#twee:focus a, #twee:hover a, #twee a:focus

{top: 26px; left: 130px; -webkit-transition-delay: 0.5s; transition-delay: 0.5s;}

Als de tweede <li> focus heeft, of als over de tweede <li> (het tweede puzzelstukje) wordt gehoverd, of als de tweede <a> focus heeft, toon dan de knop met de link.

Dit werkt precies hetzelfde als bij de eerste <li>, waarvan de uitleg te vinden is bij #een:focus a, #een:hover a, #een a:focus. Alleen de waarden bij top en left zijn anders, omdat de knop op een andere plaats komt te staan.

/************ Zesde puzzelstukje (uitgang) *************/

Bij grotere bestanden is het vaak handig een soort 'hoofdstukjes' aan te brengen. Als je zoekt naar meerdere sterretjes, kun je zo van deel naar deel springen, wat vaak nogal wat zoekwerk kan besparen. En kan voorkomen dat je in het verkeerde deel van een bestand gaat zitten werken.

#zes img

De <img>'s binnen het element met id="zes". Er is hier maar één afbeelding: de afbeelding van de uitgang bij het zesde puzzelstukje.

display: none;

Afbeelding verbergen.

position: absolute;

Om de afbeelding op de juiste plaats neer te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier li#zes.

left: -130px;

Afbeelding 130 px naar links verplaatsen, zodat hij binnen de puzzel komt te staan.

#zes:focus a, #zes:hover a, #zes a:focus

{top: -20px; left: -64px; -webkit-transition-delay: 0.5s; transition-delay: 0.5s;}

Als de zesde <li> focus heeft, of als over de zesde <li> (het zesde puzzelstukje) wordt gehoverd, of als de zesde <a> focus heeft, toon dan de knop met de link.

Dit werkt precies hetzelfde als bij de eerste <li>, waarvan de uitleg te vinden is bij #een:focus a, #een:hover a, #een a:focus. Alleen de waarden bij top en left zijn anders, omdat de knop op een andere plaats komt te staan.

#zes:focus img, #zes:hover img, #zes a:focus + img

#zes:focus img: doe iets met de de <img>'s binnen het element met id="zes" maar alleen als #zes focus heeft. #zes is de zesde <li>. Daarbinnen zit maar één <img>: het plaatje met de uitgang.

#zes:hover img: precies hetzelfde als gelijk hierboven, maar dan bij hoveren over de zesde <li>.

#zes a:focus + img: doe iets met de <img>'s die gelijk op een <a> volgen binnen het element met id="zes", maar alleen als de <a> focus heeft.

De + geeft aan dat de <img> gelijk op de <a> moet volgen in de html, en beide moeten dezelfde ouder hebben. Die gemeenschappelijke ouder is hier li#zes.

Deze derde selector is bedoeld voor mensen die de Tab-toets gebruiken om links af te lopen. Meer daarover is te vinden bij Tabindex.

display: block;

En wat moet er dan voor wonderschoons gebeuren met deze <img>? Hij moet worden getoond, wat het hoogste is wat een afbeelding in het leven kan bereiken.

Bij #zes img is de afbeelding verborgen met display: none;, hier wordt hij weer zichtbaar gemaakt.

/*********** Negende puzzelstukje (mail) ****************/

Afbeelding 20
Afbeelding 20: de pop-up en knop die bij het negende puzzelstukje horen.

Bij grotere bestanden is het vaak handig een soort 'hoofdstukjes' aan te brengen. Als je zoekt naar meerdere sterretjes, kun je zo van deel naar deel springen, wat vaak nogal wat zoekwerk kan besparen. En kan voorkomen dat je in het verkeerde deel van een bestand gaat zitten werken.

#negen > span

Voor dit element geldt ook de eerder bij li > span opgegeven css, voor zover die hier niet wordt gewijzigd.

Alle <span>'s die een direct kind van het element met id="negen" zijn. Dit is de <span> waarbinnen de afbeelding en de <span>'s met de eigenlijke tekst zitten.

Het teken > geeft aan dat het om directe kinderen moet gaan:

<li> <span></span> </li>

In onderstaande code is de buitenste <span> een direct kind van li#negen, waarvoor deze selector dus geldt. De binnenste <span> is geen direct kind van de <li>, maar van de buitenste <span>, dus daarvoor geldt deze selector niet:

<li id="negen"> <span> <span></span> </span> </li>

In dit geval is er maar één span een direct kind van li#negen. Het gebruik van de > geeft de mogelijkheid css op te geven die alleen die ene <span> bestrijkt, zonder dat dit dieper geneste <span>'s beïnvloedt.

background: #fc9;

chtergrondkleurtje.

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, is er nog niets aan de hand, want dan veranderen achtergrond- en voorgrondkleur geen van beide.

display: block;

Van zichzelf is een <span> een inline-element. Door het te veranderen in een blok-element kun je eigenschappen als breedte gebruiken. Maar eigenlijk zou dat hier niet nodig moeten zijn. Bij li > span is deze <span> absoluut gepositioneerd, waardoor de <span> al in een soort blok-element is veranderd.

Daar wordt deze <span> ook verborgen met display: none;, wat hier dus weer ongedaan wordt gemaakt met display: block;.

Waarom al dat gedoe hier nodig is en display: block; wordt gebruikt, staat iets hieronder bij transition-delay: 0.1s;.

width: 200%;

Een breedte in procenten wordt altijd genomen ten opzichte van de ouder van het element. Dat is hier li#negen. De pop-up wordt dus twee keer zo breed als de bijbehorende <li>. En omdat de <li> weer even breed is als een puzzelstukje, wordt afbeelding twee keer zo breed als een puzzelstukje.

-moz-hyphens: auto; -ms-hyphens: auto; -webkit-hyphens: auto; hyphens: auto;

Hier staat in feite vier keer hetzelfde: hyphens: auto;. Waarom dat zo is, staat bij De voorvoegsels -moz-, -ms- en -webkit-.

Omdat de ruimte voor de tekst hier en daar wat krap is, wordt automatisch afbreken aangezet. Dit werkt niet in alle browsers, maar dat maakt niet zoveel uit. Waar het wel werkt, is het meegenomen.

border: red solid 1px;

Rood randje.

padding: 5px;

Afstand tussen tekst en rand van de pop-up.

left: -20000px;

Links buiten het scherm parkeren, zodat de pop-up onzichtbaar is. Waarom hiervoor is gekozen en niet voor display: none; staat gelijk hieronder bij transition-delay: 0.1s.

transition-delay: 0.1s;

Zodra een pop-up een afbeelding bevat, heeft Internet Explorer 11 op een touchscreen daar om een of andere reden problemen mee: de pop-up blijft niet open. Ik heb geen oplossing kunnen vinden die bij elke pop-up werkt, elke oplossing is weer anders. pointer-events: none; werkt wel overal, maar is helaas alleen bij de eerste pop-up bruikbaar, zoals beschreven bij #een span. Bij de zesde pop-up werkt display: none; bij de afbeelding, hier niet, om wat voor reden dan ook.

transition-delay is een deel van de oplossing bij deze pop-up. Daarom is hier -webkit-transition-delay niet gebruikt, want het is alleen nodig voor Internet Explorer, en die heeft niets aan het voorvoegsel -webkit-.

Na enig gepuzzel blijkt deze pop-up in Internet Explorer 11 ook op een touchscreen geopend te blijven door de volgende combinatie van display, left en transition-delay:

display: block; (iets hierboven opgegeven). Bij li > span is ook deze <span> verborgen met display: none;, maar dan blijft de pop-up niet geopend. De pop-up moet al bestaan voor het touchscreen wordt aangeraakt. Dus display: none; is voor deze <span> niet bruikbaar.

left: -20000px;: omdat de pop-up al aanwezig is, wordt deze – anders dan bij de andere pop-ups – verborgen door hem links buiten het scherm te parkeren. Als hij getoond moet worden, wordt hij dan weer op het scherm gezet.

transition-delay: 0.1s;: ten slotte is dan nog een minieme vertraging van een tiende seconde nodig. Vraag me niet waarom.

Deze eigenschap zorgt voor een vertraging, als iets wordt veranderd bij :focus, :hover, en dergelijke. Als je geen eigenschappen vermeldt, heeft de vertraging betrekking op álle veranderingen.

Bij #negen:focus > span, #negen:hover > span, # negen a:focus + span wordt left: -120%; opgegeven. Dat is de enige eigenschap die daar wordt gebruikt, dus in dit geval mag transition-delay gewoon voor álle eigenschappen gelden.

#negen span:nth-of-type(3)

{font-size: 0.95em;} #negen span:nth-of-type(5) {font-size: 0.9em;} #negen span:nth-of-type(6) {font-size: 0.85em;} #negen span:nth-of-type(7) {font-size: 0.8em;}

Eerst de selector.

#negen: de werking moet beperkt worden tot de elementen die bij de negende pop-up horen, de pop-up binnen li#negen.

Binnen li#negen zitten vijf <span>'s met doorlopende tekst en twee <span>'s met aparte blokjes tekst. De zeven <span>'s samen vormen een aaneengesloten rijtje. De doorlopende tekst zit in de eerste, derde, vijfde, zesde en zevende <span>. Die doorlopende tekst wil ik steeds iets kleiner maken.

span:nth-of-type(...): het nummer tussen de haakjes geeft aan het hoeveelste element van die soort het moet zijn. Omdat het achter span staat, gaat het hier om de zoveelste <span>. In de vier bovenstaande selectors zijn de cijfers 3, 5, 6 en 7 ingevuld, dus het gaat in dit geval om de derde, vijfde, zesde en zevende <span>.

De eerste <span> doet niet mee, ook al staat daar doorlopende tekst in, want daarvan wordt de lettergrootte nog niet verkleind.

Afbeelding 21: de spans met tekst hebben elk even andere kleur, zodat ze zijn te onderscheiden

Bij elk van de vier <span>'s wordt de tekst steeds iets kleiner gemaakt met behulp van font-size. Als eenheid gebruik ik em, zodat ook gebruikers van Internet Explorer de lettergrootte kunnen veranderen.

De tekst is te lang voor de meeste browservensters, maar dat maakt niet uit. Wat niet past, verdwijnt gewoon aan de onderkant van het venster. In dit geval is dat verdwijnen opzettelijk, dus het is geen probleem.

Op de hiernaast staande afbeelding zijn de <span>'s met doorlopende tekst even met kleurtjes herkenbaar gemaakt:

eerste <span>: tekst met de gewone roze achtergrond.

tweede <span>: het blokje tekst rechts met de gele achtergrond.

derde <span>: de tekst met de blauwe achtergrond.

vierde <span>: het blokje tekst links met de grijze achtergrond.

vijfde <span>: de tekst met de rode achtergrond.

zesde <span>: de tekst met de groene achtergrond.

zevende <span>: de tekst onderaan met de gele achtergrond.

Alleen van de derde, vijfde, zesde en zevende <span> wordt hier de lettergrootte verkleind: steeds iets kleiner.

#negen img

Alle <img>'s binnen het element met id="negen". Er is zit maar één afbeelding binnen li#negen: de postbus.

float: right; Afbeelding 22: tekst staat niet naast de afbeelding

In tegenstelling tot wat veel mensen denken, is een <img> een gewoon inline-element, net zoals tekst. Weliswaar een inline-element met wat bijzondere eigenschappen, maar het blijft een inline-element.

Als de <img zonder meer wordt weergegeven, komt deze dan ook gewoon naast de tekst op dezelfde regel te staan, zoals op de afbeelding hiernaast is te zien. Waarbij de regelhoogte zich aan de hoogte van de afbeelding aanpast.

Afbeelding 23: tekst staat naast de afbeelding

Door de afbeelding naar rechts te floaten, wordt deze zo hoog mogelijk en vervolgens zo ver mogelijk naar rechts neergezet. De afbeelding komt nu los van de tekst te staan. Links van de afbeelding wordt de lege ruimte nu volledig opgevuld met tekst, zoals op de afbeelding hiernaast is te zien.

#idee

Afbeelding 24: apart stukje tekst

Het element met id="idee". Dit is de <span>, waarbinnen het gele vakje met tekst rechts binnen de pop-up staat.

background: yellow;

Gele achtergrond.

color: #411;

Donkerbruine (of zoiets, ik ben kleurenzwak) voorgrondkleur. Dit is onder andere de kleur van de tekst.

width: 40%;

Een breedte in procenten wordt altijd genomen ten opzichte van de ouder van het element. Dat is hier de <span> waar de hele pop-up in zit. Die is bij #negen > span met width: 200%; zelf weer twee keer zo breed gemaakt als de ouder daarvan: li#negen. Deze <li> is even breed als 'n stukje van de puzzel. De <span> met de pop-up is dus twee puzzelstukjes breed.

Dit gele blokje wordt krijgt 40% van die breedte van twee puzzelstukjes naast elkaar.

float: right; Afbeelding 25: zonder floaten komt het aparte blokje tekst gewoon tussen de andere tekst te staan

De tekst staat in een gewone <span>. Daardoor zou de tekst gewoon net als alle andere tekst worden weergeven: op een regel. Dat dat niet helemaal goed gaat, is hiernaast te zien.

Door de <span> naar rechts te floaten, wordt deze zo hoog mogelijk en vervolgens zo ver mogelijk naar rechts neergezet. De andere tekst komt dan gewoon links daarvan te staan.

Een <span> is van zichzelf een inline-element. Het floaten verandert de <span> in een soort blok-element, waardoor ook eigenschappen als breedte bruikbaar worden.

font-size: 1.1em;

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

margin: 3px 0 0 3px;

Kleine marge boven en links van de <span>, zodat er wat ruimte komst tussen de rest van de tekst en het gele blokje.

border: black solid 1px;

Zwart randje.

border-radius: 8px;

Ronde hoeken.

padding: 3px;

Kleine ruimte tussen tekst in en rand van het blokje.

#vraag-eerst

Afbeelding 26: apart stukje tekst

Het element met id="vraag-eerst". Dit is de <span>, waarbinnen de tekst over de toestemming staat.

background: #ddd;

Achtergrondkleurtje.

float: left;

Tekst niet tussen de andere tekst neerzetten. De uitleg is iets hierboven te vinden bij #idee onder float: right;. Alleen wordt hier niet naar rechts, maar naar links gefloat.

margin: 3px 3px 0 0;

Boven en rechts marge van 3 px, zodat de rest van de tekst niet gelijk tegen het blokje aan komt te staan.

border: solid blue 2px;

Blauw randje.

padding: 2px;

Kleine afstand tussen tekst in en rand van het blokje.

#negen:focus a, #negen:hover a, #negen a:focus

{top: -25px; left: -8px; -webkit-transition-delay: 0.5s; transition-delay: 0.5s;}

Als de negende <li> focus heeft, of als over de negende <li> (het negende puzzelstukje) wordt gehoverd, of als de negende <a> focus heeft, toon dan de knop met de link.

Dit werkt precies hetzelfde als bij de eerste <li>, waarvan de uitleg te vinden is bij #een:focus a, #een:hover a, #een a:focus. Alleen de waarden bij top en left zijn anders, omdat de knop op een andere plaats komt te staan.

#negen:focus > span, #negen:hover > span, #negen a:focus + span

#negen:focus > span: doe iets met de de <span>'s die een direct kind van het element met id="negen"zijn, maar alleen als #negen focus. heeft. #negen is de negende <li>, waarin pop-up en knop zitten die bij het negende puzzelstukje horen.

Het teken > geeft aan, dat het alleen <span>'s zijn die een direct kind van #negen zijn. Onderstaande <span> is een direct kind van #negen:

<li id="negen"> <span> </li>

De binnenste <span> hieronder is geen direct van #negen, omdat er een <span> tussen de binnenste <span> en de <li> zit. De buitenste <span> is wel een direct kind van li#negen.

<li id="negen"> <span> <span> </span> </li>

#negen:hover > span: precies hetzelfde verhaal als gelijk hierboven, maar nu bij hoveren over li#negen.

#negen a:focus + span doe iets met de <span>'s die gelijk op een <a> volgen binnen het element met id="negen", maar alleen als de <a> focus heeft.

De + geeft aan dat de <span> gelijk op de <a> moet volgen in de html, en beide moeten dezelfde ouder hebben. Die gemeenschappelijke ouder is hier li#negen.

Deze derde selector is bedoeld voor mensen die de Tab-toets gebruiken om links af te lopen. Meer daarover is te vinden bij Tabindex.

left: -120%;

Bij #negen > span is de <span> met de pop-up links buiten het scherm geparkeerd. Hier wordt hij terug op het scherm gezet, waardoor hij zichtbaar wordt.

Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier li#negen. Dit geldt ook als je als eenheid geen px, maar procenten gebruikt.

Ik gebruik procenten, zodat de plaatsing mee verandert bij smallere browservensters. Als je px of een andere absolute eenheid gebruikt, gebeurt dat niet. Een deel van de pop-up zou daardoor rechts buiten het venster verdwijnen.

In heel kleine vensters is dat nog steeds zo, daarom wordt de plaatsing daarvoor bij @media screen and (max-width: 380px), (max-height: 540px) aangepast.

Bij 0% zou de linkerkant van de pop-up precies gelijk komen te staan met de linkerkant van li#negen. Bij #negen > span is aan de pop-up een breedte van 200% gegeven, twee keer zo breed als li#negen. Bij -100% zou de pop-up daardoor voor de helft links van li#negen komen te staan.

Hier is -120% opgegeven, daardoor blijft er aan de rechterkant van de pop-up een stukje van de eronder liggende li#negen – en dus het daarmee corresponderende puzzelstukje – zichtbaar.

/********** Aanpassingen voor kleinere vensters **********/

Bij grotere bestanden is het vaak handig een soort 'hoofdstukjes' aan te brengen. Als je zoekt naar meerdere sterretjes, kun je zo van deel naar deel springen, wat vaak nogal wat zoekwerk kan besparen. En kan voorkomen dat je in het verkeerde deel van een bestand gaat zitten werken.

Normaal genomen worden media queries door de meeste mensen van klein naar groot neergezet, ook door mij. De pagina wordt als het ware afgestemd op de kleinste weergave. Voor grotere browservensters worden dan later met behulp van media queries aanpassingen aangebracht.

Die volgorde heb ik hier niet aangehouden. Hier staan de aanpassingen voor kleinere vensters juist onderaan. Het gaat hier, voor een deel, om heel specifieke aanpassingen voor één pop-up en dergelijke, en het zou – volgens mij – in dit geval verwarrend zijn om daarmee te beginnen.

Het is een tamelijk grote serie media queries, maar ze bestrijken zo'n beetje alle verschillende mogelijkheden. Zou je nog meer puzzelstukjes afmaken, dan zouden veel daarvan waarschijnlijk gebruik kunnen maken van al bestaande media queries voor de vier stukjes die al klaar zijn.

css voor vensters in landschapsstand en lager dan 350 px

@media screen and (orientation: landscape) and (max-height: 350px)

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

@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 @media-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. Een menu printen is wat zinloos.

and: er komt nog een voorwaarde, waaraan moet worden voldaan.

(orientation: landscape): het scherm moet in landschapsstand zijn.

Een scherm kent twee standen: landscape (landschap, liggend) en portrait (portret, staand). (Allerlei andere standen zoals bijvoorbeeld lezend in bed tellen hier niet mee. Liggend of staand, dat is het, al hang je met je tablet ondersteboven heen en weer te zwaaien aan de trapeze.)

Dit is bedoeld voor tablets, smartphones, en dergelijke. Voor desktop monitors zal de stand meestal niet echt van belang zijn. In combinatie met de lage maximumhoogte van 350 px wordt helemaal duidelijk, dat dit niet voor de desktop is bedoeld. Maar in veel browsers werkt dit ook op de desktop. Als je de grootte van het venster verandert, zodat het lager dan 350 px en breder dan 350 px (landschapsstand) wordt, werkt dit vaak ook op de desktop.

and: er komt nog een voorwaarde, waaraan moet worden voldaan.

(max-height: 350px): het browservenster mag niet hoger zijn dan 350px. Is het venster hoger, 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 (orientation: landscape) and (max-height: 350px) { 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 }.

#wrapper

Het element met id="wrapper". Dit is de div waar de hele handel in staat.

-ms-transform: scaleX(0.6); -webkit-transform: scaleX(0.6); transform: scaleX(0.6);

Hier staat in feite drie keer hetzelfde: transform: scaleX(0.6); Waarom dat zo is, staat bij De voorvoegsels -moz-, -ms- en -webkit-.

Bij #wrapper heeft div#wrapper, waar de hele handel in staat, een maximale hoogte van 100% gekregen. Dat is bedoeld voor lagere browservensters, om te voorkomen dat een deel van de <li>'s buiten het venster komt te staan en daarmee onbereikbaar is.

Dit geldt ook voor de inhoud van div#wrapper. Waaronder de puzzelafbeelding, want die mag niet hoger of breder dan div#wrapper zijn, zoals met behulp van max-height en max-width opgegeven bij nav > img. Als in een laag venster de hoogte van de afbeelding wordt aangepast, maar niet de breedte, krijg je 'n lachspiegeleffect. Om dat zo goed mogelijk te corrigeren, wordt de breedte aangepast.

Afbeelding 27
Afbeelding 27: schermafbeelding van een scherm van 320 x 480 px. Links zonder schalen, rechts met. Ook rechts is nog steeds een vervorming aanwezig, maar aanzienlijk minder dan links.

transform is een eigenschap om van alles aan te passen. Hier wordt de transform-functie scaleX() gebruikt: schalen in horizontale richting. In dit geval wordt tot zes tiende verkleind. Omdat ook de afbeelding hieraan meedoet, wordt het lachspiegeleffect enigszins verminderd.

In Android browser en UC browser op Android is de puzzelafbeelding in zulke lage browservensters toch hoger dan het venster. Dat is een bug in die browsers, meer daarover bij Bekende problemen (en oplossingen).

li:empty:hover::after, li:empty:focus::after

{font-size: 0.7em;}

Bij li:empty:not(:focus):hover::after, li:empty:focus::after wordt bij hoveren een tekst tevoorschijn getoverd voor de nog niet in gebruik zijnde puzzelstukjes. Dat blijft hier allemaal hetzelfde werken, alleen wordt de lettergrootte wat verkleind voor deze kleine browservensters, anders past het niet.

Als eenheid gebruik ik em, zodat ook gebruikers van Internet Explorer de lettergrootte kunnen veranderen.

css voor vensters in landschapsstand en hoger dan 351 px en lager dan 479 px

@media screen and (orientation: landscape) and (min-height: 351px) and (max-height: 479px)

De opbouw van deze regel staat beschreven bij @media screen and (orientation: landscape) and (max-height: 350px). Er zijn twee verschillen: het browservenster moet minimaal 351 px hoog zijn: (min-height: 351px). En de maximale hoogte mag 479 px zijn: (max-height: 479px). Er zijn hier dus drie voorwaarden: liggend en een hoogte tussen 351 en 479 px.

#wrapper { -ms-transform: scaleX(0.8); -webkit-transform: scaleX(0.8); transform: scaleX(0.8);} li:empty:hover::after, li:empty:focus::after {font-size: 0.7em;}

Ook het verhaal voor de css is hetzelfde als hierboven bij @media screen and (orientation: landscape) and (max-height: 350px). Het is bedoeld voor browservensters die niet echt klein zijn, maar ook niet echt groot: pubervensters. De maat van de scaleX() is daarom iets aangepast.

css voor vensters smaller dan 360 px

@media screen and (max-width: 360px)

De opbouw van deze regel staat beschreven bij @media screen and (orientation: landscape) and (max-height: 350px). Er zijn twee verschillen: de stand van het browservenster maakt niet uit, dus orientation ontbreekt. En het gaat hier niet om een maximale hoogte, maar om een maximale breedte: (max-width: 360px).

#een a, #een span

De links binnen het element met id="een" en de <span>'s binnen het element met id="een". Dit zijn de link en de pop-up binnen li#een, die bij het eerste puzzelstukje horen.

-ms-transform: scale(0.9); -webkit-transform: scale(0.9); transform: scale(0.9);

Hier staat in feite drie keer hetzelfde: transform: scale(0.9);. Waarom dat zo is, staat bij De voorvoegsels -moz-, -ms- en -webkit-.

transform is een eigenschap om van alles aan te passen. Hier wordt de transform-functie scale() gebruikt: schalen in beide richtingen, horizontaal en verticaal. In dit geval wordt tot negen tiende verkleind. Omdat maar één getal is opgegeven, wordt in beide richting evenveel geschaald.

In zulke kleine browservensters is er wat te weinig ruimte voor pop-up en knop van het eerste puzzelstukje. Daarom worden ze iets verkleind.

#een a

De links binnen het element met id="een". Dat is er hier maar één: de link binnen li#een, die bij het eerste puzzelstukje hoort.

margin-left: 110px;

Een extra marge aan de linkerkant, omdat de knop met de link anders over de afbeelding en tekst van de pop-up heen komt te staan, want die wordt gelijk hieronder ook naar rechts verplaatst.

#een span

De <span>'s binnen het element met id="een". Dat is er hier maar één: de <span> met de pop-up binnen li#een, die bij het eerste puzzelstukje hoort.

left: -20px;

Bij #een span is de <span> met left: -120px; een eindje links buiten de puzzelafbeelding gezet. In dit soort smalle browservensters zouden krokodil en tekst daardoor grotendeels links buiten het venster verdwijnen. 100 px minder naar links zetten en het past weer.

Dit heeft alleen effect op <span>'s die zijn gepositioneerd. Bij li > span zijn de <span>'s die directe kinderen van de <li> zijn absoluut gepositioneerd. Dit heeft alleen effect op die <span>, de <span> waarbinnen de hele pop-up zit. Omdat dieper geneste <span>'s niet zijn gepositioneerd, negeren die dit gewoon.

css voor vensters breder dan 361 px en smaller dan 670 px

@media screen and (min-width: 361px) and (max-width: 670px)

De opbouw van deze regel staat beschreven bij @media screen and (orientation: landscape) and (max-height: 350px). Er zijn drie verschillen: de stand van het browservenster maakt niet uit, dus orientation ontbreekt. En het gaat hier niet om de hoogte, maar om de breedte. Het venster moet minstens 361 px (min-width: 361px) en hoogstens 670 px (max-width: 670px) breed zijn.

#een a

De links binnen het element met id="een". Dat is er hier maar één: de link binnen li#een, die bij het eerste puzzelstukje hoort.

margin-left: 150px;

Een extra marge aan de linkerkant, omdat de knop met de link anders over de afbeelding en tekst van de pop-up heen komt te staan, want die wordt gelijk hieronder ook naar rechts verplaatst.

#een span

De <span>'s binnen het element met id="een". Dat is er hier maar één: de <span> met de pop-up binnen li#een, die bij het eerste puzzelstukje hoort.

left: 0;

Bij #een span is de <span> met left: -120px; een eindje links buiten de puzzelafbeelding gezet. In dit soort smalle browservensters zouden krokodil en tekst daardoor grotendeels links buiten het venster verdwijnen. Daarom wordt left hier aangepast.

Dit heeft alleen effect op <span>'s die zijn gepositioneerd. Bij li > span zijn de <span>'s die directe kinderen van de <li> zijn absoluut gepositioneerd. Dit heeft alleen effect op die <span>, de <span> waarbinnen de hele pop-up zit. Omdat dieper geneste <span>'s niet zijn gepositioneerd, negeren die dit gewoon.

css voor vensters smaller dan 470 px of lager dan 570 px

@media screen and (max-width: 470px), (max-height: 570px)

De opbouw van deze regel staat gedeeltelijk beschreven bij @media screen and (orientation: landscape) and (max-height: 350px). Omdat er wat nieuwe dingen in staan, die in die regel niet staan, worden delen van de regel hieronder ook summier beschreven.

@media: precies hetzelfde als bij de eerder genoemde regel.

screen: idem.

and: idem.

(max-width: 470px): het browservenster mag niet breder dan 470 px zijn.

,: een komma. Dit is het grootste verschil met de eerdere regel. Een komma betekent in een media querie: 'of'. De css hieronder is geldig als het venster niet breder is dan 470 px, óf als het venster niet hoger is dan 570 px. Als het venster 47.000 px breed is, maar 569 px hoog, valt het venster onder deze regel. Ondanks de openluchtfilmbreedte.

(max-height: 570px): het browservenster mag niet hoger zijn dan 570px.

#twee:focus a, #twee:hover a, #twee a:focus

Als de tweede <li> focus heeft, of als over de tweede <li> (het tweede puzzelstukje) wordt gehoverd, of als de tweede <a> focus heeft, toon dan de knop met de link.

top: 10px; left: 100px;

Bij #twee:focus a, #twee:hover a, #twee a:focus wordt de knop met de link neergezet op top: 26px; left: 130px;. Hieronder wordt de <span> met de pop-up verplaatst en verkleind. Daarom moet de positie van de knop met de link worden aangepast, zodat deze goed staat ten opzichte van de pop-up met de dansende letters.

#twee > span

Alle <span>'s die een direct kind van een het element met id="twee" zijn. Dat is er hier maar een, waarbinnen de pop-up zit.

Het teken > geeft aan dat het om directe kinderen moet gaan:

<li id="twee"> <span></span> </li>

In onderstaande code is de buitenste <span> een direct kind, waarvoor deze selector dus geldt. De binnenste <span> is geen direct kind van de <li>, maar van de buitenste <span>, dus daarvoor geldt deze selector niet:

<li id="twee"> <span> <span></span> </span> </li>
top: -80px;

Bij #twee span wordt de <span> met top: 0; bovenin li#twee geplaatst. Hier gelijk onder wordt de <span> fors verkleind met scale(0.6). Dat verkleinen gebeurt vanuit het middelpunt van het te verkleinen element, waardoor de bovenkant van de <span> lager komt te staan. En de bij de pop-up horende knop nu eenzaam en alleen staat te treuren op, voor een muis, onbereikbare hoogte.

Door de pop-up hoger te plaatsen, wordt dit voorkomen.

(Je kunt ook bij transform opgeven dat de schaling vanaf bijvoorbeeld de bovenkant moet plaatsvinden, maar dit vind ik simpeler.)

-ms-transform: scale(0.6); -webkit-transform: scale(0.6); transform: scale(0.6);

Hier staat in feite drie keer hetzelfde: transform: scale(0.6);. Waarom dat zo is, staat bij De voorvoegsels -moz-, -ms- en -webkit-.

transform is een eigenschap om van alles aan te passen. Hier wordt de transform-functie scale() gebruikt: schalen in beide richtingen: horizontaal en verticaal. In dit geval wordt tot zes tiende verkleind. Omdat maar één getal is opgegeven, wordt in beide richting evenveel geschaald.

In zulke kleine browservensters is er te weinig ruimte voor de pop-up van het tweede puzzelstukje. Daarom wordt de pop-up stevig verkleind. Omdat de dansende letters nogal groot zijn, kan dat zonder de leesbaarheid aan te tasten.

css voor vensters smaller dan 380 px of lager dan 540 px

@media screen and (max-width: 380px), (max-height: 540px)

De opbouw van deze regel staat beschreven bij @media screen and (max-width: 470px), (max-height: 570px). Er zijn twee verschillen: de maximumbreedte is hier 470 px en de maximumhoogte 570 px.

#negen:focus a, #negen:hover a, #negen a:focus

Als de negende <li> focus heeft, of als over de negende <li> (het negende puzzelstukje) wordt gehoverd, of als de negende <a> focus heeft, toon dan de knop met de link.

top: -50px; left: 30px;

Bij #negen:focus a, #negen:hover a, #negen a:focus wordt de knop met de link neergezet op top: -25px; left: -8px;. Hieronder wordt de <span> met de pop-up verplaatst en verbreed. Daarom moet de positie van de knop met de link worden aangepast, zodat deze goed staat ten opzichte van de pop-up met de tekst.

#negen:focus > span, #negen:hover > span, #negen a:focus + span

Deze selectors openen de pop-up bij het negende puzzelstukje. Hoe ze precies werken, is te vinden bij #negen:focus > span, #negen:hover > span, #negen a:focus + span.

width: 250%;

Bij #negen > span is een breedte van 200% opgegeven. Dat is in deze smalle browservensters te weinig.

top: -120px;

Een groot deel van de tekst zou wegvallen in deze lagere vensters, daarom wordt de pop-up een stuk omhoog gezet.

left: -160%;

Bij #negen:focus > span, #negen:hover > span, #negen a:focus + span is de <span> met de pop-up op left: -120%; gezet. Hier wordt de pop-up meer naar links gezet, zodat er meer binnen het browservenster past.

JavaScript

De code is geschreven in een afwijkende lettersoort. De code die te maken heeft met de basis van dit voorbeeld (essentiële code) is in de hele uitleg onderstippeld blauw. Alle niet-essentiële code is bruin. (In de inhoudsopgave staat alles in een gewone letter vanwege de leesbaarheid.)

Beide stukjes JavaScript hieronder zijn alleen nodig voor iOS. In principe werkt het menu niet op iOS, als JavaScript uitstaat. Maar dat zal niet snel gebeuren, omdat je dan niet veel meer hebt dan een groot uitgevallen (en peperduur, want Apple) horloge.

<div id="wrapper" onclick="">

Op iOS werkt aanraken van de <li> niet, het heeft geen enkel effect. Er is al jarenlang discussie over de oorzaak hiervan. En er zijn tal van oplossingen, die volgens anderen dan weer niet altijd werken. Omdat Apple ongeveer even open is over de werking van iOS als de staatsloterij vóór de trekking over het nummer van het winnende lot, zal wel altijd onduidelijk blijven, hoe dit komt.

(Vraag aan statistici: waarom is het enthousiasme van Applefans recht evenredig met de geslotenheid van Apple? Bestaat daar een of andere statistische verklaring voor? Of kan ik deze vraag beter aan een in vreemde verschijnselen gespecialiseerde antropoloog stellen?)

In dit geval lost een simpele onclick="" bij #wrapper het op:

<div id="wrapper" onclick="">

Nu werkt aanraken van de puzzel wel.

Verder heeft dit geen enkel effect. onclick is een stukje JavaScript: doe iets als er wordt geklikt op dit element. En 'klikken' moet hier dan worden gelezen als 'aanraken'. En wat moet er dan worden gedaan? Dat staat achter het isgelijkteken: "". Noppes. Niets. Nada. Blijf lekker in bed liggen vandaag. Doe vooral niets en bemoei je er verder niet mee. Maar waar het om gaat: er wordt nu geluisterd naar mogelijke aanrakingen, en die werken nu op de hele div#wrapper, en daarmee op de hele puzzel.

Een enigszins onverwachte bijwerking van dit minieme stukje JavaScript is de uitwerking op focus. Op iOS houdt een element na aanraking focus, tot er een ander element dat focus kan krijgen wordt aangeraakt. Dat andere element krijgt dan focus, en het eerste element (hier de <li>) verliest de focus, waardoor de pop-up sluit. Zolang een <li> focus heeft, blijven bijbehorende knop en pop-up geopend.

Als je het scherm buiten een <li> aanraakt, is er niets dat focus kan krijgen en blijven knop en pop-up gewoon zichtbaar, omdat de <li> focus houdt.. De enige manier om een pop-up te sluiten is het aanraken van een andere <li>. Maar dan opent daar de pop-up van. En is niet meer te sluiten.

Door de onclick bij div#wrapper blijkt ook dit opgelost: waar je het scherm nu ook aanraakt, de pop-up en knop sluiten.

<script>

document.getElementsByTagName("body")[0].addEventListener("touchstart", function () {return null;}); </script>

Het tweede stukje JavaScript dat nodig is.

<script> en </script>

Dit is gewone html: het zijn de openings- en sluittag voor het script. In html5 is de toevoeging type="text/javascript" niet meer nodig.

Het eigenlijke JavaScript is tamelijk simpel. Ik ga er niet al te diep op in, want deze site gaat uiteindelijk niet over JavaScript, maar over css.

document.getElemtsByTagName("body")[0]

Zoek naar alle elementen die 'body' heten. Aangezien 'n computer niet echt slim is, weet de ziel niet dat je per definitie maar één 'body' hebt. Van deze elementen wordt een soort lijstje gemaakt. In dit geval dus een 'lijstje' met één deelnemer. Elk element van dat lijstje krijgt een volgnummer. En een computer begint graag te tellen met '0': ziedaar de '0' uit [0] binnen komen wandelen.

In normale mensentaal: maak een lijstje met alle <body>'s, en gebruik daarvan de eerste.

In nog normalere mensentaal: doe iets met <body>.

addEventListener

En wat moet het ding dan doen met de body? Heel preuts aangelegde mensen kunnen nu beter stoppen met lezen, want het gaat hier verder over geheimzinnige aanrakingen van de body en zo, die ook nog 'ns worden afgeluisterd door 'n soort gluurder. U bent gewaarschuwd.

Er wordt een zogenaamde 'eventlistener' toegevoegd aan <body>. Dat is een ding dat luistert of er iets gebeurt. Zo'n gebeurtenis kan een toetsaanslag zijn, een beweging van de muis, een liefdevolle aanraking met de vinger, van alles.

"touchstart"

In dit geval is de gebeurtenis, waarnaar wordt geluisterd, 'touchstart'. Het begin van een aanraking. Over het einde van de aanraking ga ik het niet hebben, dat is te privé. Maar het bestaat wel, ook in JavaScript.

'touchstart' registreert het begin van een aanraking. In dit geval als iemand (of iets) het scherm van de tablet, smartphone, of wat dan ook aanraakt.

function () {return null;}

En hier dan wat er gebeurt na de aanraking. function() is gewoon een soort aankondiging dat er iets gaat gebeuren. Erachter tussen de accolades staat, wat er gaat gebeuren. Voor degenen die echt op onkuise dingen hadden gehoopt: dat gaat tegenvallen.

return null wil zeggen dat er helemaal niets gebeurt. Echt niets. Het is ongeveer het JavaScript-equivalent van: "Sorry schat, ik heb hoofdpijn vanavond" als reactie op een aanraking.

Bij de uitleg van deze code zijn allerlei haakjes en dergelijke weggelaten, want dat voert hier te ver. Als je je in dat soort dingen wilt verdiepen, kun je beter naar sites gaan die meer voor JavaScript zijn bedoeld.

Vanwaar deze hele exercitie die eindigt met een volstrekt nietsdoen? Vanwege iOS.

Omdat hoveren op een touchscreen niet mogelijk is, maar er al miljoenen websites bestaan die dat wel gebruiken, moesten de makers van touchscreens daar iets mee. Zonder meer hoveren negeren was onmogelijk, omdat bijvoorbeeld heel veel menu's dan niet meer zouden werken. Als je iets nieuws op de markt brengt, maar vrijwel geen enkele website werkt nog, is dat commercieel gezien misschien niet zo handig.

Ook in dit voorbeeld wordt :hover gebruikt: op de <li>'s die al in gebruik zijn. Op diverse plaatsen in de css staan varianten op li:hover.

Het eerste probleem: op iOS blijft een :hover geopend. Op de desktop sluit een pop-up weer, als de muis het voor hoveren gevoelige deel verlaat, op iOS niet. En ook niet zonder meer als je op 'n andere plek het scherm aanraakt.

Daarnaast wordt op diezelfde <li>'s ook gewerkt met focus: li:focus. Dat zijn dus twee verschillende dingen op hetzelfde element. Als je met een muis of toetsenbord werkt, is dat geen probleem. Op een touchscreen kan het dat wel zijn.

Dit scriptje zorgt ervoor, dat de pop-ups bij een eerste aanraking buiten de pop-up gelijk weer sluiten, en niet pas bij een tweede aanraking.

Omdat het script aan <body> is gekoppeld, werkt het in het hele browservenster. Dat zal bij een touchscreen normaal genomen hetzelfde zijn als het hele scherm.

Hoe het precies werkt, weet ik niet. Maar het werkt wel. Ik heb wel wat vage ideeën over de werking, maar zeker weten, nee. Als je gaat zoeken op internet kom je bij tien mensen twintig verhalen met dertig verklaringen en veertig tegenwerpingen tegen. En Apple zelf doet volstrekt geheimzinnig over dit soort dingen. (Sorry Applefans, dat is natuurlijk geen probleem. Dat is juist fantastisch van Apple! Dat ik dat nou toch niet wil begrijpen...)