Skip links en inhoudsopgave

Werking van de sub­menu's op de site - uitleg

Laatst aangepast: .

Afbeelding 1: de submenu's in vensters van verschillende grootte

Korte omschrijving

Links naar achterliggende pagina's zijn verborgen onder een kleine schermafdruk van die pagina. In grotere vensters kan in een pop-up een grotere schermafdruk worden getoond.

BELANGRIJK

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.

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 vanwege de leesbaarheid in een gewone letter.)

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

Toen ik met deze site begon, bestonden touchscreens nog nauwelijks. En van een tablet of smartphone had niemand nog ooit gehoord.

Op de oorspronkelijke site kon je op 'n knop klikken, waarna de bijbehorende pagina werd geopend. Als je met de muis over de knop hoverde, verscheen een pop-up met een schermafdruk van de pagina achter de knop.

In grote lijnen ziet het er nog steeds zo uit, maar de achterliggende code is volledig veranderd. Dat gebeurde op de site eerst met het betere plakband en paperclipwerk. Op touchscreens werkte het niet, dus werd er aan elke pagina een compleet menu toegevoegd speciaal voor touchscreens. Vervolgens bleek dat mensen zelfs zo'n uitleg op een smartphone gaan zitten lezen (lijkt me gruwelijk, maar goed). Dus 'n schuifmenu voor smartphones erbij. Microsoft ontdekte het touchscreen en maakte 'n geheel eigen bewerking van hoveren. Niet eens zo gek, maar helaas veranderde dat in de volgende versie van Internet Explorer weer geheel. En over Apple wil ik het niet hebben, want die grossiert in eigenaardigheden (Applefans: gelieve hier 'verbeteringen' te lezen).

Oftewel: de code had inmiddels meer weg van een afgekoeld en daardoor niet meer te eten bord spaghetti, dan van ordentelijke html en css.

Een tijd geleden zijn daarom de pagina's met menu's en dergelijke van de grond af volledig herschreven. (Een groot deel van de voorbeelden zelf moet nog worden herschreven voor touchscreens en dergelijke.)

Daarbij was er een aantal voorwaarden, en die voorwaarden gelden dus ook voor dit voorbeeld:

* De pagina moet werken op elke breedte, van heel smal tot heel breed.

* Menu's en dergelijke moeten er maar één keer in staan. De code moet niet drie keer worden herhaald voor drie verschillende menu's.

* De toelichtende tekst boven de pop-ups moet in elk browservenster te zien zijn, ook in hele smalle vensters waarin geen ruimte is voor een pop-up.

* De pop-ups moeten ook voor gebruikers van de Tab-toets te openen zijn.

* De toelichtende tekst boven de pop-ups moet ook door schermlezers voorgelezen kunnen worden.

* De pop-ups moeten geopend kunnen worden door middel van aanraken en hoveren.

* Bij een andere lettergrootte en bij zoomen moet alles redelijk blijven werken.

* Omdat deze site nou eenmaal over css (en html) gaat, moet het niet afhankelijk zijn van JavaScript, of in ieder geval moet JavaScript niet essentieel zijn voor de werking.

* De tekst in het midden van de pagina (in smalle browservensters onderaan de pagina) moet in alle vensters volledig te lezen zijn, ook op touchscreens.

* Bovenaan de pagina moet een menubalk voor navigatie binnen de site staan, en die moet altijd in beeld blijven, ook als er wordt gescrold. (In het voorbeeld is die vervangen door een <h1>, die altijd in beeld blijft.)

* Het moet ook acceptabel zijn in browsers die dingen als calc() niet kennen. Internet Explorer 8 ondersteun ik niet meer, maar in iets nieuwere browsers moet alles redelijk werken.

Ik geloof dat bovenstaande lijstje redelijk is gelukt.

De tekst in het midden staat eigenlijk helemaal los van de rest van de pagina. Het is 'n simpele kolom, waarvan breedte en hoogte worden aangepast aan breedte en hoogte van het browservenster. Rondom deze kolom met tekst staan de knoppen van het menu. (In browservensters smaller dan 763 px óf lager dan 543 px staat de kolom met tekst niet tussen, maar onder de knoppen. Dat is kleiner dan 1024 x 768 px, een veel voorkomende maat voor tablets.)

In vensters met een hoogte tussen 543 en 712 px is geen ruimte voor vier knoppen links en rechts van de kolom met tekst. In die vensters staan links en rechts twee knoppen, en de resterende vier knoppen staan onder de kolom met tekst. Door scrollen van de tekst kan de tekst toch volledig worden gelezen. Omdat het mogelijk onduidelijk is dat de tekst onderaan nog doorloopt, staat in deze vensters onderaan de tekst een doorzichtige gradiënt over de tekst heen.

De acht knoppen met bijbehorende teksten, pop-up, enz. staan elk in een eigen lijst-item <li>. Door ze elk in een eigen, volledig op zichzelf staande, <li> te zetten, is het relatief makkelijk de knoppen op de juiste plaatsen neer te zetten. Relatief, want er zat een complete kudde beren op de weg. (Heet 'n groep beren wel 'n kudde???)

Afbeelding 2: de submenu's in kleinere vensters

In kleinere browservensters is geen ruimte voor een grote pop-up met een voorbeeld van de onder de knop zittende pagina. Voor kleinere vensters is daardoor veel minder html en css nodig. De rest van de code, die voornamelijk voor de pop-up is, wordt voor deze vensters gewoon verborgen.

In elke <li> zit een thumbnail: een kleine afbeelding van de pagina achter de link in de knop.

Als alle tussenliggende <span>'s en dergelijke worden weggelaten – die zijn alleen nodig voor de pop-ups en dergelijke –, volgt daarop een <span> met een omschrijving van de afbeelding. In smallere browservensters staat deze niet in de pop-up, maar gelijk naast de thumbnail. De thumbnails zelf worden iets verkleind weergegeven. Daar worden geen aparte afbeeldingen voor gebruikt, want dat levert nauwelijks kleinere bestanden op. Ze worden niet echt veel verkleind.

Ten slotte is er dan nog een gewone link, een <a>, die naar de pagina leidt. Deze wordt over de thumbnail gezet, waardoor de thumbnail als link naar de achterliggende pagina werkt.

Als je dan nog wat schaduw, lijntjes, ronde hoekjes en dergelijke toevoegt, ziet het geheel eruit als op bovenstaande afbeelding.

Afbeelding 3: de submenu's in middelgrote vensters

In browservensters met een minimale breedte van 763 px én een minimale hoogte van 543 px is ruimte om, links en rechts van de kolom met tekst, vier thumbnails onder elkaar te zetten. De thumbnails worden nu niet meer verkleind, maar op ware grootte weergegeven.

Omdat de tekst in de middelste kolom tot de onderkant van het venster doorloopt, is duidelijk dat er onder het venster nog meer tekst staat. Ook wanneer, zoals op veel touchscreens het geval is, een scrollbalk ontbreekt.

Bij openen van de pagina moet je eerst in de tekst klikken, voordat het scrollwieltje van de muis, pijltjestoetsen, en dergelijke werken. Om dat te voorkomen is bovenaan de kolom met tekst een <input> met het attribuut autofocus neergezet.

Hierdoor werken scrollwieltje, pijltjestoetsen, en dergelijke zonder dat eerst in de tekst geklikt moet worden. Dit verandert wel de volgorde van de tabindex: bij gebruik van de Tab-toets wordt eerst door de kolom met tekst gelopen, en daarna volgen de knoppen links en rechts.

Veel maakt dat volgens mij in dit geval niet uit, want er is iets te zeggen voor het eerst door de tekst lopen, en er is iets te zeggen voor het eerst door de knoppen lopen. Verwarring zal hier niet door ontstaan. Overigens is dit vrij simpel te voorkomen door in de html de kolom met tekst boven de lijst met knoppen te zetten. Als de tekst bovenaan staat, werkt het scrollwieltje ook gelijk zonder klikken.

Op de site kan de volgorde niet worden veranderd, omdat er nog veel meer links in die lijst staan. Daarom heb ik de volgorde in het voorbeeld ook niet veranderd, want dat zou weer 'n extra verandering ten opzichte van de site zijn. Bovendien maakt het in dit geval niets uit.

Afbeelding 4: de submenu's in grote vensters

In browservensters met een minimale breedte van 763 px is genoeg ruimte voor een thumbnail links en rechts van de kolom met tekst. Maar alleen bij een minimale hoogte van 712 px passen er vier thumbnails onder elkaar. Daarom worden bij een minimale breedte van 763 px én een hoogte tussen 543 px en 712 px links en rechts van de tekst slechts twee knoppen neergezet. De andere vier knoppen komen onderaan te staan.

(Als je je inmiddels afvraagt hoe ik aan die krankzinnige grenzen kom: dat is gewoon een kwestie van uitproberen. Kijken wat het beste uitkomt in verschillende vensters. Bij een andere breedte van bijvoorbeeld de pop-ups zul je de waarden van de grenzen moeten aanpassen.)

Op de afbeelding is het browservenster 967 px breed en 661 px hoog. De knoppen worden verticaal en horizontaal zo goed mogelijk verdeeld over het venster. In browsers die calc() niet kennen, staan de middelste knoppen (van boven naar beneden gezien) gelijk onder de bovenste twee knoppen. Minder netjes, maar het werkt allemaal wel.

Onderaan de tekst is over de tekst een doorzichtige gradiënt neergezet, zodat ook in vensters zonder scrollbalk duidelijk is dat de tekst nog doorloopt. Door het gebruik van pointer-events: none; kan tekst onder deze gradiënt op de normale manier worden geselecteerd, gekopieerd, en dergelijke.

Anders dan in browservensters smaller dan763 px of lager dan 543 px is de toelichting bij de thumbnails hier verdwenen. Hierdoor is er ruimte om alle acht de thumbnails gelijktijdig in het venster van de browser te tonen. De toelichting, en een grotere schermafdruk, kunnen worden getoond door een pop-up te openen. Ook deze pop-up werkt volledig met css.

Elke thumbnail met bijbehorende pop-up, link, enz. staat in een eigen lijst-item <li>. Onder de thumbnail, een gewone <img>, staat een radioknop. (De <input>'s met id="open-1", id="open-2", enz.) Deze radioknoppen zijn verborgen.

Onder elke radioknop staat een bijbehorend <label>. (De <label>'s met class="open".) Dat <label> zorgt voor het doorzichtige witte vierkantje met het vraagteken. Het vraagteken zelf zit in een <span> met class="vraagteken" binnen de <label>. Door op de <label> te klikken of dit aan te raken, wordt de bijbehorende radioknop geselecteerd. Omdat alle acht de radioknoppen in dezelfde groep zitten, kan er steeds slechts één worden geopend. Zodra je via de <label> een andere radioknop selecteert, wordt een eventuele andere radioknop gedeselecteerd. En zal een eventueel daarbij horende pop-up daardoor worden gesloten.

Binnen de <label> staat, in een aparte <span> met class="pop-up-tekst", de toelichtende tekst bij de thumbnail. Deze tekst is normaal genomen niet te zien. Pas als de bijbehorende radioknop is geselecteerd, wordt de in de <label> zittende tekst in een pop-up getoond.

In de <label> zit ook nog een <span> met class="pop-up". Zodra een radioknop is geselecteerd, krijgt deze <span> een achtergrond-afbeelding: een grotere uitvoering van de thumbnail. Omdat deze pas wordt getoond als de radioknop is geselecteerd, wordt deze grotere afbeelding pas gedownload, als deze daadwerkelijk wordt bekeken.

De <label> is ook gevoelig is voor hoveren. Hierdoor openen toelichting en grotere afbeelding ook, als over het witte blokje met het vraagteken wordt gehoverd.

De plaats van de pop-up is afhankelijk van de plaats van de thumbnail.

In de link naar de achterliggende pagina zit nog een <span> met class="naam". Hierin zit de naam van de pagina. Deze wordt zichtbaar gemaakt, zodra over het witte vlakje met het vraagteken wordt gehoverd, of zodra dit wordt aangeklikt of aangeraakt.

Er zit nog een negende radioknop in de groep radioknoppen. Deze staat helemaal bovenaan de pagina en hoort niet specifiek bij een bepaalde thumbnail.

Binnen elke <li> zit onderaan nog een <label> met class="sluit". Deze <label>'s horen bij deze negende radioknop. Zodra een van de acht bij een knop horende radioknoppen is geselecteerd, zorgt dit label.sluit voor het tonen van een rood sluitkruis. Dit is een gewone letter 'x', die wat is opgeleukt. Door hierop te klikken of dit aan te raken, wordt de negende radioknop geselecteerd. Waardoor een geopende pop-up weer verdwijnt, want de bij de pop-up horende radioknop is nu niet meer geselecteerd.

De diverse witte vlakjes, vraagtekens, sluitkruizen, en dergelijke worden met behulp van nogal wat berekeningen steeds op de juiste plaats ten opzichte van de bijbehorende knop gezet.

Afbeelding 5: zonder correctie staat in sommige vensters een deel van de pop-ups buiten het venster

In browservensters met een maximale hoogte van 712 px staan vier van de thumbnails onderaan het venster. In vensters met een breedte tussen 763 en 1073 px levert dit een probleem op: als de zesde of zevende pop-up wordt geopend, valt deze net buiten het venster. Op de afbeelding is het venster 787 px breed en 712 px hoog. De zesde pop-up valt hier voor een groot deel buiten het venster.

Daarom worden in deze vensters de zesde en zevende pop-up met behulp van transform verkleind. Dat is verreweg de makkelijkste manier om dit op te lossen. Uiteraard moet dan ook weer de positie worden aangepast. En dan blijken de letters te klein te worden, dus die worden weer vergroot. En zo houd ik mezelf aardig van de straat en voorkom dat ik een hangoudere word.

Afbeelding 6: vinkje als pagina is bezocht

Als een pagina is bezocht, verschijnt een klein vinkje naast het vraagteken. Dit vinkje bestaat uit twee borders, die wat worden gedraaid en zo. Ze zitten in een pseudo-element dat met behulp van ::after aan span.naam, een <span> met de naam van de pagina, wordt toegevoegd.

Feitelijk is dit vinkje altijd aanwezig, ook als de pagina nog niet is bezocht. Maar het wordt pas zichtbaar, als de pagina is bezocht. Dat kan door in de css te controleren op a:visited: is de link bezocht?

Tot 'n paar jaar geleden kon je met behulp van :visited de wildste dingen doen. Omdat het kinderlijk eenvoudig bleek met behulp van wat JavaScript uit te lezen, welke sites waren bezocht, kun je :visited nog slechts voor een beperkt aantal dingen gebruiken. Dat geldt ook voor dit pseudo-element, want span.naam zit in de <a> en is dus onderdeel van de link.

Eén van de dingen die nog kan worden veranderd, is de kleur. Het vinkje is altijd aanwezig, maar als de link nog niet is bezocht, heeft het (vrijwel) dezelfde achtergrondkleur als het witte vlakje met het vraagteken. Als de link is bezocht, wordt de kleur van het vinkje veranderd, waardoor het zichtbaar wordt.

Sommige mensen kunnen of willen geen muis gebruiken om een link aan te klikken, een pop-up te openen, een <input> te bezoeken, of wat dan ook. Je kunt ook links, <input>'s, enz. bezoeken door de Tab-toets in te drukken. (Over hoe dit precies werkt, is meer te vinden bij Tabindex.)

In elke <li> zit een link. Als die met behulp van de Tab-toets wordt bezocht, focus heeft, wordt die link gevolgd door het indrukken van Enter. Door in de css te checken op a:focus zou je de op de link volgende pop-up kunnen openen, als de link focus heeft. Maar helaas zit de pop-up vóór de link in de html, dat kan niet anders. Dus dat werkt hier niet. Dat zou betekenen dat gebruikers van de Tab-toets wel de link kunnen volgen, maar de pop-up niet zien.

Je zou ook een pop-up kunnen openen als de radioknop voor de pop-up focus heeft. Maar ook dat werkt niet, want als een radioknop focus heeft, kunnen andere radioknoppen uit diezelfde groep geen focus meer krijgen. (Je selecteert een radioknop in een bepaalde groep door te bewegen met de pijltjes.)

Daarom is in elke <li> aan het begin een <span> met class="focus-open" toegevoegd. Een <span> wordt normaal genomen niet bezocht door de Tab-toets, maar wel als je tabindex="0" aan de <span> toevoegt. Door de selector span.focus-open:focus te gebruiken, kan de pop-up worden geopend zodra de<span> focus heeft.

Bij de volgende tab gaat de focus van de <span> naar de daarop volgende <a> en kan de link worden gevolgd. Dit wordt nog wat verduidelijkt door wat kleurtjes en zo.

De <span> voor de Tab-toets wordt volledig verborgen, waardoor hij geen enkele invloed heeft op touchscreens. Als de <span> aangeraakt zou kunnen worden, zou hij problemen opleveren op iOS, omdat op dat systeem de pop-up geopend zou blijven, tot een ander element focus zou krijgt. Een van de verbeteringen van Apple waar je hartstikke gek van wordt.

Je zou de pop-up ook kunnen openen, als de <label> met het vraagteken focus krijgt. Maar dat werkt om dezelfde reden niet op iOS: pas als een ander element focus zou krijgen, zou de pop-up weer sluiten. Los van of de radioknop die bij de <label> hoort, is geselecteerd of niet.

Als je 'n nieuwe pop-up opent, sluit de vorige, want de nieuwe pop-up heeft dan focus. Maar de laatste pop-up blijft altijd geopend, tot een ander element focus krijgt. Dat is uiterst verwarrend, vandaar de volledig aparte <span> voor gebruikers van de Tab-toets.

Meer over de Tab-toets, tabindex, en dergelijke kun je vinden bij Tabindex. Meer over focus bij focus.

Als dit zo zou worden gebruikt, met al die <input>'s, <label>'s en andere ongein, zouden gebruikers van een schermlezer massaal de weg kwijtraken. Die hebben daar helemaal niets aan. De schermlezer moet gewoon de links en de toelichting voorlezen, en dat is het.

Daarom worden veel elementen verborgen voor schermlezers met behulp van de WAI-ARIA-code aria-hidden="true". Dat kan niet met de <label> waarbinnen de toelichting staat, want dan wordt ook de toelichting genegeerd. Die <label> is veranderd in een element zonder betekenis met behulp van role="presentation". Wat betreft schermlezers is de <label> hiermee hetzelfde geworden als een gewone <span> of zoiets.

Meer over WAI-ARIA-codes is te vinden bij Semantische elementen en WAI-ARIA.

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, Opera, Safari en Android browser: -webkit-.

(Google Chrome is van webkit overgestapt op een eigen weergave-machine: Blink. Blink gaat geen voorvoegsels 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 Blink.)

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

In dit voorbeeld worden hyphens, linear-gradient, transform, @-webkit-keyframes, -webkit-animation en -webkit-overflow-scrolling 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.

-webkit-animation en @-webkit-keyframes

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

{-webkit-animation: ...;}

Hetzelfde geldt voor @keyframes:

@-webkit-keyframes{...}

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

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

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

-webkit-overflow-scrolling

Als op iOS niet de hele pagina, maar binnen een element wordt gescrold, zoals hier bij de tekst binnen <main> gebeurt, gaat dat scrollen om een of andere duistere reden ongelooflijk schokkerig. Met deze eigenschap kan voor vloeiend scrollen worden gezorgd.

Omdat dit alleen voor iOS nodig is, wordt van deze eigenschap ook alleen de -webkit-versie gebruikt: buiten iOS is hij niet nodig (en werkt ook niet).

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

In de laatste twee versies van Firefox is het voorvoegsel -moz- niet meer nodig. Maar omdat dat pas sinds heel kort zo is, gebruik ik het op dit moment nog.

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(...);}

transform

Op dit moment moet je nog het volgende schrijven:

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

In de toekomst kun je volstaan met:

{transform: ...;}

Inmiddels is de algemene mening dat 'vendor prefixes', zoals deze voorvoegsels 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 worden van deze nieuwe semantische elementen <main>, <nav> en <header> gebruikt. <main> voor de belangrijkste inhoud: de kolom met tekst; <nav> voor het navigatiedeel met de links en <header> voor de kop van de pagina.

(De kolom met tekst is hier natuurlijk niet het belangrijkste, omdat het in dit voorbeeld om de navigatie gaat. Maar normaal genomen zou de tekst waarschijnlijk wel het belangrijkste onderdeel van de pagina zijn.

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 <main>. Dat is een al veel langer bestaande code, die schermlezers en dergelijke wel herkennen. Voor een <main> ziet dat er zo uit:

<main role="main">

Inmiddels is dit behoorlijk veranderd. Het advies is nu, om deze speciale toevoeging niet meer te gebruiken, omdat de meeste schermlezers en dergelijke een <main> 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 role="presentation".

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 voorbeeld kunnen de <input>'s en <label>'s voor schermlezers uiterst verwarrend zijn, terwijl ze voor schermlezers geen enkel nut hebben. Daarom is het beter ze te verbergen voor schermlezers.

Bij input, .vraagteken, .sluit worden alle <input>'s verborgen met behulp van display: none;. Dit verbergt ze ook voor schermlezers, dus hier is verder geen extra code voor nodig.

De <label> die wordt gebruikt om de pop-up te sluiten, kan niet op deze manier worden verborgen. Deze moet in grotere browservensters getoond worden, als een pop-up is geopend door klikken of aanraken. In bepaalde situaties kan een schermlezer dit element aankondigen als 'label', wat erg verwarrend kan zijn. Bovendien zit in de <label> de letter 'x', die braaf wordt voorgelezen door de schermlezer.

Om deze <label> voor schermlezers te verbergen, is aan deze <label> aria-hidden="true" toegevoegd:

<label class="sluit" for="sluit-x" aria-hidden="true">x</label>

Aan het begin van de tekst in de middelste kolom is een <input> neergezet:

<input id="checkbox-voor-focus" type="checkbox" aria-hidden="true" autofocus>

Deze <input> heeft geen enkele zichtbare werking. Maar door het gebruik van het attribuut autofocus wordt de focus op de tekst gezet. Als dat niet zou gebeuren, moet eerst in de tekst worden geklikt, voordat de tekst kan worden gescrold met behulp van scrollwieltje of pijltjes. Meer hierover is te vinden bij checkbox-voor-focus.

Voor schermlezers kan deze <input> verwarrend zijn. Bovendien heeft hij daar geen enkel nut. Daarom wordt deze <input> met behulp van aria-hidden="true" voor schermlezers verborgen.

Bij elke thumbnail zit ook nog een <span> met daarin een vraagteken:

<span class="vraagteken" aria-hidden="true" title="Klik om pop-up open te houden">?</span>

Ook dit vraagteken heeft geen enkel nut voor schermlezers. Maar het wordt wel voorgelezen. Daarom wordt ook deze <span> voor schermlezers verborgen.

role="presentation"

De <label> die bij de <inpu>t's voor het openen van de pop-ups hoort, kan niet zonder meer volledig voor schermlezers worden verborgen. Want in deze <label> zit ook de beschrijving van de thumbnails, en die moet wel worden voorgelezen.

Daarom wordt deze <label> niet verborgen, maar voor schermlezers met behulp van het attribuut role="presentation" veranderd in een element zonder enige semantische betekenis. Een soort <span> of <div>:

<label class="open" for="open-2" role="presentation">

Nu wordt de omschrijving van de thumbnails gewoon voorgelezen, zonder dat de <label> een eventueel storende werking heeft voor gebruikers van een schermlezer.

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. Maar gebruikers van de Tab-toets zullen dit al hebben gedaan.

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.

De Tab-toets volgt normaal genomen de volgorde van de elementen in de html. Het maakt niet uit, in welke volgorde 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 volgorde van de Tab-toets kan worden veranderd met behulp van het tabindex-attribuut: <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. Of om een element bereikbaar te maken voor de Tab-toets, zoals de hierboven genoemde <div>.

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. Een waarde van '0' wordt, afhankelijk van browser en besturingssysteem, verschillend behandeld, waarover iets hieronder bij Tabindex="0" meer.

Bovenaan de pagina staat een <input>, en bij elke thumbnail staat ook een <input>. Normaal genomen worden die ook bezocht door de Tab-toets. Maar omdat deze met display: none; zijn verborgen, worden ze genegeerd door de Tab-toets. Precies de bedoeling, want voor gebruikers van de Tab-toets hebben deze <input>'s in dit geval geen enkel nut.

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" niet gebruikt.

tabindex="0"

Volgens de specificatie van html 4.01 moest een tabindex="0" pas worden bezocht, nadat tabindexen met een positief nummer waren bezocht. Sommige browsers hielden zich hier echter niet aan: een tabindex="0" werd gewoon tussen de positieve tabindexen gezet.

In html5 is de situatie nog fijner. Nu staat er alleen dat, wat betreft de volgorde, de gewoonte van het platform wordt gevolgd. Oftewel: doe maar raak. Maar hoe dan ook: als je tabindex="0" gebruikt, kan een element focus krijgen met behulp van de Tab-toets. Ook als dat element normaal genomen geen focus kan krijgen.

Deze waarde wordt in dit voorbeeld gebruikt bij de <span>'s bovenin elke <li>:

<span class="focus-open" tabindex="0"></span>

Door de toevoeging van tabindex="0" kan de <span> focus krijgen bij gebruik van de Tab-toets, terwijl een <span> dat normaal genomen niet kan krijgen. Door als selector iets als span.focus-open + .pop-up te gebruiken, kan de pop-up nu worden geopend, als de <span> focus heeft. Waarmee de pop-up ook is te openen door gebruikers van de Tab-toets.

De op de <span> volgende <input> is met behulp van display: none; verborgen en wordt daardoor genegeerd door de Tab-toets. Maar de hier weer op volgende <a> wordt wel aangedaan door de Tab-toets.

De eerste tab geeft de focus aan span.focus-open, waar mee de pop-up wordt geopend. De daarop volgende tweede tab geeft de focus aan de <a> die iets onder span.focus-open in de html staat: de pop-up sluit en met Enter kan nu de link worden gevolgd. (Dat de <a> focus heeft wordt met behulp van wat kleurtjes en zo aangegeven.)

Als elders op de pagina nog een tabindex wordt gebruikt, kan een tabindex="0" problemen geven met de volgorde, zoals iets hierboven beschreven. Op de site zelf, waar ook knoppen voor navigatie op de site aanwezig zijn, gaat het goed. Geen enkele knop heeft daar een tabindex, waardoor in alle browsers eerst de navigatieknoppen en dan pas de <span>'s met de tabindex worden bezocht. Precies zoals de bedoeling is. Maar als je wel een tabindex elders op de pagina gebruikt, moet je in zoveel mogelijk browsers op zoveel mogelijk systemen de volgorde bij gebruik van de Tab-toets controleren.

tabindex="..."

Op de plaats van de puntjes moet een positief getal worden ingevuld: het volgnummer. Positieve tabindexen worden hier 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.

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. Dit levert problemen op in iOS en in Edge op een touchscreen.

Als :hover met :focus wordt gecombineerd op hetzelfde element, zijn daar op iOS vaak aanpassingen voor nodig. Deze combinatie komt in dit voorbeeld niet voor, dus er zijn geen speciale aanpassingen voor iOS nodig. Ook voor andere touchscreens zijn geen aanpassingen nodig.

: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. In dit voorbeeld is er helemaal geen kadertje, omdat de focus op andere manieren wordt aangegeven.

Bij gebruik van de Tab-toets wordt elke thumbnail als het ware twee keer aangedaan. Bij de eerste tab opent de pop-up en verschijnt de naam van de bijbehorende pagina boven de thumbnail. Bij de tweede tab sluit de pop-up, wordt de thumb minder goed zichtbaar en verschijnt de naam van de achterliggende pagina als link groot op de thumbnail. Een kadertje is hier dus overbodig, want als je dit niet ziet, zie je zeker geen kadertje...

Als :hover met :focus wordt gecombineerd op hetzelfde element, zijn daar op iOS vaak aanpassingen voor nodig. Deze combinatie komt in dit voorbeeld niet voor, dus er zijn geen speciale aanpassingen voor iOS nodig. Ook voor andere touchscreens zijn geen aanpassingen nodig.

Wel zijn voor gebruikers van de Tab-toets speciale voorzieningen aangebracht, zodat ook bij gebruik van de Tab-toets de pop-up wordt geopend. Meer daarover is te vinden bij Tabindex.

:active

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

Een element is actief, als de muis wordt ingedrukt boven dat element. Op sommige touchscreens is het element actief, als het wordt aangeraakt.

:active wordt hier niet gebruikt.

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 (in het Engels 'accessibility') 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

Getest in

Laatst gecontroleerd op 9 maart 2016

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 deel 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 hierboven bij 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.

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 en 10 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 OS X.

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.

Onderstaande lijst is nogal lang, omdat ik de gewoonte heb álle bekende problemen op te schrijven. De lengte van de lijst is tamelijk indrukwekkend, maar het gaat eigenlijk vrijwel alleen om hele kleine dingetjes.

Validatie

Bij valideren van de css geeft de validator van w3c twee fouten.

pointer-events zit nog niet in een officiële specificatie en wordt nog niet herkend.

Bij calc() worden bepaalde berekeningen met procenten onrechte als fout aangemerkt: deze berekeningen werken gewoon en zijn correct. Hier moet de validator dus kennelijk zelf gevalideerd worden.

In beide gevallen is de oorzaak van de 'fout' bekend en is deze 'fout' daarom onbelangrijk.

Alle browsers

Bij hoveren sluit de pop-up, zodra niet meer over het vraagteken wordt gehoverd

Dit doet zich alleen voor, als met de muis over het vraagteken wordt gehoverd. Het speelt ook alleen in grotere browservensters, want alleen daar zijn pop-ups aanwezig.

Dit is alleen een echt probleem, als er zoveel tekst boven de afbeelding in de pop-up staat, dat niet alle tekst zonder scrollen is te lezen. In dat geval moet op het vraagteken worden geklikt. Dan blijft de pop-up geopend en kan de volledige tekst met scrollen worden gelezen. Precies om het onhandige hiervan duidelijk te maken, is bij de zesde knop een lange tekst gebruikt.

Behalve klikken op het vraagteken is hier helaas geen simpele oplossing voor. (In vorige versies speelde dit probleem niet, maar die vorige versies werkten niet op touchscreens.)

Er is vrij veel ruimte voor tekst boven de pop-up. Als je niet meer tekst gebruikt dan in die ruimte past, speelt dit probleem niet. Als de lettergrootte wordt vergroot, kan de tekst te groot worden voor de beschikbare ruimte. En dan speelt het probleem weer. Dat is niet goed op te lossen: in dat geval ontkom je niet aan klikken om de pop-up geopend te houden. Overigens speelt dit probleem niet bij inzoomen (vergroten), dus heel vaak zal zich dit niet voordoen.

Bij gebruik van de Tab-toets is een lange tekst boven de pop-up niet volledig te lezen

Dit probleem speelt alleen in grotere browservensters, want alleen daar zijn pop-ups aanwezig.

Het verhaal gelijk hierboven geldt voor het openen van de pop-up bij hoveren. De oplossing is daar: klik op het vraagteken en de pop-up blijft open.

Dat is helaas ook voor gebruikers van de Tab-toets de enige mogelijkheid. Een goede oplossing is dit niet, want gebruikers van de Tab-toets kunnen nou juist vaak de muis niet goed gebruiken.

Bovendien moet, na klikken op het vraagteken, ook nog de muis worden gebruikt om de tekst boven de pop-up te kunnen scrollen. (Er moet in de tekst worden geklikt om de pijltjes te kunnen gebruiken, of er moet worden gescrold met behulp van het muiswieltje.)

Om dit probleem duidelijk te maken, is in de zesde pop-up te veel tekst aangebracht boven de afbeelding. Als je met de Tab-toets naar die zesde pop-up gaat en deze opent, zie je dat je zonder muis niet de volledige tekst kunt lezen. (Ja, je kunt de letters verkleinen. Je kunt ook vragen of ze even opbellen, zodat je de tekst kunt voorlezen. Ik bedoel maar: er zijn grenzen aan wat je van een bezoeker aan inspanning mag verwachten.)

De enige oplossing is hier: niet meer tekst gebruiken dan er zonder scrollen boven de afbeelding in de pop-up past.

Grotere lettergrootte

Dit probleem speelt alleen in grotere browservensters, waarin pop-ups verschijnen. Het geldt alleen voor een grotere lettergrootte, niet bij gewoon inzoomen (vergroten).

Zelfs bij een vergroting van 200% blijft alles gewoon werken. De tekst boven de afbeeldingen in de pop-up kan worden gescrold, als deze niet meer binnen de ruimte boven de afbeelding past.

Als de pop-up door middel van hoveren wordt geopend, verschijnt de naam van de achterliggende pagina boven de thumbnail. Bij vergrotingen van meer dan 150% kan, bij langere namen, een deel van die naam wegvallen onder de pop-up of aan de rechterkant van het browservenster.

Als de pop-up door middel van klikken of aanraken wordt geopend, staat er naast de naam nog een sluitkruis. Hierdoor is er minder ruimte voor de naam en speelt dit probleem al bij vergrotingen van meer dan 130%.

Als de Tab-toets wordt gebruikt om de knoppen af te gaan, verschijnt de naam van de achterliggende pagina boven de thumbnail, als de pop-up is geopend. Bij vergrotingen van meer dan 150% kan ook hier bij langere namen een deel van die naam wegvallen onder de pop-up of aan de rechterkant van het browservenster.

Bij een volgende tab sluit de pop-up weer en wordt de naam van de achterliggende pagina op de pop-up zelf getoond. Nu speelt het probleem alleen aan de rechterkant van het venster, waar een deel van de naam buiten het venster kan komen te staan. Op andere plaatsen is de naam volledig zichtbaar, al kan die gedeeltelijk buiten de thumbnail komen te staan.

Android browser

Niet alle versies tonen een gradiënt

Dit probleem speelt alleen in grotere browservensters, waarin pop-ups verschijnen.

Bij tablets in landschapsstand wordt onderaan de tekst een doorzichtige gradiënt neergezet, om aan te geven dat de tekst nog doorloopt. Niet alle versies van Android browser tonen deze gradiënt, omdat niet alle versies goed met calc() uit de voeten kunnen.

De knoppen staan niet in alle versies netjes verticaal verdeeld

Dit probleem speelt alleen in grotere browservensters, waarin pop-ups verschijnen.

Als er geen vier knoppen onder elkaar passen, komen er links en rechts van de kolom twee knoppen te staan. De andere vier knoppen komen dan onder de tekst te staan. In totaal zijn er dus drie regels met knoppen.

De afstand tussen die regels moet gelijk zijn, zodat ze netjes worden verdeeld. De afstand wordt berekend met behulp van calc(). Niet alle versies van deze browser kunnen goed daarmee overweg. In sommige versies staat de tweede regel met knoppen daardoor gelijk onder de eerste regel.

Gradiënt op verkeerde plaats bij inzoomen (vergroten)

Dit probleem speelt alleen in grotere browservensters, waarin pop-ups verschijnen.

Bij tablets in landschapsstand wordt onderaan de tekst een doorzichtige gradiënt neergezet, om aan te geven dat de tekst nog doorloopt. Als wordt ingezoomd, staat deze gradiënt niet meer op de juiste plaats onderaan de tekst, maar ergens midden op de tekst.

Omdat de gradiënt behoorlijk doorzichtig is en tekst onder de gradiënt gewoon geselecteerd, gekopieerd, en dergelijke kan worden, is dit geen erg groot probleem. Het is meer niet netjes, dan dat het echt heel storend is.

De kop beslaat in portretstand soms de volle breedte van het venster

Dit probleem speelt alleen in grotere browservensters, waarin pop-ups verschijnen.

In bredere browservensters wordt de breedte van de <h1> bovenaan de pagina berekend met behulp van van calc(). Niet alle versies van deze browser kunnen daarmee goed uit de voeten. Er is ook een maximumbreedte van 870 px opgegeven, en die werkt wel altijd. In vensters smaller dan 870 px kan daardoor de <h1> de volle breedte van het venster beslaan. Dat valt nauwelijks op, want de tekst in de <h1> is wel gecentreerd. Alleen aan de achtergrondkleur van de <h1> is dit probleem te zien, want die is breder dan de bedoeling zou moeten.

Firefox (alle versies)

Bij de zesde knop is een extra tab nodig

Dit probleem speelt alleen in grotere browservensters, waarin pop-ups verschijnen.

Bij de zesde pop-up staat zoveel tekst boven de afbeelding, dat deze gescrold moet worden om de tekst volledig te kunnen lezen. Om een of andere reden is hierdoor bij gebruik van de Tab-toets een extra aanslag van de Tab-toets nodig. Als de tekst zoveel wordt ingekort dat scrollen niet meer nodig is, is de extra tab ook niet meer nodig.

Wat dit veroorzaakt is mij een raadsel. Het lijkt erop dat Firefox iets doet als het spontaan invoegen van tabindex="0" bij de <span> met de tekst, als er gescrold moet worden.

Firefox (Android)

Gradiënt op verkeerde plaats bij inzoomen (vergroten)

Dit probleem speelt alleen in grotere browservensters, waarin pop-ups verschijnen.

Bij tablets in landschapsstand wordt onderaan de tekst een doorzichtige gradiënt neergezet, om aan te geven dat de tekst nog doorloopt. Als wordt ingezoomd, staat deze gradiënt niet meer op de juiste plaats onderaan de tekst, maar ergens midden op de tekst.

Omdat de gradiënt behoorlijk doorzichtig is en tekst onder de gradiënt gewoon geselecteerd, gekopieerd, en dergelijke kan worden, is dit geen erg groot probleem. Het is meer niet netjes, dan dat het echt heel storend is.

Internet Explorer 9

Geen gradiënt

Dit probleem speelt alleen in grotere browservensters, waarin pop-ups verschijnen.

Internet Explorer 9 kent geen gradiënt. Als er onder de kolom met tekst knoppen staan, hoort er een doorzichtige gradiënt onderaan de tekst te staan, zodat duidelijk is dat deze tekst nog doorloopt. Deze gradiënt ontbreekt bij Internet Explorer 9.

Je kunt eventueel een zogenaamde 'polyfill' gebruiken om dit toch voor elkaar te krijgen, maar daar vond ik het niet belangrijk genoeg voor. Op internet kun je zoeken naar polyfills, maar de kwaliteit daarvan is zeer wisselend.

Op de site van modernizr staat een grote verzameling kwalitatief goede polyfills.

iOS

Omdat alle browsers op iOS de weergave-machine van Safari gebruiken, zijn veel van de problemen hetzelfde. Daarom worden alle browsers op iOS hier bij elkaar gezet.

Bij inzoomen (vergroten) staat gradiënt niet op de goede plaats

Dit probleem speelt alleen in grotere browservensters, waarin pop-ups verschijnen.

Bij tablets in landschapsstand wordt onderaan de tekst een doorzichtige gradiënt neergezet, om aan te geven dat de tekst nog doorloopt. Als wordt ingezoomd, staat deze gradiënt niet meer op de juiste plaats onderaan de tekst, maar ergens midden op de tekst.

Omdat de gradiënt behoorlijk doorzichtig is en tekst onder de gradiënt gewoon geselecteerd, gekopieerd, en dergelijke kan worden, is dit geen erg groot probleem. Het is meer niet netjes, dan dat het echt heel storend is.

Verspringend gradiënt (alleen UC browser)

Dit probleem speelt alleen in grotere browservensters, waarin pop-ups verschijnen.

Bij tablets in landschapsstand wordt onderaan de tekst een doorzichtige gradiënt neergezet, om aan te geven dat de tekst nog doorloopt. Deze gradiënt is met behulp van position: fixed; vastgezet. Als de tekst wordt gescrold, beweegt de gradiënt in UC browser mee met de tekst. Als niet meer wordt gescrold, springt de gradiënt terug naar de plaats, waar hij hoort te staan. Niet heel erg storend, maar het hoort niet.

UC browser op Android

Soms opent de pop-up niet, maar wordt de link gevolgd

Dit probleem speelt alleen in grotere browservensters, waarin pop-ups verschijnen.

Bij aanraken van het vraagteken moet een pop-up openen. Om onduidelijke redenen wordt soms niet de pop-up geopend, maar wordt de link gevolgd en opent de achter de knop zittende pagina gelijk.

Enige regelmaat in dit verschijnsel heb ik niet kunnen vinden. Experimenteren met dingen als een andere z-index had geen enkel effect. Het enige wat ik met zekerheid heb kunnen vaststellen: het gebeurt bij de vraagtekens rechts van de tekst meer dan bij de vraagtekens links van de tekst. In portretstand gebeurt het links zelfs helemaal niet. Als je het scherm ergens aanraakt, voordat je het vraagteken aanraakt, gaat het ook goed.

Kortom: een onduidelijke bug.

Niet alle versies tonen een vinkje, als de pagina is bezocht

Dit probleem speelt alleen in grotere browservensters, waarin pop-ups verschijnen.

Als een pagina is bezocht, moet naast het vraagteken een vinkje verschijnen. Niet alle versies van UC browser op Android tonen dit vinkje.

De knoppen staan niet netjes verticaal verdeeld

Dit probleem speelt alleen in grotere browservensters, waarin pop-ups verschijnen.

Als er geen vier knoppen onder elkaar passen, komen er links en rechts van de kolom twee knoppen te staan. De andere vier knoppen komen dan onder de tekst te staan. In totaal zijn er dus drie regels met knoppen.

De afstand tussen die regels moet gelijk zijn, zodat ze netjes worden verdeeld. De afstand wordt berekend met behulp van calc(). UC browser op Android kent calc() niet. Daardoor staat de tweede regel met knoppen gelijk onder de eerste regel.

Geen gradiënt

Dit probleem speelt alleen in grotere browservensters, waarin pop-ups verschijnen.

Bij tablets in landschapsstand wordt onderaan de tekst een doorzichtige gradiënt neergezet, om aan te geven dat de tekst nog doorloopt. Omdat UC browser op Android calc() niet kent, ontbreekt daar deze gradiënt.

De kop beslaat in portretstand de volle breedte van het venster

Dit probleem speelt alleen in grotere browservensters, waarin pop-ups verschijnen.

In bredere browservensters wordt de breedte van de <h1> bovenaan de pagina berekend met behulp van van calc(). UC browser op Android kent dat niet. Er is ook een maximumbreedte van 870 px opgegeven, en die werkt wel altijd. In vensters smaller dan 870 px kan daardoor de <h1> de volle breedte van het venster beslaan. Dat valt nauwelijks op, want de tekst in de <h1> is wel gecentreerd. Alleen de achtergrondkleur van de <h1> beslaat de volle breedte.

Wijzigingen

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

:

De code voor deze versie lijkt in niets meer op die van eerdere versies. Daarom zijn eerdere wijzigingen weggehaald. In feite is dit voorbeeld op deze datum nieuw opgenomen.

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.

* De foto's zijn gemaakt in het Vondelpark in Amsterdam op Koninginnedag 2009. Als je jezelf herkent en de originele foto wilt hebben, stuur dan even 'n mailtje naar info@css-voorbeelden.nl.

menu-019-dl.html: de pagina met het voorbeeld.

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

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

019-css-dl:

menu-019-dl.css: stylesheet voor menu-019-dl.html.

menu-019-hulp-dl.css: stylesheet voor pagina's in 019-files-dl.

019-files-dl:

de pagina's achter de knoppen, in totaal acht html-pagina's.

019-pics:

8 thumbnails (te herkennen aan 'thumb' in de naam).

8 grotere afbeeldingen voor in de pop-up.

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>

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.

<html lang="nl">

De toevoeging lang="nl" bij <html> geeft aan dat de pagina in het Nederlands is. De taal is van belang voor schermlezers, automatisch afbreken, automatisch genereren van aanhalingstekens, juist gebruik van decimale punt of komma, en dergelijke.

<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. Op deze pagina bijvoorbeeld worden knoppen, pop-ups, enz. volledig aangepast aan de grootte van het venster.

Maar die stomme mobiele browser weet dat niet, dus die gaat ervan uit dat ook deze 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.

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

<span class="focus-open" tabindex="0"></span>

Sommige mensen gebruiken geen muis of aanraking, maar de Tab-toets om links, tekstvelden, en dergelijke af te gaan. Dat kan vanwege een handicap zijn, maar ook omdat het soms veel sneller en makkelijker werkt dan een muis.

Normaal genomen wordt een <span> bij gebruik van de Tab-toets genegeerd. Door het attribuut tabindex="0" toe te voegen, worden nu ook de <span>'s bezocht. Dat maakt het mogelijk in de css de selector .focus-open:focus te gebruiken om daarmee de pop-up te kunnen openen.

(Elke pop-up heeft een eigen radioknop. Al deze knoppen behoren tot dezelfde groep. Als een knop is geselecteerd, wordt de pop-up geopend. Deze knoppen kunnen niet worden gebruikt om met behulp van :focus de bijbehorende pop-up te openen, want als een radioknop uit een bepaalde groep focus heeft, kan een andere radioknop uit dezelfde groep geen focus krijgen. Om van radioknop naar radioknop te gaan binnen dezelfde groep knoppen, gebruik je niet de Tab-toets, maar pijltjes. Vandaar deze aparte <span> voor gebruikers van de Tab-toets.)

<img src="019-pics/thumb-band.jpg" width="180" height="161" alt="">

De thumbnails. Bij elke thumbnail staat een omschrijving. Deze omschrijving wordt door schermlezers voorgelezen. Daarom heeft het weinig zin om bij de thumbnail ook nog een alt op te nemen. Een alt wordt door sommige schermlezers voorgelezen, waardoor je twee keer hetzelfde verhaal te horen zou krijgen.

Maar schermlezers melden het vaak wel, als een afbeelding aanwezig is. Als er verder geen alt of zoiets in de <img> staat, wordt soms de naam van het bestand voorgelezen.

Door de toevoeging van het attribuut alt="" weten schermlezers, dat ze deze afbeelding volledig kunnen negeren. Dit werkt alleen als er echt alt="" staat (niets tussen de aanhalingstekens). Als je alt gewoon weglaat, is er een grote kans dat de naam van het bestand wordt voorgelezen.

<label class="open" for="open-1" role="presentation">

Bij elke thumbnail hoort een radioknop, die zorgt voor het openen van de pop-up door middel van aanraken of klikken. Bij elk van die knoppen hoort een <label>. Deze <label>'s hebben geen enkel nut voor schermlezers, maar kunnen wel heel verwarrend zijn. In sommige gevallen meldt de schermlezer dat er een <label> is, maar het is volstrekt onduidelijk waar die dan voor is.

Daarom is het beter de <label>'s te verbergen voor schermlezers. Dat kan echter bij label.open niet, want in deze <label>'s zit ook de beschrijving van de thumbnail. En die zou dan ook worden verborgen voor schermlezers.

Met de WAI-ARIA-code role="presentation" wordt de <label> niet verborgen, maar wordt hij gedegradeerd tot een element zonder enige semantische betekenis. Zeg maar 'n soort <span>. Meer over WAI-ARIA-codes en semantiek is te vinden bij Semantische elementen en WAI-ARIA.

<span class="vraagteken" aria-hidden="true" title="Klik om pop-up open te houden">?</span>

Bij elke thumbnail hoort een <span> met daarin een vraagteken. Deze <span>'s hebben geen enkel nut voor schermlezers, maar kunnen wel heel irritant zijn. Elk vraagteken wordt namelijk – bij gebrek aan andere tekst in de <span> – voorgelezen.

Met behulp van het attribuut aria-hidden="true" worden de <span>'s verborgen voor schermlezers. Meer hierover bij WAI-ARIA-codes.

<label class="sluit" for="sluit-x" aria-hidden="true">x</label>

Bij elke thumbnail zit een <label>, dat hoort bij de radioknop die zorgt voor het sluiten van de pop-ups na openen door middel van aanraken of klikken. Deze <label>'s hebben geen enkel nut voor schermlezers, maar kunnen wel heel verwarrend zijn. Bovendien wordt de in de <label> zittende letter 'x' voorgelezen, wat ook een tamelijk zinloze onderneming is.

Met behulp van het attribuut aria-hidden="true" worden de <label>'s verborgen voor schermlezers. Meer hierover bij WAI-ARIA-codes.

<input id="checkbox-voor-focus" type="checkbox" aria-hidden="true" autofocus>

Bovenaan de kolom met tekst zit een <input>, die feitelijk geen enkele werking heeft. Maar door het attribuut autofocus toe te voegen, wordt de focus bij openen van de pagina op de tekst gezet. Hierdoor kan gelijk gescrold worden met behulp van het muiswieltje of met toetsen als de pijltjes.

Zonder deze <input> moet eerst in de tekst worden geklikt, omdat in de html de knoppen voor de tekst zitten. Pas daarna kan dan worden gescrold en dergelijke.

(Je zou ook in de html de <main> met de tekst voor de <nav> met de knoppen kunnen neerzetten. Op de site kan dat niet, omdat er nog veel meer links in de <nav> zitten. Daarom is dat in dit voorbeeld ook niet gebeurd, want dat zou weer 'n extra verschil met de site opleveren.)

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. Als je op internet zoekt naar 'css' en 'compress' of 'comprimeren', vind je tal van sites, waar je dat automatisch kunt laten doen.

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

@-webkit-keyframes bugfix {from {padding-left: 0;} to {padding-left: 0;}}

Op een aantal plaatsen wordt in een selector gebruik gemaakt van het teken ~ (de 'general sibling'-selector). Oudere versies van Android browser hebben daar soms problemen mee. In dit voorbeeld wordt het sluitkruisje niet getoond, als de pop-up door middel van aanraking wordt geopend. Het toevoegen van deze animatie op een aantal plaatsen in de css, lost dit probleem op.

Als je nou denkt dat hier niets wordt uitgevoerd, omdat de padding links van 0 px in een padding links van 0 px wordt veranderd, dan heb je helemaal gelijk. Toch neutraliseert deze flauwekul de bug.

Normaal genomen is het een bijzonder slecht idee css te gebruiken voor slechts één weergave-machine: webkit. Maar in dit geval is dit terecht, want de bug zit alleen in op webkit gebaseerde browsers. Het heeft dus geen zin om Internet Explorer of Firefox ook met deze ongein te belasten.

Waarom dit alleen in webkit-browsers werkt, staat bij De voorvoegsels -moz-, -ms- en -webkit-.

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: #eee;

Achtergrondkleurtje.

color: black;

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

Hoewel dit de standaardkleur is, wordt deze toch specifiek opgegeven. Hierboven is een achtergrondkleur opgegeven. Sommige mensen hebben zelf de voorgrond- en/of achtergrondkleur veranderd, bijvoorbeeld omdat ze slecht kleuren kunnen onderscheiden. Als nu de achtergrondkleur wordt veranderd, maar niet de voorgrondkleur, loop je het risico dat tekstkleur en achtergrondkleur te veel op elkaar gaan lijken.

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

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

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

margin: 0; padding: 0;

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

h1

Alle <h1>'s. Dat is er maar eentje: de belangrijkste kop op de pagina.

background: #eee;

Achtergrondkleurtje.

color: black;

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

Hoewel dit de standaardkleur is, wordt deze toch specifiek opgegeven. Hierboven is een achtergrondkleur opgegeven. Sommige mensen hebben zelf de voorgrond- en/of achtergrondkleur veranderd, bijvoorbeeld omdat ze slecht kleuren kunnen onderscheiden. Als nu de achtergrondkleur wordt veranderd, maar niet de voorgrondkleur, loop je het risico dat tekstkleur en achtergrondkleur te veel op elkaar gaan lijken.

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

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

font-size: 1em;

Van zichzelf heeft een <h1> een veel grotere letter. Hier wordt dat veranderd in 'n normale lettergrootte.

Als eenheid wordt de relatieve eenheid em gebruikt, omdat bij gebruik van een absolute eenheid zoals px niet alle browsers de lettergrootte kunnen veranderen. Zoomen kan wel altijd, ongeacht welke eenheid voor de lettergrootte wordt gebruikt.

line-height: 30px;

Er wordt geen hoogte opgegeven voor de <h1>, alleen een regelhoogte. Bij gebrek aan een hoogte wordt de regelhoogte ook de hoogte van de <h1>. Voordeel is dat tekst automatisch halverwege de regelhoogte wordt neergezet, waardoor de kop netjes verticaal in het midden van de <h1> staat.

text-align: center;

Tekst horizontaal centreren.

margin: 0;

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

ul

Alle <ul>'s. Dat is er hier maar eentje: de <ul> waar de knoppen met toebehoren in staan.

list-style-type: none;

Bolletjes en dergelijke bij de lijst-items verwijderen.

margin: 0; padding: 0;

De standaardinstellingen voor marge en padding zijn niet in alle browsers hetzelfde. Door ze op 0 te zetten, zijn ze overal hetzelfde.

abbr[title]

Deze selector valt in twee delen uiteen.

abbr: alle <abbr>'s.

[title]: met de teksthaken geef je aan, dat er een extra voorwaarde aan het element wordt gesteld. In dit geval is dat vrij simpel: het title-attribuut moet aanwezig zijn.

De hele selector: alle <abbr>'s, maar alleen als ze het title-attribuut hebben.

In het voorbeeld staat slechts twee keer een <abbr>. De eerste:

<abbr lang="en" title="Cascading Style Sheets">css</abbr>

Hier is het title-attribuut aanwezig. (Omdat de tekst in het title-attribuut Engelstalig is, is ook nog lang="en" toegevoegd, de taalcode voor Engels.)

De tweede keer ziet de <abbr> er zo uit:

<abbr>css</abbr>

Hier ontbreekt het title-attribuut.

De eerste <abbr> valt dus onder deze selector, de tweede niet.

De eerste keer wordt de afkorting 'css' voluit aangegeven in de titel. Bij latere herhalingen gebeurt dat niet meer. Wel wordt bij latere afkortingen <abbr> gebruikt, om te voorkomen dat een schermlezer 'css' als woord probeert uit te spreken.

Afhankelijk van schermlezer en instellingen kan het title-attribuut worden voorgelezen door een schermlezer. Bij hoveren over de <abbr> verschijnt de title in een klein venstertje.

Er zijn nogal wat uiteenlopende meningen over dit hele title-gedoe bij <abbr>. Op touchscreens heb je er niets aan. En niet alle schermlezers kunnen er mee uit de voeten. Daarom kiezen sommigen ervoor de eerste keer de title ook volledig weer te geven in de gewone tekst. Maar dat betekent weer, dat sommige schermlezers het twee keer voorlezen.

Er zijn ook sitebouwers die bij élke <abbr> de title toevoegen. Dat is mij te gek, want dat zou betekenen dat in 'n pagina met uitleg honderden keren html en css voluit moeten worden weergegeven in de title. Bovendien is het nogal irritant voor gebruikers van schermlezers als ze elke keer volledig voluit 'Cascading Style Sheets' of 'HyperText Markup Language' horen in plaats van 'css' en 'html'.

Iets wat je ook met enige regelmaat gebruikt ziet worden:

abbr[title]::after {content: " (" attr(title) ")";

Dit zet de titel van de <abbr> achter de afkorting op het scherm, tussen haakjes. Maar alleen als de <abbr> een title-attribuut heeft. Op deze manier kun je de afkorting alleen de eerste keer voluit laten schrijven, door alleen de eerste <abbr> een title te geven. Maar ook dit lost niet alles op, want bij latere <abbr>'s is de volledige afkorting nog steeds onbekend.

Je kunt ook ingewikkelde oplossingen met JavaScript gaan bedenken, maar dat wordt toch 'n beetje al te veel van het goede voor een relatief simpel hulpmiddel.

Afbeelding 7: de titel bij een afkorting

Ik kies ervoor alleen bij de eerste <abbr> een title-attribuut toe te voegen. Met de css hieronder wordt aangegeven dat onder die afkorting uitleg zit. Op de afbeelding is te zien hoe dat er in Firefox op Linux uitziet. De afkorting 'css' is onderstippeld, en bij hoveren over de afkorting verschijnt een venstertje met de volledige afkorting. De cursor verandert in een vraagteken.

cursor: help;

Cursor veranderen in 'n hulpsymbooltje. Hoe dat er precies uitziet, verschilt per browser en per besturingssysteem.

text-decoration: none; border-bottom: dotted 1px;

Niet alle browsers geven een <abbr> met een title-attribuut aan. En de browsers die het wel doen, gebruiken er verschillende methoden voor. Met text-decoration: none; wordt de onderstreping overal verwijderd. En met border-bottom: dotted 1px; wordt overal een onderstippeld lijntje onder de <abbr> geplaatst.

Nu ziet het er in alle browsers hetzelfde uit.

input, .vraagteken, .sluit

Alle <input>'s, de elementen met class="vraagteken en class="sluit".

<input>'s worden voornamelijk gebruikt voor het openen en sluiten van de pop-ups. Maar de feitelijke bediening gebeurt door de bijbehorende <label>'s, de <input>'s zelf hoeven niet zichtbaar te zijn. Voor grotere browservensters wordt input#checkbox-voor-focus later bij #checkbox-voor-focus weer zichtbaar gemaakt.

Elke thumbnail heeft een bijbehorende span.vraagteken en label.sluit. Die worden alleen gebruikt om de pop-ups te openen en te sluiten. Dat gebeurt niet in kleine vensters, dus die kunnen hier worden verborgen.

display: none;

Verbergen.

Door het gebruik van display: none; worden deze elementen ook voor schermlezers verborgen. Dat is prima, want ze zijn voor schermlezers alleen maar uiterst verwarrend, zonder dat ze nut hebben.

Meer over schermlezers en deze elementen is te vinden bij WAI-ARIA-codes.

.naam

Alle elementen met class="naam". Binnen elke link <a> zit een <span> met deze class. Binnen die <span> zit de korte naam (één woord) van de achterliggende pagina.

(Één woord is nogal kort voor de beschrijving van een pagina. Maar daarnaast zijn er de thumbnails van de pagina en de omschrijving van de thumbnails.)

opacity: 0;

Volledig doorzichtig maken.

Deze naam moet op verschillende momenten op verschillende plaatsen zichtbaar zijn. display: none; of visibility: hidden; kunnen niet worden gebruikt, want schermlezers negeren de tekst dan volledig. En buiten deze tekst staat er niets in de <a>. Sommige schermlezers gaan dan, bij gebrek aan beter, de naam van de pagina voorlezen of andere rampzaligheden. Stel je even de wanhoop voor van een schermlezer die probeert '019-files-dl/keyboards-dl.html' begrijpelijk voor te lezen...

Nu is er voor schermlezers in de <a> een korte naam om voor te lezen.

h2

Alle <h2>'s. Dat er hier maar eentje. Daarin staat 'Navigatie site'.

De thumbs met bijbehorende links en dergelijke staan in een <ul> binnen een <nav>. Hierdoor zijn ze goed toegankelijk voor schermlezers, want die kondigen een <nav> op een of andere manier aan als een menu. Maar wat voor soort menu, dat blijft raden. Daarom wordt bovenin de <nav> 'Navigatie site' gezet. Dit wordt voorgelezen door schermlezers, zodat duidelijk is waar het menu voor dient.

Je zou de tekst ook in een gewone <span> of zo kunnen zetten, maar schermlezers kunnen heel makkelijk van <h> naar <h> springen of een lijstje met <h>'s tevoorschijn toveren. Hierdoor is er een extra manier om de navigatie snel te vinden, zonder dat dat ook maar enig extra werk met zich meebrengt.

position: absolute; left: -20000px;

Voor mensen die kunnen zien, is deze titel volstrekt overbodig. Daarom wordt de <h2> links buiten het scherm geparkeerd. Schermlezers lezen hem gewoon voor, maar de lay-out wordt niet verpest door een overbodige mededeling.

li

Alle <li>'s. Dat zijn er hier acht: ééntje voor elke thumbnail met bijbehorende link en dergelijke.

background: #eee;

Achtergrondkleurtje.

color: black;

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

Hoewel dit de standaardkleur is, wordt deze toch specifiek opgegeven. Hierboven is een achtergrondkleur opgegeven. Sommige mensen hebben zelf de voorgrond- en/of achtergrondkleur veranderd, bijvoorbeeld omdat ze slecht kleuren kunnen onderscheiden. Als nu de achtergrondkleur wordt veranderd, maar niet de voorgrondkleur, loop je het risico dat tekstkleur en achtergrondkleur te veel op elkaar gaan lijken.

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

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

box-sizing: border-box;

Normaal genomen worden border en padding bij de breedte en hoogte opgeteld. Hier komt het beter uit, als border en padding binnen de breedte vallen. Met deze regel wordt dat bereikt.

Iets hieronder wordt een breedte opgegeven van 100%: even breed als het venster van de browser. Daar komen normaal genomen padding (links en rechts 4 px) en border (links en rechts 1 px) echter nog bij. Daardoor wordt het totaal breder dan het venster: 100% + 10 px. Door border en padding binnen de breedte te laten vallen, geldt de maximumbreedte van 100% nu voor de breedte inclusief border en padding.

width: 100%;

Breedte.

Een breedte in procenten wordt altijd genomen ten opzichte van de breedte van de ouder. Dat is hier het blok-element <ul>. Als een blok-element geen breedte heeft gekregen, wordt dat automatisch even breed als z'n ouder. De ouder van <ul> is <nav>, de ouder daarvan is <header>, en de ouder daarvan is <body>. Alle drie blok-elementen, waarbij geen breedte is opgegeven en die dus ook weer even breed worden als hun ouder.

De ouder van <body> is <html>, het laatste element. Ook dit is een blok-element zonder breedte. En dan zijn we er eindelijk: de ouder van <html> is het venster van de browser. <html> en in het kielzog daarvan <body>, <header>, <nav>, <ul> en uiteindelijk <li> worden even breed als het browservenster. Oftewel: de <li>'s vullen altijd de volle breedte van het venster, en daarmee ook de in de <li> zitten de tekst en dergelijke.

(Een <li> is ook een blok-element. Dus dan is deze hele waanzinnige exercitie toch overbodig? Nee, want gelijk hieronder wordt de <li> gefloat. En gefloate elementen worden niet breder, dan nodig is voor de inhoud. Als er maar weinig in de <li> staat, wordt deze hierdoor smaller dan het venster van de browser.)

float: left; Afbeelding 8: zonder correctie valt bij weinig tekst een deel van de thumbnail weg

Een <li> is een blok-element. Daardoor wordt elke <li> op een nieuwe regel gezet. Door ze naar links te floaten, worden ze naast elkaar gezet.

Dat is hier echter vrij zinloos, omdat de <li> hier gelijk boven even breed als het venster van de browser is gemaakt, dus er passen er nooit twee of meer naast elkaar.

In dit geval heeft float een andere functie. Binnen de <li> zit een <img>. Die wordt bij img naar links gefloat, zodat er tekst naast komen te staan. Maar dan ontstaat er een probleem.

Een blok-element, dus ook deze <li>, wordt normaal genomen automatisch precies hoog genoeg om de inhoud ervan weer te geven. Dat is hier de <img> met de ernaast staande tekst. Verder zit er nog een <a> in de <li>. De <li> zou normaal precies hoog genoeg worden, om de erin zittende <img>, de tekst daarnaast en de <a> weer te geven. (Er zit nog meer in de <li>, maar dat gaat pas meedoen in grotere browservensters. Het is hier verborgen.)

De <a> is absoluut gepositioneerd. Absoluut gepositioneerde elementen tellen niet mee voor de hoogte van de <li>. Blijven de <img> en de ernaast staande tekst over.

De <img> is naar links gefloat. Ook gefloate elementen tellen niet mee voor de hoogte van hun ouder. Alleen de tekst blijft over: de <li> wordt niet hoger dan nodig is om de tekst naast de <img> weer te geven.

Bij weinig tekst valt hierdoor een deel van de <img> aan de onderkant weg. Op de afbeelding is te zien dat bij de eerste en derde thumbnail, waarnaast weinig tekst staat, het onderste deel van de thumbnail gewoon wordt afgekapt. (Er gebeuren nog meer vreemde dingen, maar die laat ik even zitten.)

Je kunt dit op een aantal manieren oplossen. In dit geval is de simpelste manier om ook de <li>'s te floaten. In dat geval tellen gefloate kinderen van de <li>, hier de <img>, weer mee voor de hoogte. Hierdoor wordt de <li> automatisch even hoog als de thumbnail of de tekst, afhankelijk van welk van deze twee het hoogst is, en verdwijnen er geen delen van de <img> meer bij weinig tekst.

margin-top: -1px;

Rondom de <li>'s wordt hier gelijk onder een zwart randje van 1 px dik gezet. Omdat de <li>'s onder elkaar staan, komen tussen twee <li>'s twee randjes tegen elkaar te staan. Samen zijn die 2 px dik. Door de <li> 1 px naar boven te verplaatsen, vallen de randjes over elkaar heen en is de rand ook hier 1 px dik.

border: black solid 1px;

Zwart randje rondom de <li>.

padding: 4px 4px 10px;

Omdat voor links geen waarde is opgegeven, krijgt links automatisch dezelfde waarde als rechts. Hier staat dus eigenlijk 4px 4px 10px 4px in de volgorde boven – rechts – onder – links. Overal wat afstand tussen inhoud en buitenkant van de <li>. Aan de onderkant iets meer, zodat de <li>'s wat minder dicht op elkaar lijken te staan.

position: relative;

Om kinderen van een element te kunnen positioneren ten opzichte van dat element, moet het element zelf zijn gepositioneerd. Omdat verder niets voor top en dergelijke wordt opgegeven, heeft dit verder geen enkele invloed op het element zelf.

a

Alle <a>'s. Dit zijn de links naar de achter de knoppen zittende pagina's.

Door deze <a>'s even groot te maken als de thumbnails en ze daaroverheen te zetten, gaat de hele thumbnail als link werken.

width: 120px; height: 108px;

Zelfde breedte en hoogte als gelijk hieronder aan de <img>'s met de thumbnails wordt gegeven.

position: absolute;

Om de <a> op de juiste plaats neer te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf is gepositioneerd. Dat is hier de <li> waar de <a> in zit.

Een <a> is een inline-element. Daardoor kunnen eigenschappen als breedte en hoogte niet worden gebruikt. Door de <a> absoluut te positioneren, verandert deze in een soort blok-element, waardoor dit soort eigenschappen wel gebruikt kunnen worden.

top: 8px; left: 8px;

Op deze positie komt de <a> precies boven de thumbnail te staan, waardoor de hele thumbnails als link gaat werken.

img

Alle <img>'s. Dat zijn hier de acht thumbnails.

box-shadow: 4px 6px 4px 1px; Afbeelding 9: thumbnail met schaduw

Schaduw aan de thumbnail geven.

Met behulp van box-shadow kan schaduw worden gegeven aan een element.

Als je verder niets opgeeft, is de schaduw 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. De natte droom van de Gevorderde Geheim Agent, maar niet van een sitebouwer.

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: rechtsonder de thumbnail. Hieronder zijn de waarden iets veranderd, zodat het effect van de verschillende waarden duidelijker is te zien.

Afbeelding 10: box-shadow alleen rechts zichtbaar

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

Hier is gelijk iets te zien, waar je op moet letten: een box-shadow wordt plompverloren bovenop aangrenzende elementen gezet. Op de afbeelding staat de schaduw over de ernaast staande tekst. Je moet dus altijd voor voldoende ruimte rondom het element met de schaduw zorgen.

Afbeelding 11: box-shadow alleen aan onderkant zichtbaar

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.

Ook hier geldt weer dat de schaduw plompverloren bovenop aangrenzende elementen wordt neergepoot, zoals hier over de eronder staande tekst.

Afbeelding 12: box-shadow met alleen vervaging

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 het kenmerk van een vervaging.

Afbeelding 13: box-shadow met alleen breedte

1px: het vierde getal geeft de breedte van de schaduw aan. Om bijstaande artistieke hoogstandje te krijgen, zijn de waarden 0 0 0 30px gebruikt: de schaduw is 30 px breed. Als schaduw is deze zielenpoot duidelijk mislukt, maar je kunt hier wel allerlei andere grapjes mee uithalen, zoals een tweede border. En aangezien je meerdere box-shadows kunt gebruiken, kun je met box-shadow feitelijk een oneindig aantal borders maken.

Je kunt ook nog een kleur opgeven bij box-shadow. Als je geen kleur opgeeft, wordt de voorgrondkleur gebruikt. Die voorgrondkleur is hier zwart, daarom zou het opgeven van een kleur hier niet nodig moeten zijn. Maar sommige versies van Android browser geven geen schaduw, als je geen kleur opgeeft. Daarom wordt toch een kleur opgegeven.

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. Op de pagina met links staan onder het kopje CSS → Online uitproberen, code genereren, en dergelijke sites, waar je online een box-shadow kunt maken.

width: 120px;

Breedte.

In de html is ook een breedte opgegeven, maar zodra in de css een breedte wordt opgegeven, 'wint' die van de breedte in de html. De in de html opgegeven breedte van 180 px is voor bredere browservensters.

De echte breedte van de thumbnail is 180 px. Dit is ook de breedte die in grotere vensters wordt gebruikt. Maar voor kleinere vensters wordt de breedte iets verkleind. Dat is eigenlijk hartstikke verkeerd, omdat hierdoor een groter bestand wordt gedownload, dan nodig is. Normaal genomen zou je voor kleinere vensters thumbnails van 120 px breed maken. Maar het verschil in bestandsgrootte is zo klein, dat ik het hier de moeite niet waard vind.

height: auto; Afbeelding 14: thumbnail vervormd door te grote hoogte

In de html is bij de <img> ook een hoogte opgeven: 161 px. Dat is de echte hoogte van de thumbnail, maar die wordt alleen gebruikt in grotere browservensters.

Hier gelijk boven is de breedte verkleind van 180 tot 120 px. Als de hoogte hier niet wordt aangepast, blijft deze gewoon 161 px. Dat leidt tot thumbnails van 120 bij 161 px waarop alleen nog wanstaltig lange kinderen staan, zoals op de afbeelding hiernaast is te zien: een broodmagere vijfjarige met de lengte van een forse volwassene.

(Hier gelijk onder staat hetzelfde kind op een thumbnail met de juiste verhoudingen. Nogal 'n verschil.)

Door als hoogte auto op te geven, bepaalt de browser de hoogte. Daardoor blijven de verhoudingen van de foto intact. Omdat de breedte van 180 naar 120 px is verkleind, een derde minder, wordt ook de hoogte met een derde verminderd. De foto wordt nu niet vervormd, wat een ernstige groeistoornis bij het arme kind voorkomt.

float: left; Afbeelding 15: tekst staat niet allemaal naast thumbnail

Zo ver mogelijk naar links neerzetten. Dat maakt hier voor de <img> eigenlijk niet zoveel uit, want de thumb zou hoe dan ook ongeveer op deze plaats komen te staan.

De <img> wordt hier gefloat, omdat de tekst dan over de volle hoogte van de <img> naast de <img> wordt gezet.

Een <img> is een inline-element. Een ietwat apart inline-element, maar het blijft een inline-element. De <label> waar de tekst in staat is ook een inline-element. Daardoor worden normaal genomen beide elementen, net als gewone tekst, naast elkaar op dezelfde regel gezet. Daarbij bepaalt de thumb, omdat die het hoogst is, de regelhoogte. Dat is op de afbeelding te zien: naast de thumb staat één regel tekst, niet meer.

Door de thumb naar links te floaten, vult de tekst de volledige lege ruimte links van de thumb.

margin: 3px 10px 6px 3px;

Aan alle kanten wat marge, zodat de thumb op een nette manier wordt neergezet. De marge rechts is wat hoog. De box-shadow aan de rechterkant van de thumbnail neemt ongeveer 6 px in beslag, dus er zijn rechts 6 px meer nodig voor voldoende afstand tot de tekst.

border: black solid 1px;

Zwart randje rondom de thumb.

border-radius: 5px;

Aan alle kanten ronde hoeken.

.pop-up-tekst

Alle elementen met class="pop-up-tekst". De <span>'s waarbinnen de toelichting bij de thumbnails staat. In kleinere browservensters zijn deze teksten altijd zichtbaar. Ze staan rechts van de thumbnails (en eronder, als rechts te weinig ruimte is voor alle tekst).

-moz-hyphens: auto; -ms-hyphens: auto; -webkit-hyphens: auto; hyphens: auto;
Afbeelding 16
Afbeelding 16: links de tekst zonder afbreken, rechts de tekst met afbreken in een venster van 310 px breed.

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

In kleinere browservensters staat de tekst rechts van de thumbnails. Daar kan, in smalle vensters, heel erg weinig ruimte zijn. Daarom wordt hier automatisch afbreken van woorden aangezet.

In heel smalle vensters wordt het nooit echt netjes, maar door afbreken aan te zetten worden in ieder geval de lelijkste lege plekken voorkomen. Op de afbeelding is de tekst rechts minder lelijk verdeeld dan de tekst links.

main

Alle <main>'s. Dat is er maar eentje. Binnen <main> staat de belangrijkste inhoud van de pagina. Dat is hier voornamelijk opvultekst, maar normaal genomen staat daar – hopelijk – wel iets interessants.

display: block;

Oudere browsers kennen <main> niet. Onbekende elementen worden standaard als inline-element weergegeven. Daarom wordt hier expliciet gezegd dat dit een blok-element is.

max-width: 700px;

Maximumbreedte.

Het zal niet vaak voorkomen, maar in browservensters die breder dan 763 px én lager dan 543 px zijn, kan de in <main> staande tekst heel erg breed worden. Waardoor de tekst heel lastig te lezen wordt. Daarom wordt de maximale breedte beperkt tot 700 px.

(Dit geldt ook voor de tekst rechts van de thumbnails: ook die kan heel breed worden. Maar omdat daar maar weinig tekst staat, en omdat het om vensters met een toch tamelijk exotische maat gaat, heb ik daar geen maximumbreedte opgegeven. Als je dat wel wilt doen, kun je bij li een maximumbreedte opgeven. Je moet dan hier bij <main> nog clear: both; toevoegen, omdat anders de tekst uit <main> rechts in de lege ruimte naast de <li>'s komt te staan.)

margin: 0 auto;

Omdat voor onder en links geen waarde is opgegeven, krijgen die automatisch dezelfde waarde als boven en rechts. Hier staat dus eigenlijk 0 auto 0 auto in de volgorde boven – rechts – onder – links. Boven en onder geen marge. Rechts en links auto, wat hier hetzelfde betekent als evenveel. Ongeacht de breedte van het venster van de browser staat <main>, en dus de tekst daarin, altijd horizontaal gecentreerd.

Deze manier van centreren van een blok-element werkt alleen, als het te centreren blok-element een breedte heeft gekregen. Dat is hier het geval, want ook de gelijk hierboven opgegeven maximumbreedte geldt als breedte. (Alleen zie je natuurlijk pas iets van dat centreren in vensters breder dan 700 px.)

padding: 5px;

Aan alle kanten wat ruimte tussen tekst in en buitenkant van <main>.

p

Alle <p>'s. Alle tekst staat in een <p>.

text-indent: 1em;

Eerste regel van elke <p> 1 em laten inspringen. Door als eenheid em te nemen, verandert de breedte van de inspringing mee met de lettergrootte.

margin: 0.25em 0 0;

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

Van zichzelf heeft een <p> een marge aan boven- en onderkant. De marge aan de onderkant wordt hier weggehaald. De marge aan de bovenkant wordt 0.25 em. Door als eenheid em te nemen, verandert de grootte van de marge mee met de lettergrootte.

css voor vensters minimaal 763 px breed en minimaal 543 px hoog

@media screen and (min-width: 763px) and (min-height: 543px)

De css die hier tot nu toe staat, geldt voor alle browservensters.

De css die binnen deze media query staat, geldt alleen voor vensters die minimaal 763 px breed én minimaal 543 px hoog zijn. In deze vensters zijn de thumbnails groter. Verder is de toelichtende tekst bij de thumbnails verborgen. Deze wordt pas zichtbaar, als een pop-up wordt geopend. In die pop-up zit ook een grotere versie van de thumbnail.

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

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

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

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

(min-height: 543px): het venster moet minimaal 543 px hoog zijn. Is het venster lager, dan wordt de css die binnen deze media-regel staat genegeerd.

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

@media screen and (min-width: 763px) and (min-height: 543px) { 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 }.

body

Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

body {background: #eee; color: black; font-family: Arial, Helvetica, sans-serif; margin: 0; padding: 0;}

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

background: #ff9;

Voor kleinere browservensters is eerder een lichtgrijze achtergrondkleur opgegeven, omdat die achtergrondkleur achter de tekst staat. Maar de standaardachtergrondkleur van de voorbeelden op de site is eigenlijk beige. Hier wordt de kleur veranderd naar de standaardkleur. Dat kan hier, omdat er in deze grotere vensters geen tekst op deze achtergrond staat.

De voorgrondkleur, die ook de kleur van de tekst bepaalt, hoeft niet opnieuw opgegeven te worden. Normaal genomen is het goed altijd een voorgrondkleur op te geven, als je de achtergrondkleur verandert. Sommige gebruikers passen kleuren aan, omdat ze bijvoorbeeld meer contrast nodig hebben of kleurenblind zijn. Als je dan, zoals hier, de achtergrondkleur verandert in beige en de gebruiker heeft toevallig als voorgrondkleur ook beige of iets wat daarop lijkt, heb je onleesbare tekst.

In dit geval hoeft de voorgrondkleur niet opgegeven te worden, want dat is al eerder bij body gebeurd.

font-size: 110%;

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

Als eenheid wordt de relatieve eenheid % gebruikt, omdat bij gebruik van een absolute eenheid zoals px niet alle browsers de lettergrootte kunnen veranderen. Zoomen kan wel altijd, ongeacht welke eenheid voor de lettergrootte wordt gebruikt.

h1

Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

h1 {background: #eee; color: black; max-width: 700px; overflow: auto; font-size: 1em; line-height: 30px; text-align: center; margin: 0 auto;}

Alle <h1>'s. Dat is er maar eentje: de belangrijkste kop op de pagina.

Op de site staat boven de pagina's met menu's een menubalk. Deze menubalk blijft altijd bovenaan het browservenster staan, ook bij scrollen. Die balk ontbreekt in dit voorbeeld. De <h1> vervult hier ongeveer de zelfde functie. Bij scrollen blijft de <h1> net als de menubalk bovenaan het venster staan, doordat de eronder zittende <main> absoluut is gepositioneerd.

width: calc(100% - 402px);

De <h1> wordt horizontaal gecentreerd en moet precies boven de <main> met de tekst komen te staan, zodat ze netjes op elkaar aansluiten. Voor dat horizontaal centreren moet de <h1> een breedte hebben. (Logisch: als iets geen breedte heeft, kun je het niet in het midden zetten.)

Links en rechts van de <main> met de tekst moet een ruimte van 201 px overblijven voor de thumbnails (inclusief wat marge en dergelijke). Daarom moet deze ruimte ook openblijven bij de <h1>, zodat deze niet breder wordt dan de <main>.

Om te beginnen wordt een breedte in procenten genomen: 100%. Een breedte in procenten is altijd ten opzichte van de ouder van het element. Dat is hier <body>, een blok-element. Een blok-element krijgt normaal genomen automatisch dezelfde breedte als z'n ouder. De ouder van <body> is <html>, ook een blok-element. Omdat er geen hoger element is, wordt <html> even breed als het venster van de browser. Daardoor worden ook <body> en de <h1> even breed als het venster.

width: calc(100%); is weinig interessant, want dan kun je ook gewoon width: 100%; gebruiken. Maar dan komt het handige van calc(): je kunt er px van aftrekken. Het gebruik van procenten en pixels in dezelfde berekening is geen enkel probleem.

Om de lege ruimte links en rechts van elk 201 px te krijgen, wordt van die 100% (de breedte van het browservenster) 402 px afgetrokken. Dat kan met calc(100% – 402px). Ongeacht hoe breed het venster is. Bij een vensterbreedte van 1500 px is de <h1> 1500 – 402 = 1098 px breed, en bij een vensterbreedte van 1000 px is de <h1> 1000 – 402 = 598 px breed.

(UC browser op Android en sommige versies van Android browser kennen calc() niet. In die browsers vult de achtergrondkleur van de <h1> de volle breedte van het browservenster tot een maximum van 870 px. Dat maximum komt door de gelijk hieronder opgegeven maximumbreedte voor de <h1>, die wel gewoon werkt in deze browsers.)

max-width: 870px;

Maximale breedte. Om te lange en daardoor slecht leesbare zinnen te voorkomen in brede browservensters, wordt de breedte van <main> beperkt. Dus moet ook de breedte van de <h1> worden beperkt, zodat deze niet breder wordt dan <main>.

height: 40px;

Hoogte.

overflow: auto;

Als de letters sterk vergroot worden, verdwijnt het onderste deel van de <h1> onder de <main>. Nu verschijnt een scrollbalk(je), zodat de <h1> in ieder geval is te lezen.

Normaal genomen zou je de hoogte van de <h1> gewoon laten groeien. Maar dat zou ook betekenen dat de plaatsing van tekst, thumbs, en dergelijke moet worden aangepast. Die plaatsing is al tamelijk ingewikkeld. Daarom is er in dit geval voor gekozen de <h1> als het ware in z'n eigen hok te houden, zodat de plaatsing van de rest van de pagina ook bij een grote letter niet wordt verstoord. Overigens wordt de <h1> pas slecht leesbaar bij een sterkere lettervergroting dan 170%.

line-height: 40px;

Tekst wordt automatisch halverwege de regelhoogte gezet. Door de regelhoogte even hoog te maken als de hoogte, staat de tekst niet zo dicht aan de bovenkant van het venster van de browser.

margin: 0 auto;

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

Boven en onder geen marge. Links en rechts auto, wat hier hetzelfde betekent als evenveel. Oftewel: de <h1> staat altijd horizontaal gecentreerd, ongeacht de breedte van het venster van de browser.

Het op deze manier horizontaal uitlijnen van een blok-element kan alleen, als dat blok-element een breedte heeft.

De <main> wordt op een iets andere manier horizontaal gecentreerd, maar het resultaat is hetzelfde. Omdat de <h1> en de <main> beide horizontaal worden gecentreerd, sluiten ze altijd netjes op elkaar aan, ongeacht de breedte van het browservenster.

border: black solid;

Zwart randje, Hier gelijk onder wordt de breedte opgegeven.

border-width: 0 1px;

Kleur en stijl zijn gelijk hierboven opgegeven.

Omdat voor onder en links geen waarde is opgegeven, krijgen die automatisch dezelfde waarde als boven en rechts. Hier staat dus eigenlijk 0 1px 0 1px in de volgorde boven – rechts – onder – links. Alleen links en rechts een border.

Door kleur en stijl apart van de breedte op te geven, spaar je een klein beetje css uit.

.blok

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

li {background: #eee; color: black; box-sizing: border-box; width: 100%; float: left; margin-top: -1px; border: black solid 1px; padding: 4px 4px 10px; position: relative;}

De elementen met class="blok". Dit zijn de <li>'s, waarbinnen de thumbnails, pop-ups, en dergelijke staan. Elk in een eigen <li>.

width: 180px;

Eerder is een breedte van 100% opgegeven. Hierdoor zouden de <li>'s de volle breedte van het browservenster beslaan. Dat is precies de bedoeling in smallere vensters, maar niet hier. 180 px is de breedte van de thumbnails, breder hoeven de <li>'s niet te zijn.

height: 161px;

Hoogte.

Strikt genomen is dit niet nodig, maar het wordt op de site gebruikt om kleine verschillen door borders en dergelijke op te heffen. Je zou het hier weg kunnen laten, maar dan moet je op 'n aantal plaatsen de positie 1 px veranderen. Wat weer 'n heel gepuzzel is, dus heb ik het gewoon zo van de site overgenomen.

border: none;

Eerder opgegeven border verwijderen.

padding: 0;

Eerder opgegeven padding verwijderen.

position: absolute;

Om de <li>'s en de daarin zittende thumbnails en dergelijke op de juiste plaats neer te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder, die zelf een positie heeft. Als er geen voorouder met een positie is, zoals hier het geval is, wordt gepositioneerd ten opzichte van het venster van de browser.

left: 9px;

9 px naar links neerzetten.

.focus-open

De elementen met class="focus-open". Dit zijn <span>'s speciaal voor gebruikers van de Tab-toets, zodat de pop-ups ook bij gebruik van de Tab-toets openen. Over de werking is meer te vinden bij Tabindex.

position: absolute;

Om de <span> op de juiste plaats neer te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat zijn hier de <li>'s, waar de <span> in staat.

left: -20000px;

Ver links buiten het scherm plaatsen. Hierdoor wordt de lay-out niet verstoord, terwijl het voor de Tab-toets niets uitmaakt dat de <span> buiten het scherm staat. Hiermee worden ook eventuele problemen op touchscreens voorkomen: wat je niet aan kunt raken, kan bij aanraking ook geen problemen veroorzaken. (Hmmm, ergens klinkt die laatste zin ietwat eigenaardig. Maar het klopt wel, ondanks de wat vreemde zinsbouw: probeer je touchscreen maar 'ns aan te raken, als je zeven meter links ervan staat. En niet valsspelen door 'n polsstok te gebruiken of zo, gewoon met je handen.)

img

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

img {box-shadow: 4px 6px 4px 1px black; width: 120px; max-width: 100%; height: auto; float: left; margin: 3px 10px 6px 3px; border: black solid 1px; border-radius: 5px;}

Alle afbeeldingen. Dat zijn hier de acht thumbnails.

box-shadow: none;

De eerder opgegeven schaduw verwijderen.

width: auto;

Eerder zijn de <img>'s versmald tot 120 px. Hier krijgen ze de echte grootte weer terug. (In de html staat bij <img> een breedte van 180 px. Eigenlijk heeft dat in dit geval niet zoveel nut, omdat een breedte in de css altijd 'wint' van een breedte in de html. Omdat de thumbnails 180 px breed zijn, krijgen ze hoe dan ook een breedte van 180 px. Waarom ik het dan toch laat staan? Omdat het in het algemeen een goede gewoonte is om wel een breedte en hoogte aan te geven bij een <img>.)

margin: 0;

Eerder opgegeven marge verwijderen.

.open

Alle elementen met class="open".

Binnen elke <li> staat een <input type="radio"> om de pop-up te kunnen openen. De <input>'s zelf zijn verborgen. Het openen gaat via de bij de <input> horende <label> Dit zijn die <label>'s. Binnen deze <label>'s zit de pop-up met bijbehorend vraagteken en sluitkruisje.

text-align: center;

Tekst horizontaal centreren.

Dit zorgt voor het horizontaal centreren van het vraagteken en van de tekst in de pop-up.

position: absolute;

Om de <label>, en dus alles daarin, 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>, waar de <label> in staat.

left: 1px; Afbeelding 17: vraagteken staat niet op, maar naast de thumbnail

Binnen de <li> zit een <img>: de thumbnail. Daarop volgt in de html een <input>, maar die is verborgen. En daarop volgt deze <label>, met daarin als eerste onderdeel een vraagteken. <img> en <label> zijn inline-elementen, dus worden ze achter elkaar op dezelfde regel gezet. Op de afbeelding is te zien dat het vraagteken hierdoor niet op, maar rechts van de thumb komt te staan. Met deze regel wordt het vraagteken links bovenop de thumb gezet.

(Terzijde: de pagina is nog niet bezocht, dus het vinkje naast het vraagteken hoort er niet te zijn. Op deze afbeelding is te zien dat dat vinkje er gewoon is. Het heeft echter vrijwel dezelfde kleur als de achtergrondkleur van het vraagteken, waardoor het vrijwel onzichtbaar is. Als de pagina is bezocht, wordt de kleur van het vinkje zwart en zie je het duidelijk op de witte achtergrond van het vraagteken.)

.vraagteken

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

input, .vraagteken, .sluit{display: none;}

Alle elementen met class="vraagteken". Dit zijn de <span>', waarbinnen het vraagteken zit. Met onderstaande css wordt het vraagteken sterk vergroot en in een wit vierkantje gezet. Omdat deze <span>'s binnen een <label> zitten, selecteert aanraken van of klikken op het vraagteken de bij de <label> horende radioknop. Waardoor de bijbehorende pop-up wordt geopend.

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

Vaak 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 enigszins doorzichtig: 0.75. Hierdoor zie je de thumbs nog enigszins door de achtergrond heen, maar zijn de donkergrijze vraagtekens en, als de achterliggende pagina is bezocht, zwarte vinkjes toch goed zichtbaar, ook op donkere thumbs.

color: #666;

Voorgrondkleur, dat is onder andere de tekstkleur en daarmee de kleur van het vraagteken, donkergrijs.

display: block;

Eerder zijn deze <span>'s voor kleinere browservensters verborgen met display: none;. Nu worden ze weer zichtbaar gemaakt.

Een <span> is een inline-element. Daardoor kun je eigenschappen als breedte en hoogte niet gebruiken. Maar door het zichtbaar te maken als blok-element, is dit soort eigenschappen toch te gebruiken.

width: 48px;

Breedte. De hoogte wordt iets hieronder bij line-height geregeld.

font-size: 2.4em;

Vraagteken fors vergroten.

Als eenheid wordt de relatieve eenheid em gebruikt, omdat bij gebruik van een absolute eenheid zoals px niet alle browsers de lettergrootte kunnen veranderen. Zoomen kan wel altijd, ongeacht welke eenheid voor de lettergrootte wordt gebruikt.

line-height: 50px;

Regelhoogte. Tekst wordt automatisch halverwege de regelhoogte neergezet. De combinatie van hoogte, regelhoogte, padding, en dergelijke zet het vraagteken ongeveer halverwege de hoogte van het vierkantje neer.

Omdat geen aparte hoogte is opgegeven, is dit gelijk de hoogte van de <span>, en daarmee van het witte blokje. Daardoor staat het vraagteken verticaal in het midden.

De hoogte is iets meer dan de breedte, maar door de borders, schaduw, en dergelijke levert dit voor het oog toch een vierkantje op.

border-radius: 5px 0 5px;

Ronde hoeken.

Omdat voor linksonder geen waarde is opgegeven, krijgt linksonder automatisch dezelfde waarde als rechtsboven. Hier staat dus eigenlijk 5px 0 5px 0 in de volgorde linksboven – rechtsboven – rechtsonder – linksonder.

Linksboven en rechtsonder een kleine ronding. De ronding is even groot als de ronding die eerder bij img aan de thumbnail is gegeven, zodat het witte vierkantje daarop aansluit.

position: relative;

Hier iets onder wordt een z-index gebruikt om het vraagteken altijd zichtbaar te laten zijn. Waarom deze relatieve positie nodig is, staat hieronder bij z-index.

top: 1px;

Hier gelijk boven is een relatieve positie aan de <span> gegeven. Hierdoor komt het witte blokje boven de border aan de bovenkant te staan. Door de <span> 1 px naar beneden te verplaatsen, wordt dit opgelost.

Het hele verhaal over hoe dit komt, staat gelijk hieronder bij z-index.

z-index: 40;

Zorgen dat het blokje met het vraagteken gevoelig is voor aanraken, klikken en hoveren.

Als meerdere elementen op dezelfde plaats op het scherm worden gezet, zijn er heel strikte regels, welk element bovenaan komt te staan en dus zichtbaar is. Eén van die regels is dat elementen die zijn gepositioneerd, boven elementen komen te staan die niet zijn gepositioneerd.

Hieronder bij .blok a wordt van de link naar de achter de knop zittende pagina een rechthoek gemaakt, die even groot is als de thumbnail. Die rechthoek wordt over de thumbnail gezet, zodat de hele oppervlakte van de thumbnail als link werkt. Om dat te kunnen doen, wordt onder andere een relatieve positie aan die <a> gegeven.

De <span> met het vraagteken op het witte blokje heeft geen positie. Deze komt daardoor ónder de <a> te staan. Daar merk je niets van, want de <a> is doorzichtig: je ziet het witte blokje met het vraagteken gewoon, door de <a> heen. Alleen werken aanraken, klikken en hoveren niet meer, omdat het blokje is afgedekt door de <a>. En omdat die <a> een link is naar de achterliggende pagina, wordt die pagina ook geopend bij aanraken of aanklikken van het vraagteken.

Dat is niet de bedoeling.

Door nu aan deze <span> ook een positie te geven, wordt hij wat dit betreft gelijkwaardig aan de <a>. Helaas lost dat nog niets op, want de <a> staat ook lager in de html. Omdat de <span> en de <a> nu gelijkwaardig zijn, wordt die verrekte <a> nog steeds over het vraagteken heen gezet.

Daarom wordt een z-index van 40 aan de <span> gegeven. Omdat de <a> geen z-index heeft (althans: geen andere dan de standaardwaarde voor een gepositioneerd element), wint nu eindelijk de <span> met het vraagteken. De <a> wordt nu onder de <span> met het witte vierkantje gezet, waardoor de <span> nu gevoelig is voor aanraken, klikken en hoveren.

Een z-index werkt trouwens alleen maar in bepaalde omstandigheden. Eén van die omstandigheden is een relatieve positie. Omdat de <span> iets hierboven relatief is gepositioneerd, is dat al geregeld.

Maar nu is er weer 'n klein ander probleempje.

Omdat de <span> nu hoger staat, staat deze ook over de border aan de bovenkant heen. Dat is echter snel opgelost. De <span> is al relatief gepositioneerd, en door hem met top: 1px; iets omlaag te zetten, wordt de border weer zichtbaar.

(Je kunt dit ook op andere manieren dan de hierboven staande oplossen, bijvoorbeeld door iets hierboven een z-index aan .open te geven. Dat heeft weer iets andere bijwerkingen. Min of meer toevallig is voor deze oplossing gekozen. Maar er zijn ook andere oplossingen mogelijk.)

.pop-up

De elementen met class="pop-up". De <span>'s met de eigenlijke pop-up. De afbeelding in de pop-up is een achtergrond-afbeelding in deze <span>. Verder staat binnen deze <span> nog een <span> met de tekst die boven de afbeelding in de pop-up verschijnt.

background-position: 0 132px;

Positie van de achtergrond-afbeelding. Gewoon links in de <span> zetten, maar aan de bovenkant 132 px vrijlaten voor de tekst die boven de achtergrond-afbeelding komt te staan.

De css voor de acht achtergrond-afbeeldingen staat bij @media screen and (min-width: 763px) and (min-height: 543px). In dezelfde stylesheet als de rest van de css. Maar op de site, waar het om veel meer pagina's gaat, staat die css voor de achtergrond-afbeeldingen in de <head> van de betreffende pagina. Die css is voor elke pagina anders, dus het heeft geen nut die in een externe stylesheet te zetten.

Maar de regel hierboven kan op de site wel in een externe stylesheet, omdat de positie van de achtergrond-afbeelding overal hetzelfde is. Nu is één regel voldoende voor alle thumbnails op de site.

In dit voorbeeld, waar het maar om één pagina gaat, had deze regel dus net zo goed verderop bij de css voor de achtergrond-afbeeldingen gekund.

height: 464px;

Hoogte van de <span>. De achtergrond-afbeeldingen zijn 332 px hoog, dus boven de afbeelding is 132 px ruimte voor tekst.

Een achtergrond-afbeelding heeft van zichzelf geen grootte. Hij vult alleen de achtergrond van het element, waar hij in wordt gezet. Daarom moet dit element, hier de <span>, een hoogte en breedte krijgen.

De hoogte is hier geregeld, de breedte wordt bij .pop-up-tekst geregeld. In span.pop-up-tekst staat de tekst, die boven de afbeelding in de pop-up komt te staan. Die <span> krijgt een breedte van 540 px. Samen met wat padding levert dit de breedte van de achtergrond-afbeeldingen op. En omdat .pop-up-tekst binnen span.pop-up staat, krijgt .pop-up dezelfde breedte.

(Feitelijk is die breedte 4 px minder dan de breedte van de achtergrond-afbeelding. Bij zoomen kan anders een foeilelijk kiertje rechts van de afbeelding verschijnen.)

margin-left: -20000px;

De <span>, en daarmee de pop-up, moet alleen worden getoond, als het vraagteken wordt aangeraakt of ‑geklikt, als daarover wordt gehoverd of als de Tab-toets focus geeft aan span.focus-open. Normaal genomen zou je de <span> verbergen met iets als display: none;. Dat kan hier echter niet, omdat er tekst in de <span> staat. Schermlezers negeren elementen die zijn verborgen met display: none;, dus schermlezers zouden de tekst boven de afbeelding in de pop-up dan niet voorlezen.

Daarom wordt de <span> niet verborgen, maar links buiten het scherm geparkeerd. Als de pop-up getoond moet worden, hoeft de <span> dan alleen maar binnen het venster van de browser te worden gezet.

Meestal gebruik je left: -20000px; om iets buiten het scherm te plaatsen. Hier gebruik ik liever een negatieve marge. Dat werkt ook prima en voorkomt ernstige overspannenheid. Ik werd namelijk een beetje gek van alle verschillende waarden bij left bij verschillende pop-ups in vensters van verschillende groottes. Door geen left, maar margin-left te gebruiken ben ik in ieder geval één van die ellendepukkels, pardon left's kwijt.

Het zichtbaar maken wordt nu volledig door de marge geregeld, de precieze plaats volledig door left.

border: #fc3 ridge 13px;

Randje rondom de <span>.

position: absolute;

Om de <span> en dus de pop-up 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 label.open.

Een <span> is een inline-element. Daardoor kunnen eigenschappen als hoogte niet worden gebruikt. Door de <span> absoluut te positioneren verandert hij in een soort blok-element, waardoor dit soort eigenschappen wel gebruikt kunnen worden.

top: -40px;

Door de <span>'s met de pop-ups 40 px naar boven te zetten, staat de bovenkant van de pop-ups precies tegen de bovenkant van het browservenster. Voor de pop-ups die bij de knoppen in de tweede, derde en vierde regel horen, wordt iets hieronder top aangepast.

left: 181px;

De linkerkant van de pop-ups precies tegen de rechterkant van de thumbnails zetten. Voor de pop-ups bij de knoppen rechts van de tekst, wordt dit iets hieronder aangepast.

z-index: 60;

De <main> met de tekst komt in de html na de header met de knoppen, pop-ups, enz. Hierdoor komen de pop-ups onder de tekst te staan, waardoor je vrijwel alleen nog (delen van) de border ziet. Nou is die border ongelooflijk artistiek verantwoord en zo, maar het zou toch aardig zijn, als ook de tekst en de afbeelding in de pop-up zichtbaar waren.

Door de z-index te verhogen, komen de pop-ups boven de <main> met de tekst te staan, ook al staat deze lager in de html.

Een z-index werkt alleen in sommige omstandigheden. Eén van die omstandigheden is een absolute positie. Die heeft de <span> iets hierboven gekregen, dus dat is geregeld.

Er zijn meerdere z-indexen voor verschillende elementen: 40, 50 en 60. Deze sluiten niet op elkaar aan. Hierdoor kun je later makkelijk elementen met een z-index toevoegen, zonder dat je bestaande z-indexen moet gaan veranderen.

.pop-up-tekst

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

.pop-up-tekst {-moz-hyphens: auto; -ms-hyphens: auto; -webkit-hyphens: auto; hyphens: auto;}

De elementen met class="pop-up-tekst". Dit zijn de <span>'s, waarbinnen de tekst boven de afbeelding in de pop-up staat.

background: white;

Witte achtergrond.

color: black;

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

Hoewel dit de standaardkleur is, wordt deze toch specifiek opgegeven. Hierboven is een achtergrondkleur opgegeven. Sommige mensen hebben zelf de voorgrond- en/of achtergrondkleur veranderd, bijvoorbeeld omdat ze slecht kleuren kunnen onderscheiden. Als nu de achtergrondkleur wordt veranderd, maar niet de voorgrondkleur, loop je het risico dat tekstkleur en achtergrondkleur te veel op elkaar gaan lijken.

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

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

display: block;

Een <span> is een inline-element. Hierdoor zijn eigenschappen als breedte en hoogte niet te gebruiken. Door er een blok-element van te maken, kan dit soort eigenschappen wel worden gebruikt.

width: 540px;

Breedte. Deze <span>'s staan binnen span.pop-up, de <span> waar de hele pop-up in zit. Aan die <span> is geen breedte gegeven. Daardoor bepaalt deze breedte ook de breedte van span.pop-up.

height: 125px;

Met deze hoogte wordt precies het lege deel boven de achtergrond-afbeelding gevuld. Dat lege deel is ontstaan, doordat bij .pop-up background-position: 0 132px; is opgegeven. Dat de getallen wat verschillen (125 px en 132 px) komt door allerlei dingen als borders en zo.

overflow: auto;

Als er veel tekst in de <span> staat, past deze niet boven de afbeelding in de pop-up. In dat geval verschijnt een verticale scrollbalk. Bij de zesde pop-up is dit het geval. Maar dat is eigenlijk vooral gedaan om te laten zien dat dit niet echt heel handig is.

Gebruikers van de muis moeten eerst klikken op het vraagteken, zodat de pop-up open blijft. Pas daarna kunnen ze de tekst scrollen. Voor gebruikers van de Tab-toets is er geen enkele mogelijkheid om de tekst te scrollen: die moeten eerst in de tekst klikken, voordat pijltjes of scrollwieltje werken. En als je de Tab-toets gebruikt, omdat je geen muis kunt bedienen, lukt dat dus niet.

Het is dus beter om niet meer tekst boven de afbeelding te zetten, dan dat er zonder scrollen in kan.

(Bij een grotere lettergrootte bestaat het probleem dan trouwens nog steeds. Als iemand slecht ziet en de tekst daarom heeft vergroot én de muis niet kan gebruiken, is dit onoplosbaar. Maar bij gewoon inzoomen (vergroten) speelt dit probleem niet, dus dit zal niet vaak voorkomen.)

font-size: 0.8em;

Iets kleinere letter, zodat er iets meer tekst boven de afbeelding past.

Als eenheid wordt de relatieve eenheid em gebruikt, omdat bij gebruik van een absolute eenheid zoals px niet alle browsers de lettergrootte kunnen veranderen. Zoomen kan wel altijd, ongeacht welke eenheid voor de lettergrootte wordt gebruikt.

-moz-hyphens: manual; -ms-hyphens: manual; -webkit-hyphens: manual; hyphens: manual;

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

Omdat er in smalle browservensters weinig ruimte is rechts van de thumbnails, is eerder automatisch afbreken aangezet. In bredere vensters ziet dat er niet mooi uit, daarom wordt het weer teruggezet naar de standaardwaarde.

(Die standaardwaarde is niet none, zoals je makkelijk kunt denken. Bij none wordt helemaal niet afgebroken, ook niet als bijvoorbeeld &shy; in een woord is gebruikt. De standaardwaarde is manual: nu wordt niet afgebroken, behalve als in een woord iets als &shy; staat.

border-bottom: black solid 1px;

Randje aan de onderkant.

padding: 3px;

Kleine afstand tussen tekst in en buitenkant van de <span>.

.blok a

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

a {width: 120px; height: 108px; position: absolute; top: 8px; left: 8px;}

De <a>'s binnen de elementen met class="blok". De links naar de achter de knoppen zittende pagina's. Binnen elke li.blok zit zo'n link.

-webkit-animation: bugfix infinite 1s;

In oudere versies van Android browser zit een bug, waardoor de het sluitkruisje soms niet wordt getoond. Met behulp van deze regel wordt het sluitkruisje toch getoond. Meer hierover bij @-webkit-keyframes bugfix.

box-shadow: black 4px 3px 4px 1px;

Rechts en onder wat schaduw aan de <a> geven. Omdat de <a> even groot is als de thumbnail, lijkt de schaduw rondom de thumbnail te staan.

Een uitgebreide uitleg over box-shadow is te vinden bij box-shadow: 4px 6px 4px 1px black;. Alleen zijn de waarden hier anders: 4 px naar rechts, 3 px omlaag, over 4 px vervagen en 1 px breed. Verder moet hier een kleur worden opgegeven, anders krijgt de schaduw de standaardkleur van een <a>.

display: block;

Een <a> is een inline-element. Daardoor kunnen eigenschappen als breedte en hoogte niet worden gebruikt. Door er een blok-element van te maken, kan dit soort eigenschappen wel worden gebruikt.

width: 180px; height: 161px;

Breedte en hoogte. Dit is precies even groot als de thumbnails. Door de <a> bovenop de thumbnails te zetten, gaat de hele thumbnail als link werken. (In werkelijkheid is het natuurlijk niet de thumbnail die als link werkt, maar de <a>. Maar het lijkt wel zo, en daar gaat het om.)

text-align: center;

In de <a> zit een <span> met de korte naam van de achterliggende pagina. Deze wordt op verschillende momenten op verschillende plaatsen getoond. Hier wordt deze naam horizontaal gecentreerd.

margin: 0 auto;

Omdat voor onder en links geen waarde is ingevuld, krijgen die automatisch dezelfde waarde als boven en rechts. Hier staat dus eigenlijk 0 auto 0 auto in de volgorde boven – rechts – onder – links. Boven en onder geen marge. Links en rechts auto, wat hier hetzelfde betekent als evenveel. De <a>'s staan nu altijd in horizontaal gecentreerd in hun ouder, de <li> met de thumb, pop-up, enz.

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

border: black solid 1px;

Zwart randje.

border-radius: 5px;

Ronde hoeken.

position: relative;

Eerder zijn alle <a>'s absoluut gepositioneerd. Dat is hier niet meer nodig. In het algemeen is het beter een absolute positie te vermijden, als die niet nodig is, omdat het allerlei ongewenste bijwerkingen kan hebben.

Maar binnen de <a> staat een <span> met de korte naam van de pagina. En die moet gepositioneerd worden ten opzichte van de <a>. Dat kan alleen als de <a> zelf een positie heeft. Daarom wordt de absolute positie hier vervangen door een relatieve.

(Feitelijk moet de <span> met de naam worden gepositioneerd ten opzichte van de thumbnail, maar omdat de <a> precies over de thumbnail heen staat, is het eindresultaat hetzelfde: de naam lijkt gepositioneerd ten opzichte van de thumb.)

top: 0; left: 0;

Eerder is voor beide een waarde van 8 px opgegeven. Om te voorkomen dat de <a>'s 8 px naar beneden en naar rechts worden verplaatst, wordt dat hier weer ongedaan gemaakt.

.naam

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

.naam {opacity: 0;}

Alle elementen met class="naam". Binnen elke <a> zit een <span>, waarbinnen de korte naam van de achterliggende pagina zit.

color: transparent; opacity: 1;

Deze twee eigenschappen hebben in dit geval met elkaar te maken, dus is het makkelijker om ze samen te beschrijven.

Eerder is de <span> met de naam met opacity: 0; doorzichtig gemaakt. (display: none; of visibility: hidden; waren onbruikbaar, omdat schermlezers dan de naam volledig zouden negeren.)

In bredere browservensters moet de naam op verschillende momenten in verschillende kleuren worden getoond. Daarom wordt de naam hier weer zichtbaar gemaakt met opacity: 1;. En vervolgens weer onzichtbaar gemaakt met

color: transparent;.

Het voordeel van deze ogenschijnlijk zinloze werkverschaffing: nu hoeft, als de naam zichtbaar moet worden gemaakt, alleen de kleur te worden veranderd. En niet de kleur én de doorzichtigheid.

display: block;

Van zichzelf is een <span> een inline-element. Daardoor kunnen eigenschappen als breedte en hoogte niet worden gebruikt. Door er een blok-element van te maken, kan dit soort eigenschappen toch worden gebruikt.

width: 180px;

Breedte. Dit is dezelfde breedte als die van de thumbnails, waar de naam soms boven wordt gezet. Op sommige plaatsen is een andere breedte nodig. Voor die plaatsen wordt de breedte later aangepast.

height: 39px;

Hoogte.

font-size: 25px;

Tamelijk grote letter.

Meestal wordt als eenheid voor lettergrootte een relatieve eenheid als em gebruikt, omdat bij gebruik van een absolute eenheid zoals px niet alle browsers de lettergrootte kunnen veranderen. (Zoomen kan wel altijd, ongeacht welke eenheid voor de lettergrootte wordt gebruikt.)

Hier is het een voordeel, als een browser dat niet kan. Dat voorkomt namelijk dat de naam te groot wordt. Dat is verder geen ernstig probleem, maar in sommige browsers wordt dat nu dus voorkomen.

line-height: 34px;

Regelhoogte. Tekst wordt normaal genomen automatisch halverwege de regelhoogte neergezet.

Iets hierboven is een hoogte van 39 px opgegeven. Dan zou je verwachten dat ook de regelhoogte 39 px is, zodat de tekst halverwege de hoogte komt te staan. In dit geval is het mooier de tekst iets hoger neer te zetten, omdat de tekst is onderstreept. Voor het oog staat de tekst nu verticaal gecentreerd, terwijl die bij een regelhoogte van 39 px voor het oog iets te laag staat.

text-decoration: underline;

Onderstrepen.

margin-top: 50px;

50 px marge aan de bovenkant.

Bij gebruik van de Tab-toets wordt bij de eerste tab de pop-up geopend. Bij een tweede tab wordt de naam van de achterliggende pagina op de thumbnail gezet (en nog wat dingen, die hier verder niet van belang zijn). Met deze marge staat de naam ongeveer halverwege de thumbnail. Bij hoveren en dergelijke verschijnt de naam ook. Daarvoor wordt later de marge aan de bovenkant aangepast.

Je zou dit mogelijk ook met top kunnen doen, maar dit is min of meer toevallig zo gegroeid. Als dit veranderd zou worden, vereist dat weer het nodige testwerk, dus laat ik het zo.

position: absolute;

Met behulp van ::after wordt bij span.naam hier gelijk onder een pseudo-element gemaakt. Binnen dit pseudo-element staat het vinkje dat aangeeft dat de pagina al is bezocht.

Dit pseudo-element wordt absoluut gepositioneerd ten opzichte van span.naam. Dat kan alleen, als span.naam zelf een positie heeft, wat hier wordt geregeld. Later wordt span.naam zelf ook nog verplaatst met behulp van top en dergelijke, en dat is hier gelijk ook mogelijk gemaakt.

z-index: 50;

Het vinkje, waar gelijk hierboven bij position over wordt geschreven, verdwijnt onder de witte achtergrond van span.vraagteken. Om dat te voorkomen, krijgt deze <span> een hogere z-index.

Een z-index werkt alleen in sommige omstandigheden. Eén van die omstandigheden is een absolute positie. Die heeft de <span> iets hierboven gekregen, dus dat is ook geregeld.

Er zijn meerdere z-indexen voor verschillende elementen: 40, 50 en 60. Deze sluiten niet op elkaar aan. Hierdoor kun je later makkelijk elementen met een z-index toevoegen, zonder dat je bestaande z-indexen moet gaan veranderen.

.naam::after

Afbeelding 18: pseudo-element met vinkje volledig zichtbaar gemaakt

Binnen elke <a> zit een span met class="naam". Hierbinnen zit de korte naam van de achterliggende pagina. Met behulp van ::after worden bij deze <span>'s pseudo-elementen gemaakt. Deze zorgen voor het verschijnen van de vinkjes naast het vraagteken, als een pagina is bezocht.

Hiernaast staat een sterk vergroot 'vinkje'. De zwarte lijnen vormen het vinkje. In werkelijkheid zijn dit twee borders bij een rechthoek. De achtergrond van het pseudo-element is even rood gemaakt, zodat duidelijker te zien is dat het vinkje echt uit borders bestaat. Die hieronder redelijk ernstig worden mishandeld om ze in de juiste rondingen en zo te meppen.

content: "";

Hoewel er geen tekst of zoiets in het pseudo-element staat, is dit toch nodig. Dat er geen tekst in staat, geef je aan door niets tussen de aanhalingstekens te zetten.

color: #ddd;

Voorgrondkleur. Bij gebrek aan tekst wordt deze kleur hier alleen voor de borders gebruikt.

De vinkjes worden bovenop het witte vierkantje met het vraagteken gezet. Met deze kleur zijn ze vrijwel onzichtbaar. Als de pagina is bezocht, hoeft de kleur alleen maar te worden veranderd naar zwart om de vinkjes zichtbaar te maken.

De witte achtergrond achter het vraagteken is enigszins doorzichtig. Daarom wordt hier geen white gebruikt als kleur, maar heel lichtgrijs. Dit maakt de meeste vinkjes (vrijwel) onzichtbaar ten opzichte van de achtergrond. De vinkjes bij de vierde en achtste thumbnail moeten een iets andere kleur krijgen om (vrijwel) volledig onzichtbaar te zijn. Dat gebeurt iets hieronder.

width: 6px; height: 12px; Afbeelding 19: hoogte en breedte van pseudo-element met vinkje zichtbaar gemaakt

Breedte en hoogte van het pseudo-element. Op de afbeelding is de achtergrond even rood gemaakt, zodat het pseudo-element is te zien. In het uiteindelijke vinkje is de achtergrond weggelaten. Waar het om gaat: het vinkje begint dus echt als een simpele rechthoek.

border: solid;

Stijl van de border. De breedte wordt gelijk hieronder opgegeven.

border-width: 0 2px 2px 0; Afbeelding 20: border van pseudo-element die vinkje wordt

Dit levert rechts en onderaan een gewone border van 2 px breedte op. Op de afbeelding is de achtergrond weer weggelaten, zodat alleen twee rechte lijntjes overblijven.

border-top-right-radius: 3px; border-bottom-left-radius: 5px; Afbeelding 21: border van pseudo-element ronding geven

Ronde hoeken rechtsboven en linksonder. Dit laat het uiteindelijke vinkje iets meer op en vinkje lijken. Het laatste stukje wordt iets hieronder bij transform vormgegeven. (Dat komt hier wat onhandig uit, maar ik hanteer een strikte volgorde van eigenschappen binnen de css. En transform komt in die volgorde een eind onder border-radius.)

pointer-events: none;

Over de volledige thumbnail staat de <a> met de link naar de achterliggende pagina. Daar weer overheen wordt linksboven met behulp van label.open en span.vraagteken een wit vierkantje met vraagteken neergezet. Als je dit vlakje aanraakt of aanklikt, moet de pop-up openen. De link in de <a> werkt niet, omdat deze wordt afgedekt door de <label> met het witte vlakje en het vraagteken.

Naast het vraagteken in het witte vlakje wordt dit pseudo-element met het vinkje gezet. Deze staat bovenop het witte vlakje. Maar dit pseudo-element hoort bij span.naam, en die <span> zit in de <a>, is onderdeel van de link. Als je het vinkje aanraakt of aanklikt, wordt hierdoor niet de pop-up geopend, maar wordt de link gevolgd.

Bij hoveren met de muis valt dat nog mee, omdat het vinkje verdwijnt als je over het witte vierkantje hovert. En je moet over het witte vierkantje heen, voordat je het vinkje bereikt. Maar als je heel snel en heel precies bent, kan het zelfs met de muis: het vinkje blijft staan en werkt als link.

Op een touchscreen is het vervelender, want daar werkt hoveren niet. Als je het vinkje aanraakt, wordt de link gevolgd.

Deze regel schakelt hoveren, aanraken, klikken en dergelijke uit voor dit pseudo-element. Als je het vinkje aanraakt, wordt die aanraking doorgegeven aan het element onder het pseudo-element met het vinkje. En dat is precies de bedoeling, want dat is label.open, die zorgt voor het openen van de pop-up.

position: absolute;

Om het vinkje 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 span.naam, de <span> waar dit pseudo-element bij hoort.

Een met behulp van ::after gemaakt pseudo-element is van zichzelf een inline-element. Daardoor zijn eigenschappen als breedte en hoogte niet te gebruiken. Door het absoluut te positioneren verandert het in een soort blok-element, waardoor dit soort eigenschappen wel is te gebruiken.

top: -50px;

Dit pseudo-element hoort bij span.naam. Bij .naam is die <span> met margin-top: -50px; 50 px omlaag gezet. Waardoor dit pseudo-element met vinkje 50 px te laag komt te staan. Hier wordt het vinkje weer 50 px terug naar boven gezet, waardoor het naast het vraagteken komt te staan.

left: 5px;

Op deze afstand vanaf links staat het vinkje op de goede plaats in de knoppen op de linkerhelft. Bij de knoppen in de rechterhelft moet het vinkje aan de andere kant van het vraagteken komen. Dat wordt iets verderop geregeld.

-ms-transform: rotate(45deg) skew(14deg); -webkit-transform: rotate(45deg) skew(14deg); transform: rotate(45deg) skew(14deg);

Hier staat in feite vier keer hetzelfde: transform: rotate(45deg) skew(14deg);. Waarom dat zo is, staat bij De voorvoegsels -moz-, -ms- en -webkit-.

Afbeelding 22: pseudo-element met vinkje draaien

Dit is de laatste stap in de vorming van het vinkje. De eerste stap staat iets omhoog bij width. (Dat komt hier wat onhandig uit, maar ik hanteer een strikte volgorde van eigenschappen binnen de css. En transform komt in die volgorde een eind onder border-radius.)

Met transform kun je verschillende bewerkingen op een element uitvoeren. In dit geval gaat het om rotate (draaien) en skew (vervormen). Als je bij transform meerdere bewerkingen wilt uitvoeren, zoals hier het geval is, zet je die gewoon achter elkaar.

Met deze combinatie van 45 graden draaien en 14 graden vervormen, lijkt het eindresultaat redelijk op een vinkje. Niet als je het zo sterk vergroot als op de afbeelding hier, maar wel als je het in gewoon formaat ziet.

.sluit

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

input, .vraagteken, .sluit {display: none;}

De elementen met class="sluit". Binnen elk van de acht <li>'s staat onderaan een <label>. Deze toont, als de pop-up door aanraken of klikken is geopend, het sluitkruisje. Door op de <label> met het sluitkruisje te te klikken of dit aan te raken, wordt de bij label.sluit horende radioknop geselecteerd en sluit de pop-up weer.

-webkit-animation: bugfix infinite 1s;

In oudere versies van Android browser zit een bug, waardoor de het sluitkruisje soms niet wordt getoond. Met behulp van deze regel wordt het sluitkruisje toch getoond. Meer hierover bij @-webkit-keyframes bugfix.

background: white;

Witte achtergrond.

color: red;

Voorgrondkleur rood. Dit is ook de letterkleur. Het sluitkruisje is niets anders dan een wat opgeblazen letter 'x'.

display: block;

Eerder is .sluit met display: none; verborgen. Nu wordt het weer zichtbaar gemaakt. Een <label> is van zichzelf een inline-element. Daardoor kunnen eigenschappen als hoogte en breedte niet worden gebruikt. Door het weer te geven als blok-element, kunnen dit soort eigenschappen wel worden gebruikt.

width: 38px; height: 39px; overflow: hidden; font-size: 77px; line-height: 25px;

Deze eigenschappen zorgen gezamenlijk voor een acceptabele weergave in alle browsers. Omdat elke browser zo z'n eigen kleine afwijkingen heeft, moet je de benodigde eigenschappen en waarden gewoon door uitproberen uitvogelen.

width en height: met deze breedte en hoogte komt de 'x' het beste uit.

overflow: hieronder worden een grote lettergrootte opgegeven. Te groot voor de hierboven opgegeven breedte en hoogte. Door overflow op hidden te zetten, wordt alles verborgen wat niet binnen de opgegeven breedte en hoogte past.

font-size: 77 px is een forse lettergrootte. Maar dat is ook de bedoeling.

Meestal wordt als eenheid een relatieve eenheid als em gebruikt, omdat bij gebruik van een absolute eenheid zoals px niet alle browsers de lettergrootte kunnen veranderen. (Zoomen kan wel altijd, ongeacht welke eenheid voor de lettergrootte wordt gebruikt.)

Hier is het een voordeel, als een browser dat niet kan. Dat voorkomt namelijk dat de 'x' te groot wordt. Dat is verder geen ernstig probleem, maar in sommige browsers wordt dat nu dus voorkomen.

line-height: bij een regelhoogte van 25 px staat de 'x' in alle browsers verticaal in het midden van de witte achtergrond.

border: black solid;

Zwart randje. De breedte wordt gelijk hieronder opgegeven.

border-width: 1px 1px 0;

De kleur en stijl zijn gelijk hierboven al opgegeven.

Omdat voor links geen breedte is opgegeven, krijgt die automatisch dezelfde waarde als rechts. Hier staat dus eigenlijk 1px 1px 0 1px in de volgorde boven – rechts – onder – links. Overal een randje, behalve aan de onderkant.

Door kleur en stijl te scheiden van de breedte, wordt wat css uitgespaard. Dit is minder css dan drie aparte regels voor boven, rechts en links.

border-top-left-radius: 5px;

Linksboven ronde hoek.

position: absolute;

Om de <label> met het sluitkruisje 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>, waar label.sluit in staat.

top: -40px;

40 px naar boven verplaatsen.

Als de pop-up is geopend door aanraking of aanklikken, wordt boven de thumbnail de korte naam van de bijbehorende achterliggende pagina getoond. Op deze hoogte komt het sluitkruisje daar precies naast te staan.

Als je geen top op zou geven, komt de <label> op z'n normale plaats te staan: onder de <a> die er in de html gelijk voor zit. Omdat die <a> even groot is als de thumbnail, komt het sluitkruisje dan niet boven, maar helemaal onder de thumbnail te staan.

left: -20000px;

Links buiten het scherm parkeren, zodat het onzichtbaar is. Als dat nodig is wordt het sluitkruisje binnen het scherm geplaatst, waarna het zichtbaar is.

Normaal genomen zou het sluitkruisje worden verborgen met display: none;. Dat wordt hier niet gedaan, omdat het dan niet zichtbaar blijkt te worden in oudere versies van Android browser, dat fantastische wonder der techniek dat bij tijd en wijle bij mij een slecht humeur, leverkolieken en een hoge bloeddruk veroorzaakt.

z-index: 50;

In bepaalde groottes van het browservenster komen sommige thumbnails en de bijbehorende links en dergelijke niet naast, maar onder de kolom met tekst te staan. Omdat die tekst in de html onder de knoppen staat, verdwijnen hierdoor de sluitkruisjes onder de tekst.

Door een hogere z-index te geven aan de <label>, is het sluitkruisje toch altijd zichtbaar boven de tekst.

Een z-index werkt alleen in sommige omstandigheden. Eén van die omstandigheden is een absolute positie. Die heeft de <span> iets hierboven gekregen, dus dat is geregeld.

Er zijn meerdere z-indexen voor verschillende elementen: 40, 50 en 60. Deze sluiten niet op elkaar aan. Hierdoor kun je later makkelijk elementen met een z-index toevoegen, zonder dat je bestaande z-indexen moet gaan veranderen.

.focus-open:focus ~ .open .pop-up, input:checked + .open .pop-up, .open:hover .pop-up

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

.pop-up {background-position: 0 132px; height: 464px; margin-left: -20000px; border: #fc3 ridge 13px; position: absolute; top: -40px; left: 181px; z-index: 60;}

#blok-link-2 .pop-up, #blok-link-4 .pop-up, #blok-link-6 .pop-up, #blok-link-8 .pop-up {left: -705px;}

#blok-link-3 .pop-up, #blok-link-4 .pop-up {top: -170px;}

#blok-link-5 .pop-up, #blok-link-6 .pop-up {top: -255px;}

#blok-link-7 .pop-up, #blok-link-8 .pop-up {top: -326px;}

Drie nogal verschillende selectors, gescheiden door een komma. Ze hebben elk hetzelfde resultaat: ze zetten de eerder links buiten het scherm geparkeerde span.pop-up, waarbinnen de pop-up zit, binnen het scherm, waardoor deze zichtbaar wordt. Het uiterlijke van de pop-up is al eerder opgegeven, hier wordt alleen het zichtbaar maken geregeld.

De eerste selector: .focus-open:focus ~ .open .pop-up:

.focus-open:focus: de <span> die alleen met de Tab-toets is te bereiken, speciaal aangebracht voor gebruikers van de Tab-toets. Maar alleen als deze <span> focus heeft, als deze bereikt is door de Tab-toets een bepaald aantal keren – afhankelijk van de hoeveelste <span> het is – in te drukken.

~: het hierachter staande element moet ergens in de html staan, na het hiervoor staande element. Het hoeft er, anders dan bij de +, niet gelijk op te volgen, als het maar ergens na het eerste element in de html staat.

De enige voorwaarde is verder dat het voor en het na de ~ staande element dezelfde ouder hebben. Dat is hier het geval: span.focus-open voor de ~ en label.open na de ~ hebben beide als ouder dezelfde <li>.

.open: de <label> met class = "open". De <label> die bij de <input> hoort, die zorgt voor het openen van de betreffende pop-up.

Deze 'tussenliggende' <label> is nodig, omdat de selector .focus-open:focus .pop-up niet zou werken: .pop-up zit niet binnen .focus-open. Ook .focus-open:focus ~ .pop-up zou niet werken, want .focus-open en .pop-up hebben niet dezelfde ouder.

.pop-up: de elementen met class="pop-up" binnen label.open. Dit is er maar eentje: de <span> waar de hele pop-up in zit.

In normale mensentaal: als span.focus-open focus heeft, doe dan iets met span.pop-up die binnen de op span.focus-open volgende label.open zit.

De tweede selector: input:checked + .open .pop-up:

input:checked: als een <input> is geselecteerd. (De <input>'s waar het hier om gaat, zijn radioknoppen, waarvan er negen in één groep zitten. Als je er eentje selecteert, wordt daardoor een eventuele eerder geselecteerde knop automatisch gedeselecteerd.

Dit is 'n heel grove selector, maar er volgt nog meer, en dat maakt hem preciezer.

+: de elementen voor en na de + moeten in de html gelijk op elkaar volgen.

.open: de elementen met class="open". Dit zijn de <label>'s die bij de <input>'s horen, die voor het openen van de pop-ups zorgen. Ze volgen in de html gelijk op de radioknop waar ze bij horen. Waarmee is voldaan aan de voorwaarde input + .open.

Deze combinatie van .open gelijk volgend op 'n <input> komt alleen binnen elke <li> met thumbs en dergelijke één keer voor, waarmee deze selector toch heel precies is, ondanks het wat ruige begin met alle <input>'s.

.pop-up: de elementen met class="pop-up". Dit zijn de <span>'s, waarbinnen de pop-ups zitten.

In normale mensentaal: als een radioknop is geselecteerd, doe dan iets met de pop-up die in de <label> zit die gelijk op de radioknop volgt. Als de derde radioknop is geselecteerd, doe dan iets met de pop-up bij de derde thumbnail.

De derde selector: .open:hover .pop-up:

.open:hover: als wordt gehoverd over de elementen met class="open". Binnen elke <li> zit een <input>, waarmee de bijbehorende pop-up kan worden geopend. De elementen met class="open" zijn de bij die <input>'s horende <label>'s. Ze zijn zichtbaar als de witte vlakjes met het vraagteken.

.pop-up: de elementen met class="pop-up". Dit zijn de <span>'s, waarbinnen de pop-ups zitten.

In normale mensentaal: als wordt gehoverd over label.open, doe dan iets met de binnen die <label> zittende span.pop-up.

Door in de selectors alleen classes te gebruiken, geldt deze regel voor álle acht de pop-ups. Als id's waren gebruikt, zouden acht verschillende regels nodig zijn geweest.

margin-left: 0;

Na het volschrijven van anderhalve pagina dat er iets gaat gebeuren, is de spanning ongetwijfeld tot het kookpunt gestegen. Wat gaat er gebeuren, na zo'n gigantische aankondiging?????

Nou, niet zoveel eigenlijk. Want het meeste is al gebeurd bij .pop-up. Daar is de hele lay-out van de pop-up al gemaakt. En daar is de pop-up ook met margin-left: -20000px; links buiten het scherm geparkeerd.

Door die marge weg te halen, wordt de pop-up binnen het scherm geplaatst en daardoor zichtbaar.

Met behulp van left is eerder de exacte plaats al opgegeven. Die is voor pop-ups bij thumbs links naast de tekst anders dan bij pop-ups bij thumbs rechts van de tekst.

.blok a:focus .naam

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

.naam {opacity: 0;}

.naam {color: transparent; opacity: 1; display: block; width: 180px; height: 39px; font-size: 25px; line-height: 34px; text-decoration: underline; margin-top: 50px; position: absolute; z-index: 50;}

Als een link binnen een element met class="blok" focus heeft, doe dan iets met de daarin zittende elementen met class"=naam".

De elementen met class="blok" zijn de acht <li>'s, waarbinnen thumbnails, pop-ups, en dergelijke zitten. Binnen elke <li> zit een link naar de achterliggende pagina. En binnen die link zit weer een <span> met class="naam", waarbinnen de korte naam naar de achter de link zittende pagina zit.

color: blue; Afbeelding 23: als link focus heeft staat naam op thumbnail op doorzichtig witte achtergrond

De voorgrondkleur van span.naam is eerder doorzichtig (transparent) gemaakt, waarmee ook de tekst doorzichtig en dus onzichtbaar is geworden.

Als gebruikers van de Tab-toets de knoppen afgaan, brengt de eerste toetsaanslag ze bij een speciaal voor hen aangebrachte span.focus-open. (Meer daarover is te vinden bij <span class="focus-open" tabindex="0"><span>). Dat opent de pop-up. Een tweede toetsaanslag sluit de pop-up weer, en zet de focus op de link: als de Enter-toets wordt ingedrukt, wordt de link gevolgd.

Om duidelijk te maken bij welke thumbnail naar welke pagina wordt gegaan, wordt de naam zichtbaar gemaakt. Die naam stond al die tijd al braaf op de thumbnail, maar was onzichtbaar, omdat de kleur van de tekst doorzichtig was. Door simpelweg de voorgrondkleur, en daarmee de kleur van de tekst, in blauw te veranderen, wordt de naam zichtbaar.

Gelijktijdig wordt bij input:not(:checked) ~ a:focus gezorgd voor een doorzichtig witte afdekking van de thumbnail, omdat de blauwe naam anders vaak niet goed te zien is. Het geheel ziet er dan uit zoals op bijgaande afbeelding.

input:checked ~ a .naam

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

.naam {opacity: 0;}

.naam {color: transparent; opacity: 1; display: block; width: 180px; height: 39px; font-size: 25px; line-height: 34px; text-decoration: underline; margin-top: 50px; position: absolute; z-index: 50;}

.blok a:focus .naam {color: blue;}

Afbeelding 24: als input is geselecteerd wordt naam getoond

Als een <input> is geselecteerd wordt de bij die <input> horende pop-up getoond. Gelijktijdig wordt de korte naam van de bij de <input> horende achterliggende pagina boven de thumbnail getoond, zoals op de afbeelding is te zien.

Omdat de naam binnen een <span> zit, die weer binnen de link naar de achterliggende pagina zit, werkt de naam als een link: bij aanraking of aanklikken van de naam, opent de achterliggende pagina.

input:checked: als een <input> is geselecteerd. Binnen elke <li> staat onder andere een <input> van de soort radioknop. Dit is een tamelijk grove selector, omdat hij voor élke <input> geldt. Maar de rest van de selector beperkt dit tot een heel specifieke volgorde, die alleen binnen een <li> voorkomt.

~: het hierachter staande element moet ergens in de html staan, na het hiervoor staande element. Het hoeft er, anders dan bij de +, niet gelijk op te volgen, als het maar ergens na het eerste element in de html staat.

De enige voorwaarde is verder dat het voor en het na de ~ staande element dezelfde ouder hebben. Dat is hier het geval: input voor de ~ en a na de ~ hebben beide als ouder de <li>, waarbinnen ze staan.

a: alle links. Dat is er hier maar eentje, de link naar de achterliggende pagina.

.naam: alle elementen met class="naam". Dat is er ook maar eentje: de binnen de <a> zittende <span> met de korte naam van de achterliggende pagina.

In normale mensentaal: als een radioknop is geselecteerd, doe dan iets met de naam die in span.naam binnen de op die radioknop volgende link zit.

background: white;

Witte achtergrond.

color: blue;

Niet omdat ik zo dol ben op blauw, hoewel het mijn lievelingskleur is, maar blauw is een gebruikelijke kleur voor een link. De gebruikelijke onderstreping is eerder al opgegeven.

width: 141px;

Breedte. Samen met het ernaast staande sluitkruisje is dit even breed als de thumb.

font-size: 20px;

Iets grotere letter.

Meestal wordt als eenheid een relatieve eenheid als em gebruikt, omdat bij gebruik van een absolute eenheid zoals px niet alle browsers de lettergrootte kunnen veranderen. (Zoomen kan wel altijd, ongeacht welke eenheid voor de lettergrootte wordt gebruikt.)

Hier is het een voordeel, als een browser dat niet kan. Dat voorkomt namelijk dat de naam te groot wordt. Dat is verder geen ernstig probleem, maar in sommige browsers wordt dat nu dus voorkomen.

margin: 0 0 0 39px;

Links een marge van 39 px.

Eerder is aan de bovenkant een negatieve marge van 50 px opgegeven. Die wordt hier weggehaald. De marge links plaatst de naam precies naast het sluitkruisje.

De verschillende marges, top en left die op verschillende plaatsen worden gebruikt om de naam op de goede plaats te zetten, zouden mogelijk iets efficiënter gebruikt kunnen worden. Dat scheelt echter niet zo heel veel css, en het is heel veel werk dit steeds in alle browsers in tig verschillende resoluties te testen.

Deze instellingen werken, en daarom laat ik ze zo.

border: black solid 1px;

Zwart randje.

border-top-right-radius: 5px;

Rechterbovenhoek rond.

top: -41px;

Op deze hoogte staat de naam precies boven de thumbnail.

De verschillende marges, top en left die op verschillende plaatsen worden gebruikt om de naam op de goede plaats te zetten, zouden mogelijk iets efficiënter gebruikt kunnen worden. Dat scheelt echter niet zo heel veel css, en het is heel veel werk dit steeds in alle browsers in tig verschillende resoluties te testen.

Deze instellingen werken, en daarom laat ik ze zo.

left: -1px;

Kleine verplaatsing naar links, zodat de naam goed aansluit op het ernaast staande sluitkruisje.

De verschillende marges, top en left die op verschillende plaatsen worden gebruikt om de naam op de goede plaats te zetten, zouden mogelijk iets efficiënter gebruikt kunnen worden. Dat scheelt echter niet zo heel veel css, en het is heel veel werk dit steeds in alle browsers in tig verschillende resoluties te testen.

Deze instellingen werken, en daarom laat ik ze zo.

input:not(:checked) ~ a:focus

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

a {width: 120px; height: 108px; position: absolute; top: 8px; left: 8px;}

.blok a {-webkit-animation: bugfix infinite 1s; box-shadow: 4px 3px 4px 1px black; display: block; width: 180px; height: 161px; text-align: center; margin: 0 auto; border: black solid 1px; border-radius: 5px; position: relative; top: 0; left: 0;}

#blok-link-2 a, #blok-link-4 a, #blok-link-6 a, #blok-link-8 a {box-shadow: -4px 3px 4px 1px black;}

input:not(:checked): <input>'s die niet (:not) zijn geselecteerd (:checked). Dit is een tamelijk grove selector, die voor alle niet-geselecteerde radioknoppen zou gelden. Maar er volgt nog een deel op, waardoor de selector veel specifieker wordt.

~: het hierachter staande element moet ergens in de html staan, na het hiervoor staande element. Het hoeft er, anders dan bij de +, niet gelijk op te volgen, als het maar ergens na het eerste element in de html staat.

De enige voorwaarde is verder dat het voor en het na de ~ staande element dezelfde ouder hebben. Dat is hier het geval: de input voor de ~ en de a na de ~ hebben beide als ouder dezelfde <li>.

a:focus: als de link focus heeft. Dit is de link naar de achterliggende pagina bij de thumb. Deze link staat over de thumbnail heen, waardoor hij de thumb volledig afdekt.

In normale mensentaal: doe iets met de link naar de achterliggende pagina, maar alleen als deze focus heeft en de ervoor zittende <input> niet is geselecteerd.

Dit is bedoeld voor gebruikers van de Tab-toets. Bij de eerste tab wordt onder andere de naam getoond op de thumb, zoals beschreven bij .blok a:focus .naam. Omdat die naam soms nogal onduidelijk is, wordt een doorzichtige witte achtergrond op de thumb gezet.

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

Doorzichtig witte achtergrondkleur. Hoe rgba() precies werkt, is te vinden bij background: rgba(255, 255, 255, 0.75);. Het enige verschil is dat de doorzichtigheid hier geen 0.5, maar 0.75 is: iets minder.

input:not(:checked) + .open:hover ~ a .naam, .focus-open:focus ~ input:not(:checked) ~ a .naam

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

.naam {opacity: 0;}

.naam {color: transparent; opacity: 1; display: block; width: 180px; height: 39px; font-size: 25px; line-height: 34px; text-decoration: underline; margin-top: 50px; position: absolute; z-index: 50;}

.blok a:focus .naam {color: blue;}

input:checked ~ a .naam {background: white; color: blue; width: 141px; font-size: 20px; margin: 0 0 0 39px; border: black solid 1px; border-top-right-radius: 5px; top: -41px; left: -1px;}

#blok-link-2 input:checked ~ a .naam, #blok-link-4 input:checked ~ a .naam, #blok-link-6 input:checked ~ a .naam, #blok-link-8 input:checked ~ a .naam {margin: 0 39px 0 0; border-radius: 5px 0 0;}

Dit ziet er weer gezellig ingewikkeld uit. Maar zoals gewoonlijk: als je het in stukjes hakt, wordt het al 'n stuk overzichtelijker.

Deze regel zorgt ervoor dat de korte naam van de achterliggende pagina boven de thumbnail wordt gezet bij hoveren over het witte vlakje met het vraagteken, of als de speciaal voor de Tab-toets aangebrachte span.focus-open focus heeft. (Meer over span.focus-open is te vinden bij Tabindex.)

Er zijn twee selectors: eentje voor en eentje na de komma.

De eerste selector: input:not(:checked) + .open:hover ~ a .naam

input:not(:checked): alle <input>'s – dat zijn hier radioknoppen –, maar alleen als deze niet (:not) zijn geselecteerd (:checked). De naam moet ook worden getoond als de pop-up is geopend door het selecteren van een radioknop. Maar in dat geval staat er ook een kruisvakje naast de naam, waardoor de op een iets andere plaats moet worden neergezet.

Afbeelding 25: bovenste naam staat goed, onderste twee niet

Door deze selector niet te laten werken, als de radioknop is geselecteerd en het sluitkruisje zichtbaar is, wordt voorkomen dat de naam op de verkeerde plaats naast het sluitkruisje wordt gezet.

Op de afbeelding staat bovenaan de naam naast het sluitkruisje. Dit is de situatie als de pop-up door klikken of aanraken geopend blijft: links boven de thumb het sluitkruisje, rechts de naam.

In het midden staat de situatie, als de speciaal voor de Tab-toets aangebrachte <span> focus heeft, of als over het witte vlakje met het vraagteken wordt gehoverd: de naam wordt boven de thumbnail weergegeven, maar zonder sluitkruisje.

Onderaan staat, wat er gebeurt bij een combinatie van deze twee dingen: het sluitkruisje staat er, maar de naam staat – net zoals bij hoveren of als de <span> voor de Tab-toets focus heeft – in het midden boven de thumbnail. Waardoor deze gedeeltelijk onder het sluitkruisje verdwijnt.

Dit wordt voorkomen door hoveren en focus voor de Tab-toets alleen te laten werken, als de radioknop niet is geselecteerd. Als de radioknop is geselecteerd, wordt de bijbehorende korte naam nu niet verplaatst bij hoveren of focus.

Dit is een tamelijk grove selector, omdat hij voor álle <input>'s geldt. Maar de rest van de selector beperkt dit tot een heel specifieke volgorde van elementen, die alleen binnen de <li>'s met de thumbnails en dergelijke voorkomt.

+: het element achter de + moet in de html direct volgen op het element voor de +. In dit geval gaat het om element met class="open" (de <label> die onder andere voor het openen van de pop-up zorgt) die gelijk op een button type radioknop volgt.

.open:hover: de elementen met class="open", maar alleen als hierover wordt gehoverd. In dit <label> zit onder andere de <span> die zorgt voor het witte vlakje met het vraagteken.

~: het hierachter staande element moet ergens in de html staan, na het hiervoor staande element. Het hoeft er, anders dan bij de +, niet gelijk op te volgen, als het maar ergens na het eerste element in de html staat.

De enige voorwaarde is verder dat het voor en het na de ~ staande element dezelfde ouder hebben. Dat is hier het geval: label.open voor de ~ en de <a> na de ~ hebben beide als ouder dezelfde <li>.

a: alle links. Dat is er hier maar eentje: de link naar de achterliggende pagina.

.naam: de elementen met class="naam". Binnen elke <a> zit een span.naam, waarbinnen de korte naam van de achterliggende pagina staat.

In normale mensentaal: doe iets met de korte naam van de pagina, die binnen een <span> binnen de <a> zit, als over het witte vlakje met het vraagteken wordt gehoverd, maar niet als de ervoor zittende radioknop is geselecteerd.

De tweede selector: .focus-open:focus ~ input:not(:checked) ~ a .naam

.focus-open:focus: een speciaal voor gebruikers van de Tab-toets aangebrachte span.focus-open zorgt ervoor dat de pop-up ook met de Tab-toets kan worden geopend. Er is meer over te lezen bij Tabindex. Als deze <span> focus heeft.

~: het hierachter staande element moet ergens in de html staan, na het hiervoor staande element. Het hoeft er, anders dan bij de +, niet gelijk op te volgen, als het maar ergens na het eerste element in de html staat.

De enige voorwaarde is verder dat het voor en het na de ~ staande element dezelfde ouder hebben. Dat is hier het geval: span.focus-open voor de ~ en de <input> na de ~ hebben beide als ouder dezelfde <li>.

input:not(:checked): alle <input>'s – die zijn hier van het type radioknop –, maar alleen als deze niet zijn geselecteerd. Waarom dit nodig is, staat hier iets boven bij input:not(:checked) bij de eerste selector.

~: het hierachter staande element moet ergens in de html staan, na het hiervoor staande element. Het hoeft er, anders dan bij de +, niet gelijk op te volgen, als het maar ergens na het eerste element in de html staat.

De enige voorwaarde is verder dat het voor en het na de ~ staande element dezelfde ouder hebben. Dat is hier het geval: de input voor de ~ en de <a> na de ~ hebben beide als ouder dezelfde <li>.

a: alle links. Dat is er hier maar eentje: de link naar de achterliggende pagina.

.naam: de elementen met class="naam". Binnen elke <a> zit een span.naam, waarbinnen de korte naam van de achterliggende pagina staat.

In normale mensentaal: doe iets met de korte naam van de pagina, die binnen een <span> binnen de <a> zit, als de speciaal voor de Tab-toets aangebrachte <span> focus heeft, maar niet als de op die <span> volgende radioknop is geselecteerd.

background: white;

Witte achtergrond.

color: black;

De voorgrondkleur, en dus ook de kleur van de tekst, is eerder doorzichtig (transparent) gemaakt. Daardoor is de tekst onzichtbaar. Hier wordt de korte naam van de achterliggende pagina weer zichtbaar gemaakt.

font-size: 22px;

Tamelijk grote letter.

Meestal wordt als eenheid een relatieve eenheid als em gebruikt, omdat bij gebruik van een absolute eenheid zoals px niet alle browsers de lettergrootte kunnen veranderen. (Zoomen kan wel altijd, ongeacht welke eenheid voor de lettergrootte wordt gebruikt.)

Hier is het een voordeel, als een browser dat niet kan. Dat voorkomt namelijk dat de naam te groot wordt. Dat is verder geen ernstig probleem, maar in sommige browsers wordt dat nu dus voorkomen.

margin: 0;

Alle eerder opgegeven marges weghalen.

De verschillende marges, top en left die op verschillende plaatsen worden gebruikt om de naam op de goede plaats te zetten, zouden mogelijk iets efficiënter gebruikt kunnen worden. Dat scheelt echter niet zo heel veel css, en het is heel veel werk dit steeds in alle browsers in tig verschillende resoluties te testen.

Deze instellingen werken, en daarom laat ik ze zo.

border: black solid 1px;

Zwart randje.

border-radius: 5px 5px 0 0;

Links‑ en rechtsboven ronde hoekjes.

top: -41px;

41 px naar boven verplaatsen. Op deze hoogte staat de naam precies boven de thumbnail.

De verschillende marges, top en left die op verschillende plaatsen worden gebruikt om de naam op de goede plaats te zetten, zouden mogelijk iets efficiënter gebruikt kunnen worden. Dat scheelt echter niet zo heel veel css, en het is heel veel werk dit steeds in alle browsers in tig verschillende resoluties te testen.

Deze instellingen werken, en daarom laat ik ze zo.

left: -1px;

Kleine verschuiving naar links om de naam op precies de juiste plaats te krijgen.

De verschillende marges, top en left die op verschillende plaatsen worden gebruikt om de naam op de goede plaats te zetten, zouden mogelijk iets efficiënter gebruikt kunnen worden. Dat scheelt echter niet zo heel veel css, en het is heel veel werk dit steeds in alle browsers in tig verschillende resoluties te testen.

Deze instellingen werken, en daarom laat ik ze zo.

input:checked ~ a .naam::after, .open:hover + a .naam::after, .focus-open:focus ~ a .naam::after

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

.naam::after {content: ""; color: #ddd; width: 6px; height: 12px; border: solid; border-width: 0 2px 2px 0; border-top-right-radius: 3px; border-bottom-left-radius: 5px; pointer-events: none; position: absolute; top: -50px; left: 5px; -ms-transform: rotate(45deg) skew(14deg); -webkit-transform: rotate(45deg) skew(14deg); transform: rotate(45deg) skew(14deg);}

#blok-link-4 .naam::after, #blok-link-8 .naam::after {color: #ccc;}

#blok-link-2 .naam::after, #blok-link-4 .naam::after, #blok-link-6 .naam::after, #blok-link-8 .naam::after {left: auto; right: 3px;}

.blok a:visited .naam::after, #blok-link-4 a:visited .naam::after, #blok-link-8 a:visited .naam::after {color: black;}

Drie selectors, gescheiden door een komma. Het tweede deel van alle drie is hetzelfde, daarom beschrijf ik ze hier gezamenlijk.

Het eerste deel van de drie selectors geeft aan, wanneer iets moet gebeuren:

input:checked: de <input>'s – dat zijn hier radioknoppen – die zijn geselecteerd.

.open:hover: als over de elementen met class="open" wordt gehoverd. Dit zijn de <label>'s, waarbinnen onder andere het witte vlakje met het vraagteken zit.

.focus-open:focus: een speciaal voor gebruikers van de Tab-toets aangebrachte span.focus-open zorgt ervoor dat de pop-up ook met de Tab-toets kan worden geopend. Er is meer over te lezen bij Tabindex. Als deze <span> focus heeft.

Samengevat: als een radioknop is geselecteerd, of als wordt gehoverd over het witte vlakje met het vraagteken, of als de <span> voor gebruikers van de Tab-toets focus heeft. Deze drie dingen hebben alle drie tot gevolg, dat de pop-up wordt geopend.

+ en ~: het element voor de + of ~ moet in de html voor het element achter de + of ~ staan.

Bij de + moeten de elementen gelijk op elkaar volgen. Bij de ~ mogen er andere elementen tussen zitten, als het tweede element maar na het eerste element in de html staat.

De enige voorwaarde is verder dat het voor en het na de ~ staande element dezelfde ouder hebben. Dat is hier het geval: de input voor de ~ en de <a> na de ~ hebben beide als ouder dezelfde <li>.

Het derde deel, dat bij alle drie de selectors hetzelfde is:

.naam::after: bij .naam::after is met behulp van ::after bij .naam een pseudo-element gemaakt, waarbinnen een vinkje is gezet. Dit vinkje wordt naast het vraagteken zichtbaar, als de bijbehorende pagina al is bezocht.

In normale mensentaal: doe iets met het vinkje naast het vraagteken als de pop-up is geopend doordat een radioknop is geselecteerd, over het witte vlakje met het vraagteken wordt gehoverd, of de <span> voor de Tab-toets focus heeft.

display: none;

Het pseudo-element met het vinkje hoort bij span.naam. Bij input:not(:checked) + .open:hover ~ a .naam, .focus-open:focus ~ input:not(:checked) ~ a .naam is span.naam een eind naar boven verplaatst. Hierdoor gaat ook het vinkje mee naar boven, waardoor dit niet meer naast het vraagteken, maar een eind daarboven wordt neergezet. Om precies te zijn: op de thumbnail erboven.

Dit onaangepaste gedrag wordt niet getolereerd. De zich misdragende vinkjes worden gewoon helemaal verborgen. Eigen schuld, dikke bult.

(Je zou ze waarschijnlijk ook 'n eind omlaag kunnen neerzetten, maar zo belangrijk zijn ze niet. En er zitten al zoveel marges, posities, enz. in de css, dat ik kies voor de simpelste oplossing: weg met die handel.)

input:checked ~ .sluit

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

input, .vraagteken, .sluit {display: none;}

.sluit {-webkit-animation: bugfix infinite 1s; background: white; color: red; display: block; width: 38px; height: 39px; overflow: hidden; font-size: 77px; line-height: 25px; border: black solid; border-width: 1px 1px 0; border-top-left-radius: 5px; position: absolute; top: -40px; left: -20000px; z-index: 50;}

input:checked: als een <input> – dat zijn hier radioknoppen – is geselecteerd.

~: het hierachter staande element moet ergens in de html staan, na het hiervoor staande element. Het hoeft er, anders dan bij de +, niet gelijk op te volgen, als het maar ergens na het eerste element in de html staat.

De enige voorwaarde is verder dat het voor en het na de ~ staande element dezelfde ouder hebben. Dat is hier het geval: de <input> voor de ~ en label.sluit na de ~ hebben beide als ouder dezelfde <li>.

.sluit: de elementen met class="sluit". Onderaan elke <li> zit een label.sluit. Hierbinnen zit de letter 'x'. Deze wordt wat opgeleukt tot een rood sluitkruisje.

In normale mensentaal: doe iets met label.sluit, het sluitkruisje, als de ervoor zittende radioknop is geselecteerd.

left: 0;

Bij .sluit is het sluitkruisje al helemaal opgemaakt. Daar is het ook links buiten het scherm geparkeerd, zodat het onzichtbaar is. Hier wordt het sluitkruisje binnen het scherm gezet en daardoor zichtbaar.

Als de pop-up is geopend door aanraken van of klikken op het witte vlakje met het vraagteken, wordt feitelijk een radioknop geselecteerd. Deze knop zorgt voor het openblijven van de pop-up. Alleen door het selecteren van een andere radioknop uit dezelfde groep, kan de pop-up weer worden gesloten.

Daar is dit sluitkruisje voor. De radioknop die bij de <label> met het sluitkruisje hoort, zit in dezelfde groep radioknoppen, waarmee de pop-ups worden geopend. Door op deze <label>, het sluitkruisje, te klikken of dit aan te raken, wordt de negende radioknop geselecteerd. Deze negende radioknop hoort niet bij een pop-up. Als deze negende knop wordt geselecteerd via dit <label>, is de eerder geselecteerde radioknop niet meer geselecteerd, waardoor de bij die knop horende pop-up weer verdwijnt.

main

Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

main {display: block; max-width: 700px; margin: 0 auto; padding: 5px;}

Alle <main>'s. Dat is er maar eentje. Binnen <main> staat de belangrijkste inhoud van de pagina. Dat is hier voornamelijk opvultekst, maar normaal genomen staat daar – hopelijk – wel iets interessants.

background: #eee;

Lichtgrijze achtergrondkleur.

color: black;

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

Hoewel dit de standaardkleur is, wordt deze toch specifiek opgegeven. Hierboven is een achtergrondkleur opgegeven. Sommige mensen hebben zelf de voorgrond- en/of achtergrondkleur veranderd, bijvoorbeeld omdat ze slecht kleuren kunnen onderscheiden. Als nu de achtergrondkleur wordt veranderd, maar niet de voorgrondkleur, loop je het risico dat tekstkleur en achtergrondkleur te veel op elkaar gaan lijken.

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

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

width: calc(100% - 412px);

Breedte.

Een blok-element zoals <main> wordt normaal genomen even breed als z'n ouder. Dat is hier <body>, ook een blok-element. Ook <body> wordt hierdoor even breed als z'n ouder: het blok-element <html>. Omdat <html> geen ouder meer heeft, wordt dit even breed als het venster van de browser. Normaal genomen zou <main> daardoor ook even breed worden als het venster van de browser.

Dat is hier niet de bedoeling, want links en rechts van de <main> met de tekst staan nog thumbnails. Met behulp van calc() wordt daarom hier een breedte opgegeven.

Een breedte in procenten is altijd ten opzichte van de ouder van het element. Bij calc(100%) zou <main> daarom even breed zijn als <body> (en uiteindelijk even breed als het venster van de browser). Dat is weinig interessant.

Maar met calc() kun je verschillende eenheden in één berekening gebruiken. Door van 100% (de breedte van het venster van de browser) 412 px af te trekken, is er links en rechts van <main> altijd ruimte voor de thumbnails, ongeacht hoe breed het venster is.

Deze breedte zou eigenlijk niet nodig moeten zijn, omdat hieronder de <main> een maximumbreedte krijgt. In bredere vensters zou deze hetzelfde moeten werken als een gewone breedte, waardoor de <main> – in combinatie met de absolute positie en left en right – horizontaal gecentreerd zou moeten staan. Dat gebeurt echter niet in Internet Explorer en Edge.

Op een of andere manier zorgt het opgeven van deze breedte voor horizontaal centreren in deze browsers. Vreemd, omdat de uitkomst van deze berekening groter kan zijn dan de hieronder opgegeven maximumbreedte van 860 px. Maar het werkt, en daar gaat het maar om.

(In smallere vensters speelt dit niet: left: 200px; en right: 200px; zorgen er dan voor dat <main> horizontaal gecentreerd staat.)

max-width: 860px;

Maximumbreedte voorkomt te lange en daardoor slecht leesbare regels. Het is bovendien nodig om <main> horizontaal te kunnen centreren. Hoe dat centreren precies gebeurt, staat iets hieronder bij position.

(Hierboven wordt ook een gewone breedte opgegeven. Dat is alleen nodig vanwege een bug in Internet Explorer en Edge.)

overflow: auto;

<main> wordt hieronder absoluut gepositioneerd met onder andere top: 40px; en bottom: 0;. Dit zorgt ervoor dat de erboven staande <h1> niet meescrolt, maar dat deze <h1> altijd bovenaan het venster van de browser blijft staan.

Als er nu zoveel tekst in <main> staat dat dit niet binnen het venster past, verschijnt een verticale scrollbalk aan de rechterkant van het venster, waarmee de hele pagina gescrold kan worden. Ook de boven de tekst staande <h1> scrolt dan mee.

Door overflow bij <main> op auto te zetten, verschijnt de scrollbalk niet aan de rechterkant van het venster, maar aan de rechterkant van <main>. De tekst kan nu binnen <main> worden gescrold, zonder dat de rest van de pagina meescrolt. De <h1> blijft nu netjes bovenaan het venster van de browser staan.

-webkit-overflow-scrolling: touch;

Zoals gelijk hierboven beschreven scrolt de tekst binnen het element <main>. Als op iOS niet de hele pagina, maar binnen een element wordt gescrold, gaat dat ongelooflijk schokkerig. De reden daarvan is volstrekt onduidelijk, want Apple is bepaald niet open met informatie over dit soort dingen.

Dit zorgt ervoor dat op iOS ook binnen <main> soepel gescrold kan worden.

Omdat deze eigenschap alleen nodig is voor iOS, wordt alleen de -webkit-vorm gebruikt. Normaal genomen is dat hartstikke fout, omdat je dan onbetaald Apple helpt bij z'n pogingen sites alleen in Safari goed weer te geven. Maar in dit geval is deze eigenschap allen op iOS nodig.

border: black solid;

Zwart randje. De breedte wordt gelijk hieronder opgegeven.

border-width: 0 1px;

Kleur en stijl zijn gelijk hierboven al opgegeven.

Omdat voor onder en links geen breedte is opgegeven, krijgen die automatisch dezelfde breedte als boven en rechts. Hier staat dus eigenlijk 0 1px 0 1px in de volgorde boven – rechts – onder – links. Alleen links en rechts een randje.

Het op deze manier opgeven van de borders gebruikt iets minder css dan twee volledig losse regels voor de borders links en rechts.

position: absolute;

Om de <main> op de juiste plaats neer te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Als die er niet is, zoals hier het geval is, wordt gepositioneerd ten opzichte van het venster van de browser.

Met top: 40px; en bottom: 0; wordt <main> in verticale richting vastgezet. In de ruimte van 40 px aan de bovenkant staat de <h1>.

Iets hierboven is overflow: auto; opgegeven. Als er te veel tekst is voor het venster, scrolt de tekst hierdoor binnen <main>, zonder dat de hele pagina meescrolt. De <h1> scrolt hierdoor ook niet mee, maar blijft altijd bovenaan het venster van de browser staan.

Het verhaal voor left en right is iets ingewikkelder.

Bij beide wordt 200 px opgegeven. Dat is ten opzichte van het browservenster. Hierdoor is er links en rechts van de <main> met de tekst altijd ruimte voor de thumbnails.

Als je verder niets zou doen, zou je in brede vensters heel lange regels krijgen, die daardoor heel slecht leesbaar worden. Daarom is iets hierboven een maximumbreedte van 860 px opgegeven. (En nog iets hoger ook een gewone breedte, maar die doet hier verder niet mee, want die is alleen nodig voor een bug in Internet Explorer en Edge.)

En dan ontstaat er in brede vensters een onmogelijke situatie. Stel dat het venster 1500 px breed is. left: 200px;, dan blijft er rechts daarvan nog 1300 px over. right: 200px;. Nu is er in het midden nog 1300 px over. Maar de maximumbreedte is 860 px. Dat levert een gat op van 440 px.

Een middeleeuwse pijnbank of vierendelen (eigenlijk tweedelen hier) zou kunnen helpen, maar dat levert mogelijk wat problemen van justitiële aard op. Een krant kun je in zo'n geval gezellig in tweeën scheuren, maar het in tweeën slaan van de monitor wordt al snel een begrotelijke hobby en bevordert ook de kwaliteit van het beeld niet echt.

Dan vallen we maar heel saai terug op de specificatie. In deze onmogelijke gevallen wordt rechts en links de afstand gelijk verdeeld. Oftewel: <main> wordt netjes horizontaal gecentreerd.

(Dit is trouwens ook een weinig bekende truc om absoluut gepositioneerde blok-elementen horizontaal te centreren. En het werkt zelfs ook bij verticaal centreren. De enige voorwaarde is dat er een breedte (of hoogte) aanwezig is, en dat right en left (of top en bottom) een andere waarde dan de standaardwaarde auto moeten hebben.

top: 40px; right: 200px; bottom: 0; left: 200px;

Deze eigenschappen worden gelijk hierboven bij position besproken.

#checkbox-voor-focus

Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

input, .vraagteken, .sluit {display: none;}

Het element met id="checkbox-voor-focus".

Aan het begin van de tekst in de middelste kolom is een <input> neergezet:

<input id="checkbox-voor-focus" type="checkbox" aria-hidden="true" autofocus>

Deze <input> heeft feitelijk geen enkele werking. Maar door het gebruik van het attribuut autofocus wordt de focus op de tekst gezet. Als dat niet zou gebeuren, moet eerst in de tekst worden geklikt, voordat de tekst kan worden gescrold met behulp van scrollwieltje of pijltjes.

(Dit komt doordat in de html de <nav> met de knoppen voor de <main> met de tekst staat. Je zou die volgorde ook kunnen veranderen, en dan is deze <input> niet nodig. Op de site kan dat niet, omdat er nog veel meer links en dergelijke in de <nav> staan. In het voorbeeld heb ik de volgorde hetzelfde gelaten, omdat er anders nog 'n verschil met de site zou ontstaan.)

display: block;

Eerder is deze <input> verborgen met display: none;. In kleinere browservensters is dat prima, want daar is hij niet nodig. Maar in bredere vensters kan dat niet, omdat de truc niet werkt als de <input> met display: none; wordt verborgen. Daarom wordt de <input> hier weer zichtbaar gemaakt.

position: absolute;

Om de <input> op een bepaalde plaats neer te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier <main>.

left: -20000px;

Ik heb verder helemaal niets tegen <input>'s, maar ze zijn niet echt het allermooiste element dat er is. Daarom wordt de <input> links buiten het scherm geparkeerd. Nu kan hij, anders dan bij display: none;, rustig z'n nuttige werk doen, zonder dat artistieke zielen zoals ik zich aan z'n uiterlijk hoeven te ergeren.

css voor vensters minimaal 543 px en maximaal 712 px hoog en minimaal 763 px breed

@media screen and (min-height: 543px) and (max-height: 712px) and (min-width: 763px)

Afbeelding 26: menu in brede, maar middelhoge vensters

De css die hier tot nu toe staat, geldt voor alle browservensters.

De css die binnen deze media query staat, geldt alleen voor vensters die minimaal 543 px hoog én maximaal 712 px hoog én minimaal 763 px breed zijn. Deze vensters zijn te laag om links en rechts van de tekst vier thumbnails onder elkaar te kunnen zetten. Daarom worden links en rechts van de tekst twee thumbnails neergezet en worden de overige vier onder de tekst neergezet.

Ook de css die eerder bij @media screen and (min-width: 763px) and (min-height: 543px) is opgegeven, blijft hier gewoon gelden. Er wordt binnen deze media-regel alleen extra css opgegeven die alleen geldt voor vensters die maximaal 712 hoog zijn.

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

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

(min-height: 543px): het venster moet minimaal 543 px hoog zijn. Is het venster lager, dan wordt de css die binnen deze media-regel staat genegeerd.

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

(max-height: 712px): het venster mag maximaal 712 px hoog zijn. Is het venster hoger, dan wordt de css die binnen deze media-regel staat genegeerd.

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

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

Gelijk na deze regel komt een { te staan, en aan het einde van de css die binnen deze regel valt een bijbehorende afsluitende }.

Die zijn in de regel hierboven weggevallen, maar het geheel ziet er zo uit:

@media screen and (min-width: 760px) and (min-height: 500px) { 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 }.

#blok-link-6 .vraagteken

Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

input, .vraagteken, .sluit {display: none;}

.vraagteken {background: rgba(255, 255, 255, 0.75); color: #666; display: block; width: 48px; height: 40px; font-size: 2.4em; line-height: 29px; border-radius: 5px 0 5px; padding-top: 10px; position: relative; top: 1px; z-index: 40;}

#blok-link-2 .vraagteken, #blok-link-4 .vraagteken, #blok-link-6 .vraagteken, #blok-link-8 .vraagteken {border-radius: 0 5px;}

De elementen met class="vraagteken" binnen het element met id="blok-link-6". De <span> die in de zesde <li> voor het witte blokje met het vraagteken zorgt.

border-radius: 5px 0;

Omdat voor rechts- en linksonder geen waarde is opgegeven, krijgen die automatisch dezelfde waarde als links‑ en rechtsboven. Hier staat dus eigenlijk 5px 0 5px 0 in de volgorde linksboven – rechtsboven – rechtsonder – linksonder.

Eerder stond dit zesde vraagteken rechts van de tekst. Nu staat het onder de tekst links van het midden. De eerder opgegeven ronde hoeken rechtsboven en linksonder moeten daarom worden omgekeerd naar ronde hoeken linksboven en rechtsonder.

#blok-link-7 .vraagteken

Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

input, .vraagteken, .sluit {display: none;}

.vraagteken {background: rgba(255, 255, 255, 0.75); color: #666; display: block; width: 48px; height: 40px; font-size: 2.4em; line-height: 29px; border-radius: 5px 0 5px; padding-top: 10px; position: relative; top: 1px; z-index: 40;}

De elementen met class="vraagteken" binnen het element met id="blok-link-7". De <span> die in de zevende <li> voor het witte blokje met het vraagteken zorgt.

border-radius: 0 5px;

Omdat voor rechts- en linksonder geen waarde is opgegeven, krijgen die automatisch dezelfde waarde als links‑ en rechtsboven. Hier staat dus eigenlijk 0 5px 0 5px in de volgorde linksboven – rechtsboven – rechtsonder – linksonder.

Eerder stond dit zevende vraagteken links van de tekst. Nu staat het onder de tekst rechts van het midden. De eerder opgegeven ronde hoeken linksboven en rechtsonder moeten daarom worden omgekeerd naar ronde hoeken rechtsboven en linksonder.

#blok-link-6 a

Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

a {width: 120px; height: 108px; position: absolute; top: 8px; left: 8px;}

.blok a {-webkit-animation: bugfix infinite 1s; box-shadow: 4px 3px 4px 1px black; display: block; width: 180px; height: 161px; text-align: center; margin: 0 auto; border: black solid 1px; border-radius: 5px; position: relative; top: 0; left: 0;}

#blok-link-2 a, #blok-link-4 a, #blok-link-6 a, #blok-link-8 a {box-shadow: -4px 3px 4px 1px black;}

input:not(:checked) ~ a:focus {background: rgba(255, 255, 255, 0.5);}

De links binnen het element met id="blok-link-6". Dit is de link naar de achterliggende pagina in de zesde <li>.

box-shadow: 4px 3px 4px 1px black;

Deze <a> hoort bij een thumbnail die eerst rechts van de tekst stond. Nu staat deze linksonder de tekst. Daarom moet de box-shadow niet meer links, maar rechts van de <a> worden neergezet.

Hoe box-shadow precies werkt, is te vinden bij box-shadow: 4px 6px 4px 1px black;.

left: 1px;

Kleine correctie om dubbele border links van thumbnail te voorkomen.

Waarom dit precies nodig is, heb ik verder niet uitgezocht. De plaatsing van diverse elementen is nogal ingewikkeld. Mogelijk zou je deze kleine correctie overbodig kunnen maken, maar dat vergt waarschijnlijk uren zoeken. En controleren of dat niet elders weer problemen veroorzaakt. Dit werkt, dus houd ik het zo.

#blok-link-7 a

Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

a {width: 120px; height: 108px; position: absolute; top: 8px; left: 8px;}

.blok a {-webkit-animation: bugfix infinite 1s; box-shadow: 4px 3px 4px 1px black; display: block; width: 180px; height: 161px; text-align: center; margin: 0 auto; border: black solid 1px; border-radius: 5px; position: relative; top: 0; left: 0;}

input:not(:checked) ~ a:focus {background: rgba(255, 255, 255, 0.5);}

De links binnen het element met id="blok-link-7". Dit is de link naar de achterliggende pagina in de zevende <li>.

box-shadow: -4px 3px 4px 1px black;

Deze <a> hoort bij een thumbnail die eerst links van de tekst stond. Nu staat deze rechtsonder de tekst. Daarom moet de box-shadow niet meer rechts, maar links van de <a> worden neergezet.

Hoe box-shadow precies werkt, is te vinden bij box-shadow: 4px 6px 4px 1px black;.

main

Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

main {display: block; max-width: 700px; margin: 0 auto; padding: 5px;}

main {background: #eee; color: black; width: calc(100% - 412px); max-width: 860px; overflow: auto; -webkit-overflow-scrolling: touch; border: black solid; border-width: 0 1px; position: absolute; top: 40px; right: 200px; bottom: 0; left: 200px;}

Alle <main>'s. Dat is er maar eentje. Binnen <main> staat de belangrijkste inhoud van de pagina. Dat is hier voornamelijk opvultekst, maar normaal genomen staat daar – hopelijk – wel iets interessants.

bottom: 181px;

Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Als die er niet is, zoals hier het geval is, wordt gepositioneerd ten opzichte van het venster van de browser.

Aan de onderkant wordt een ruimte van 181 px vrijgehouden, waarin de thumbnails kunnen staan, zonder dat deze over de tekst in <main> heen komen te staan.

main::before

Bij het element <main> wordt met behulp van ::before een pseudo-element gemaakt. Dit pseudo-element wordt gebruikt om aan de onderkant van <main> een gradiënt neer te zetten. Deze gradiënt staat over ruwweg de onderste drie regels van de tekst. Bovenaan is hij doorzichtig, onderaan ondoorzichtig.

Op touchscreens is geen scrollbalk aanwezig. Daardoor is niet duidelijk dat de tekst onderaan nog doorloopt. Als het 'n beetje ongelukkig uitkomt en de onderste zichtbare regel is toevallig de laatste regel van een paragraaf, lijkt het of er niet meer tekst is.

Met de gradiënt wordt duidelijk gemaakt dat de tekst nog doorloopt.

content: "";

Dit moet altijd worden opgegeven bij een met behulp van ::before gemaakt pseudo-element, ook als er geen echte tekst of zo aanwezig is. Dat geef je aan met twee aanhalingstekens, waar niets tussen staat.

background-image: -webkit-linear-gradient(to bottom, rgba(204, 204, 204, 0) 0%, rgba(204, 204, 204, 0.5) 20%, rgba(204, 204, 204, 0.8) 80%, rgba(204, 204, 204, 1) 100%); background-image: linear-gradient(to bottom, rgba(204, 204, 204, 0) 0%, rgba(204, 204, 204, 0.5) 20%, rgba(204, 204, 204, 0.8) 80%, rgba(204, 204, 204, 1) 100%);

Hier staat in feite twee keer hetzelfde: background-image: linear-gradient(to bottom, rgba(204, 204, 204, 0) 0%, rgba(204, 204, 204, 0.5) 20%, rgba(204, 204, 204, 0.8) 80%, rgba(204, 204, 204, 1) 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. Oudere versies van Android browser en UC browser op Android hebben ook geen gradiënt, omdat bij de positionering calc() wordt gebruikt, wat deze browsers niet kennen.

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 vier keer twee waarden, gescheiden door een komma. De eerste waarde is steeds de kleur, de tweede de plaats waar die kleur staat.

rgba(204, 204, 204, 0) 0%: de kleur rgba(204, 204, 204, 0) (wit) op 0% vanaf de bovenkant neerzetten (dat is helemaal bovenaan).

Dit is een lichtgrijze kleur, die volledig doorzichtig is. (Hoe rgba() precies werkt, is te vinden bij background: rgba(255, 255, 255, 0.75);.)

rgba(204, 204, 204, 0.5) 20%: de kleur is hetzelfde als gelijk hierboven, maar nu is de kleur halfdoorzichtig: 0.5, waardoor de tekst vager wordt. Deze doorzichtigheid wordt op 20% vanaf de bovenkant bereikt.

De lichtgrijze gradiënt verandert geleidelijk van volledig doorzichtig (0%, bovenaan) in halfdoorzichtig (20% vanaf de bovenkant).

rgba(204, 204, 204, 0.8) 80%: de kleur is nog steeds hetzelfde als hierboven, maar nu is de gradiënt vrijwel ondoorzichtig: 0.8, waardoor de tekst nog moeilijk te zien is. Deze doorzichtigheid wordt op 80% vanaf de bovenkant bereikt.

De lichtgrijze gradiënt verandert geleidelijk van halfdoorzichtig (20% vanaf de bovenkant) in vrijwel ondoorzichtig (80% vanaf de bovenkant).

rgba(204, 204, 204, 1) 100%): de kleur is nog steeds hetzelfde als hierboven, maar nu is de gradiënt volledig ondoorzichtig: 1. Deze ondoorzichtigheid wordt op 100% vanaf de bovenkant bereikt, oftewel: aan de onderkant.

De lichtgrijze gradiënt verandert geleidelijk van vrijwel ondoorzichtig (80% vanaf de bovenkant) in volledig ondoorzichtig (100% vanaf de bovenkant.)

Er zijn vier plaatsen opgegeven, waartussen de doorzichtigheid verandert: tussen 0% en 20%, tussen 20% en 80%, en tussen 80% en 100%. De overgang tussen de verschillende graden van doorzichtigheid 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.

width: calc(100% - 402px);

Hieronder wordt het pseudo-element fixed gepositioneerd. Dat betekent dat het wordt gepositioneerd ten opzichte van het venster van de browser. Ook breedte en dergelijke worden berekend ten opzichte van het venster, niet ten opzichte van <main>, de ouder van het pseudo-element.

<main> heeft bij main een breedte van calc(100% – 412px) gekregen: 412 px smaller dan het venster van de browser. Omdat het pseudo-element alleen de tekst binnen <main> moet afdekken, en niet de thumbnails ernaast, moet het pseudo-element dezelfde breedte krijgen. Met een kleine correctie.

calc(100%) zou de breedte van het venster van de browser opleveren. Dat is weinig interessant. Maar met calc() kun je berekeningen maken met verschillende eenheden. Van de 100% wordt 402 px afgetrokken, waardoor het pseudo-element altijd 402 px smaller is dan het venster van de browser, ongeacht de breedte van het venster.

Van <main> is 412 px van de 100% vensterbreedte afgetrokken. Het pseudo-element is dus 10 px smaller dan <main>. Iets hieronder wordt het ook nog met margin-left: -5px; 5 px naar links gezet. Met deze breedte en de verschuiving van 5 px dekt het pseudo-element, en dus de daarin zittende gradiënt, precies de tekst binnen <main> af.

Althans: niet alleen de tekst wordt afgedekt, maar ook de scrollbalk aan de rechterkant van <main>. Dat is ook de reden dat het pseudo-element 10 px smaller moet zijn en 5 px naar links wordt verplaatst. De scrollbalk is ongeveer 17 px breed en komt buiten <main> te staan. Met deze breedte en verplaatsing naar links staat de linkerkant van het pseudo-element precies gelijk met de linkerkant van <main>, en staat de rechterkant van het pseudo-element precies gelijk met de rechterkant van de scrollbalk bij <main>

Het onderste deel van de scrollbalk wordt dus afgedekt door het pseudo-element, maar dat is nauwelijks een probleem, omdat de gradiënt doorzichtig is. Als de gradiënt binnen de scrollbalk zou vallen, wat makkelijk is te doen, zou je op touchscreens zonder scrollbalk rechts van de gradiënt een lelijke kier van 17 px breed overhouden.

max-width: 870px;

De breedte van het pseudo-element wordt genomen ten opzichte van het venster van de browser. In heel brede vensters zou het pseudo-element, en dus de daarin zittende gradiënt, daardoor breder kunnen worden dan <main>. Een maximumbreedte voorkomt dat.

height: 70px;

Hoogte. Dit bestrijkt ongeveer 3 regels tekst. Omdat de gradiënt hieronder met bottom: 181px; aan de onderkant van <main> wordt neergezet, wordt de hoogte vanaf de onderkant van <main> gemeten.

margin-left: -5px;

Kleine correctie om de linkerkant van de gradiënt gelijk te krijgen met de linkerkant van <main>.

pointer-events: none;

Het pseudo-element met de gradiënt staat over de onderste regels tekst heen. Hierdoor kan deze tekst niet worden geselecteerd om bijvoorbeeld te worden gekopieerd. Dit zorgt ervoor dat een aanraking, muisklik, en dergelijke als het ware door de gradiënt heen naar het onderliggende element gaan: de <main> met de tekst. Hierdoor is ook de tekst onder de gradiënt gewoon te selecteren, kopiëren, enz.

position: fixed;

De gradiënt positioneren ten opzichte van het venster van de browser. Hierdoor scrolt de gradiënt niet mee met de tekst binnen <main>, maar blijft altijd aan de onderkant van <main> staan.

Een met behulp van ::before gemaakt pseudo-element is van zichzelf een inline-element. Daardoor zijn eigenschappen als breedte en hoogte niet te gebruiken. Door het fixed te positioneren verandert het in 'n soort blok-element, waardoor dit soort eigenschappen wel is te gebruiken.

bottom: 181px;

Op 181 vanaf de onderkant van het venster van de browser neerzetten. Bij main is ook <main> op deze afstand vanaf de onderkant van het venster neergezet. Hierdoor staat de gradiënt precies over de onderste regels van de tekst in <main>.

css voor vensters minimaal 900 px breed

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

De opbouw van deze regel staat beschreven bij @media screen and (min-width: 763px) and (min-height: 543px). Er zijn twee verschillen: het browservenster moet minimaal 900 px breed zijn, en de hoogte is onbelangrijk.

Binnen deze media query wordt alleen de lettergrootte van de <h1> iets groter gemaakt voor deze bredere vensters.

h1

Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

h1 {background: #eee; color: black; max-width: 700px; overflow: auto; font-size: 1em; line-height: 30px; text-align: center; margin: 0 auto;}

h1 {width: calc(100% - 402px); max-width: 870px; height: 40px; overflow: auto; line-height: 40px; margin: 0 auto; border: black solid; border-width: 0 1px; position: absolute; left: 200px; right: 200px;}

Alle <h1>'s. Dat is er maar eentje: de belangrijkste kopregel op de pagina.

font-size: 1.6em;

Grotere letter.

Als eenheid wordt de relatieve eenheid em gebruikt, omdat bij gebruik van een absolute eenheid zoals px niet alle browsers de lettergrootte kunnen veranderen. Zoomen kan wel altijd, ongeacht welke eenheid voor de lettergrootte wordt gebruikt.

font-weight: normal;

Een <h1> is van zichzelf vet. In combinatie met de grotere letter hierboven doet dat aan De Telegraaf bij de aankondiging van de Derde Wereldoorlog denken. Ik houd niet van De Telegraaf en ik houd niet van wereldoorlogen, dus niet vet, maar gewoon weergeven.

css voor vensters maximaal 712 px hoog en minimaal 763 px en maximaal 1073 px breed

@media screen and (max-height: 712px) and (min-width: 763px) and (max-width: 1073px)

De opbouw van deze regel staat beschreven bij @media screen and (min-height: 543px) and (max-height: 712px) and (min-width: 763px). Er zijn twee verschillen: er is geen minimumhoogte en er is een maximumbreedte van 1073 px.

In browservensters van deze breedte worden pop-ups getoond. Maar de twee middelste pop-ups onderaan zijn te groot: ze vallen gedeeltelijk buiten het venster van de browser. Daarom worden die zesde en zevende pop-up hier verkleind voor deze vensters.

#blok-link-6 .pop-up-tekst, #blok-link-7 .pop-up-tekst

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

.pop-up-tekst {-moz-hyphens: auto; -ms-hyphens: auto; -webkit-hyphens: auto; hyphens: auto;}

.pop-up-tekst {background: white; color: black; display: block; width: 540px; height: 125px; overflow: auto; font-size: 0.8em; -moz-hyphens: manual; -ms-hyphens: manual; -webkit-hyphens: manual; hyphens: manual; border-bottom: black solid 1px; padding: 3px;}

De elementen met class="pop-up-tekst" binnen een element met id="blok-link-6" of id="blok-link-7". Dit zijn de <span>'s, waarbinnen de tekst boven de afbeelding in de zesde en zevende pop-up staat.

font-size: 1.3em;

Hier iets boven zijn de zesde en zevende pop-up verkleind, zodat ze binnen het venster van de browser passen. Hierdoor is echter ook de tekst verkleind, waardoor deze slecht leesbaar wordt. Daarom wordt de tekst hier weer vergroot.

Als eenheid wordt de relatieve eenheid em gebruikt, omdat bij gebruik van een absolute eenheid zoals px niet alle browsers de lettergrootte kunnen veranderen. Zoomen kan wel altijd, ongeacht welke eenheid voor de lettergrootte wordt gebruikt.

css voor vensters minimaal 1500 px breed en minimaal 712 px hoog

@media screen and (min-width: 1500px) and (min-height: 710px)

De opbouw van deze regel staat beschreven bij @media screen and (min-width: 763px) and (min-height: 543px). Er zijn twee verschillen: het browservenster moet minimaal 1500 px breed zijn, en de hoogte minimaal 710 px.

In brede vensters zouden de thumbnails te ver links en rechts van de tekst komen te staan, wat lelijke open ruimtes oplevert. Dat wordt hier gecorrigeerd.

.blok

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

li {background: #eee; color: black; box-sizing: border-box; width: 100%; float: left; margin-top: -1px; border: black solid 1px; padding: 4px 4px 10px; position: relative;}

.blok {width: 180px; height: 161px; border: none; padding: 0; position: absolute; left: 9px;}

#blok-link-1, #blok-link-2 {top: 41px;}

#blok-link-3, #blok-link-4 {top: 211px;}

#blok-link-5, #blok-link-6 {top: 382px;}

#blok-link-7, #blok-link-8 {top: 553px;}

#blok-link-2, #blok-link-4, #blok-link-6, #blok-link-8 {left: auto; right: 11px;}

De elementen met class="blok". Dit zijn de <li>'s, waarbinnen de thumbnails, pop-ups, en dergelijke staan. Elk in een eigen <li>.

margin-left: -630px; left: 50%;

Om de <li>'s en de daarin zittende thumbnails en dergelijke op de juiste plaats neer te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder, die zelf een positie heeft. Als er geen voorouder met een positie is, zoals hier het geval is, wordt gepositioneerd ten opzichte van het venster van de browser. De <li>'s, en dus de daarin zittende thumbnails, worden horizontaal in het midden van het venster neergezet.

De <li>'s, en de daarin zittende thumbs, zijn 180 px breed. Door ze weer 630 px naar links terug te zetten, staan ze 20 px links van de tekst in <main>.

#blok-link-2, #blok-link-4, #blok-link-6, #blok-link-8

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)

li {background: #eee; color: black; box-sizing: border-box; width: 100%; float: left; margin-top: -1px; border: black solid 1px; padding: 4px 4px 10px; position: relative;}

.blok {width: 180px; height: 161px; border: none; padding: 0; position: absolute; left: 9px;}

.blok {margin-left: -630px; left: 50%;}

#blok-link-1, #blok-link-2 {top: 41px;}

#blok-link-3, #blok-link-4 {top: 211px;}

#blok-link-5, #blok-link-6 {top: 382px;}

#blok-link-7, #blok-link-8 {top: 553px;}

#blok-link-2, #blok-link-4, #blok-link-6, #blok-link-8 {left: auto; right: 11px;}

De elementen met id="blok-link-2", id="blok-link-4", id="blok-link-6" en id="blok-link-8". De tweede, vierde, zesde en achtste <li>. De <li>'s die rechts van de tekst komen te staan.

margin-left: 446px;

Hier iets boven bij .blok {margin-left: -630px; left: 50%;} zijn alle <li>'s met margin-left: -630px; terug naar links gezet. Dat is leuk voor de <li>', met de daarin zittende thumbnails, die links van de tekst moeten komen, maar niet voorde <li>'s die rechts daarvan moeten komen. Daarom worden hier de vier <li>'s die rechts moeten komen naar rechts verplaatst. Met deze marge staan ze 20 px rechts van de tekst.

left: 50%;

Dit staat ook al iets hierboven bij .blok {margin-left: -630px; left: 50%;}. Toch moet het hier worden herhaald.

Voor deze vier <li>'s is eerder bij #blok-link-2, #blok-link-4, #blok-link-6, #blok-link-8 left: auto; opgegeven. In die selectors wordt een id gebruikt. In de selector iets hierboven bij .blok wordt een class gebruikt. En een selector met een id 'wint', heeft meer specificiteit, dan een selector met een class.

Normaal genomen 'wint' lager staande css van hoger staande, maar niet in dit geval. In de selector hier worden ook vier id's gebruikt. Door de left: 50%; hier nog eens te herhalen, gaat het gewicht van de id meespelen en nu 'wint' dit wel van de eerdere selector met id's, omdat het lager in de css staat.

css voor vensters minimaal 763 px breed en minimaal 543 px hoog

De css hieronder is voor elke pagina anders. Daarom staat deze op de site bovenaan de pagina. Het heeft geen zin de externe stylesheet nodeloos groot te maken met css, die slechts op één pagina wordt gebruikt. Omdat het op de site apart staat, is het hier ook apart gezet. Normaal genomen zou je het natuurlijk combineren met de eerder opgegeven css voor deze maat browservensters.

@media screen and (min-width: 763px) and (min-height: 543px)

De opbouw van deze regel staat beschreven bij @media screen and (min-width: 763px) and (min-height: 543px). Hier wordt het tonen van de afbeelding in de pop-up geregeld.