Skip links en inhoudsopgave

Lijst met leesbare en met knoppen uitvouw­bare officiële versie van een verdrag - uitleg

Laatst aangepast: .

Afbeelding 1: de lijst met uitvouwbare teksten

Korte omschrijving

Van artikelen uit een verdrag bestaan een leesbare versie en de officiële tekst. De leesbare versie is altijd zichtbaar, de officiële tekst pas na openen. Knoppen geven de diverse open‑ en sluitmogelijkheden weer.

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, downloadt dan de hele handel (ga terug naar het voorbeeld en kies daar voor downloaden). In de download zit 'n voorbeeld dat wel naadloos aansluit op de uitleg in de download.

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 blauw gekleurd. Alle niet-essentiële code is bruin. (In de inhoudsopgave staat alles in een gewone letter vanwege de leesbaarheid.)

Opmerkingen

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

Alles op deze site is gemaakt op een systeem met Linux (Kubuntu). Daarbij is vooral gebruik gemaakt van Komodo Edit, GIMP en Firefox met extensies. De pdf-bestanden zijn gemaakt met LibreOffice.

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

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

Achterliggend idee

De html bestaat uit een gewone description list, een <dl>. (Vóór html5 heette een description list een definition list.) In de lijst staan de inleiding en de dertig artikelen van de Universele verklaring van de rechten van de mens.

In de <dt> staat het volgnummer van het artikel en een leesbare versie van het officiële artikel uit de Verklaring. In de <dd> staat de officiële tekst van het betreffende artikel uit de Verklaring.

In kleinere browservensters is minder ruimte om de tekst goed neer te zetten, daarom werkt het daarin iets anders dan in grotere vensters. Bij het openen van de pagina ziet de pagina er daardoor iets anders uit in kleinere dan in grotere vensters. Die andere werking voor kleinere vensters (smaller dan 760 px of lager dan 500 px) komt later ter sprake. Hier eerst zoals het er in grotere vensters uitziet.

Bij opening van de pagina is alleen de leesbare versie in de <dt> zichtbaar. De officiële tekst in de <dd> is absoluut links buiten het scherm gepositioneerd met behulp van left: -20000px;. Hierdoor is de <dd> gewoon leesbaar voor schermlezers en dergelijke. Als je de <dd> zou verbergen met iets als display: none; of visibility: hidden; zou een schermlezer de <dd> niet meer voorlezen.

Door de <dd> binnen het venster van de browser te plaatsen, wordt deze zichtbaar. Dit kan op verschillende manieren.

In dit voorbeeld wordt uitgebreid gebruik gemaakt van de 'checkbox hack'. Een <label> bij een <input> kan overal op de pagina worden neergezet, ook een heel eind uit de buurt van de bijbehorende <input>. In dit geval worden <label>'s binnen de <dt> gezet, maar staan de bijbehorende knoppen boven de <dl>. Bij klikken op of aanraken van een <label>, wordt de bijbehorende knop aangevinkt.

Die bijbehorende knop staat boven de <dl>. Door een selector te gebruiken die selecteert op een aangevinkte knop, gevolgd door een bepaalde <dd>, kan die <dd> getoond of verborgen worden, afhankelijk van het aangevinkt zijn van de knop. Daarbij maakt het niets uit dat dat aan‑ en uitvinken gebeurt door een <label>, die een eind van die knop vandaan staat.

In totaal zijn er dertig aankruisvakjes en 31 radioknoppen, die allemaal boven de <dl> staan. Deze worden verborgen met behulp van display: none;. Normaal genomen zouden deze knoppen ook worden bezocht, als de Tab-toets wordt gebruikt. Maar door het gebruik van display: none; worden ze genegeerd door de Tab-toets. Meer over de Tab-toets is te lezen bij Tabindex.

Afbeelding 2: de pagina bij opening

Bij opening van de pagina is de <dt> met de leesbare versie zichtbaar. Links van de tekst is ruimte vrijgehouden voor twee knoppen: een cirkel met daarin het nummer van het artikel, en een knop met een plusteken en schaduw.

De cirkel met het artikelnummer is een gewone <span> met ronde borders en dergelijke.

De knop met het plusteken en de schaduw is een <label>, die is gekoppeld aan een bijbehorende radioknop. Elk artikel heeft een eigen radioknop, dus in totaal zijn er dertig radioknoppen. De <label> staat in de <dt>, de bij de <label> horende radioknop staat boven de <dl>. Hierdoor is de <label> een soort 'afstandsbediening' voor de radioknop geworden: bij klikken op of aanraken van de knop (de <label>), wordt de bijbehorende radioknop geselecteerd.

Als een bepaalde radioknop is geselecteerd, kan de bijbehorende <dd> binnen het venster van de browser worden gepositioneerd. Voor het derde artikel is selector:

#r-3:checked ~ dl dd:nth-of-type(4)

Hierin is #r-3 de vierde radioknop. Als deze is geselecteerd, moet iets worden gedaan met de bijbehorende vierde <dd>. (Omdat de eerste <dd> bij de inleiding hoort, is het volgnummer van de <dd> met het officiële derde artikel '4' en geen '3'. Bij de id van de radioknop kon gewoon een '3' worden gebruikt, maar het volgnummer van de <dd> is helaas niet eenvoudig aan te passen. Om dezelfde reden hoort niet de derde, maar de vierde radioknop bij het derde artikel.)

Als de vierde radioknop is geselecteerd, wordt de <dd> met het derde artikel op het scherm gepositioneerd:

Afbeelding 3: de tekst bij de vierde radioknop is uitgevouwen

De knop met het plusteken is een <label> bij een radioknop. Als een andere knop wordt aangeklikt of aangeraakt, opent de bij die knop horende <dd>. En omdat van een serie radioknoppen er maar eentje kan zijn geselecteerd, sluit de eerder geopende <dd>. Er is dus steeds maar één <dd> zichtbaar.

De <dd> van het derde artikel wordt gewoon over de lagere artikelen gezet, waardoor deze niet meer zijn te lezen. Op de afbeelding is de leesbare versie van artikel 4 verdwenen onder de officiële versie van artikel 3. Door het achtereenvolgens aanklikken of aanraken van alle knoppen, kunnen alle <dd>'s na elkaar zichtbaar worden gemaakt. Dit gebeurt alleen in grotere browservensters. In kleinere vensters zou de tekst van de <dd> niet binnen het venster passen, waardoor je voortdurend omhoog en omlaag zou moeten scrollen.

Afbeelding 4: het sluitkruisje om de tekst verbergen

Ik heb hierboven gejokt. Er zijn geen dertig, maar 31 radioknoppen. Zodra op bovenbeschreven wijze een <dd> zichtbaar is gemaakt, wordt boven de ronde knop met het artikelnummer een <label> gezet. Dat <label> heeft een schaduw en een sluitkruisje. Op de afbeelding is het links te zien. Het hoort bij de 31e radioknop. Bij deze 31e knop hoort geen enkele <dd>. Zodra dit <label> wordt aangeraakt of aangeklikt, sluit daardoor de <dd> die zichtbaar is.

Omdat je meer <label>'s bij één <input> mag gebruiken, is het mogelijk boven elk van de dertig artikelnummers (en de inleiding) een <label> zichtbaar te maken, zodra één <dd> is geopend. Het maakt niet uit welk <label> voor het sluiten wordt gebruikt, want ze zijn allemaal gekoppeld aan dezelfde 31e radioknop.

Er is nog iets anders veranderd: de knop waarmee de <dd> is geopend, is groen geworden, zoals op de afbeelding iets hierboven bij de rechterknop is te zien. In werkelijkheid is niet alleen de kleur van de knop veranderd. De originele grijze knop, die bij openen van de pagina was te zien, was in werkelijkheid een <label> bij een radioknop. Zodra met behulp van dat <label> een radioknop is geselecteerd, wordt over dat <label> een ander <label> gezet. Dat nieuwe <label> is het <label> dat voor de groene knop zorgt. Het hoort bij een aankruisvakje en heeft een groene achtergrondkleur.

Ogenschijnlijk verandert alleen de kleur, in werkelijkheid is de hele originele knop verdwenen onder een nieuwe knop. Of eigenlijk: de <label> die bij de radioknop hoort, is verdwenen onder een <label> die bij een aankruisvakje hoort.

Afbeelding 5
Afbeelding 5: de pagina bij openen in een kleiner browservenster.

In browservensters smaller dan 760 px of lager dan 500 px is dat hele eerste <label> afwezig. Daarin is de <label> met de groene knop gelijk zichtbaar. Omdat de <label> bij de radioknop afwezig is, verandert ook de cirkel met het artikelnummer niet. Oftewel: alle <label>'s bij radioknoppen zijn verborgen in kleinere vensters.

Afgezien hiervan is de werking van de groene knoppen verder vrijwel hetzelfde in grotere en kleinere vensters.

Bij aanraken van of klikken op de <label> met de groene knop, wordt de bijbehorende <dd> zichtbaar gemaakt. Die <dd> stond links buiten het scherm gepositioneerd. Door de absolute positie van de <dd> te veranderen in een statische positie, komt de <dd> op zijn normale plaats te staan:

Afbeelding 6: de tekst wordt niet over, maar tussen de bestaande tekst gezet

Anders dan bij het aanraken of aanklikken van de radioknop, zoals hierboven is beschreven voor grotere browservensters, wordt de <dd> nu niet over onderliggende artikelen gezet, maar ertussen. Als de <dd> van het derde artikel wordt geopend, zoals op de afbeelding het geval is, schuiven artikel 4 en verder omlaag. De leesbare versie blijft dus gewoon zichtbaar.

In kleinere vensters voorkomt dit het voortdurend omhoog en omlaag moeten scrollen, omdat er tekst verdwijnt onder een geopende <dd>. In grotere vensters geeft dit de mogelijkheid om één of meer <dd>'s voortdurend open te houden. Voortdurend, want de <label> met de groene knop hoort bij een aankruisvakje. En er mogen meerdere aankruisvakjes gelijktijdig aangevinkt worden.

Ook hier staat de <input> die bij de <label> hoort weer boven de <dl>. De selector die bij het derde artikel hoort ziet er nu als volgt uit:

#c-3:checked ~ dl dd:nth-of-type(4)

Hierin is #c-3 het vierde aankruisvakje. Als dit is aangevinkt, moet iets worden gedaan met de bijbehorende vierde <dd>. (Omdat de eerste <dd> bij de inleiding hoort, is het volgnummer van de <dd> met het officiële derde artikel '4' en geen '3'. Bij de id van het aankruisvakje kon gewoon een '3' worden gebruikt, maar het volgnummer van de <dd> is helaas niet eenvoudig aan te passen. Om dezelfde reden hoort niet het derde, maar het vierde aankruisvakje bij het derde artikel.)

Als het aankruisvakje is aangevinkt, verandert het uiterlijk van de bijbehorende <label>: de achtergrond wordt rood, het plusteken verandert in een sluitkruisje en de schaduw verandert van plaats.

Door de <label> nogmaals aan te raken of aan te klikken, wordt het vinkje in het aankruisvakje weer weggehaald. En sluit de <dd> weer.

In grotere browservensters verandert er nog iets: het sluitkruisje en de schaduw bij het artikelnummer verdwijnen weer. Sluitkruisje en schaduw horen bij een <label> bij een radioknop. Die radioknop heeft alleen maar zin, als de <dd> is geopend met behulp van een radioknop. Als de <dd> met een aankruisvakje zichtbaar is gemaakt, heeft het geen nut een radioknop voor sluiten te tonen.

De radioknoppen en aankruisvakjes staan boven de <dl>. Door afwisselend een aankruisvakje en een radioknop neer te zetten, kan de volgende selector worden gebruikt:

input[type="checkbox"]:not(:checked) + input[type="radio"]:checked ~ dl span label

Deze selector wordt gebruikt om schaduw aan de knop met het artikelnummer te geven. Dat moet gebeuren als de radioknop is geselecteerd, maar alleen als het gelijk daarvoor staande aankruisvakje niet is aangevinkt. Maar zodra er ergens een radioknop is geselecteerd, zonder dat het daarvoor staande aankruisvakje is aangevinkt, krijgen de knoppen met de artikelnummers weer een sluitkruisje en schaduw.

Het plusteken en sluitkruisje zijn gemaakt met behulp van met ::before en ::after gemaakte pseudo-elementen, die een border krijgen. Dit was de enige manier om in elke browser mooie kruisjes op de juiste plaats te krijgen. Het sluitkruisje is precies hetzelfde als het plusteken, alleen wordt de hele <label> waar de pseudo-elementen bij horen gewoon 45 graden gedraaid. De plaats van de schaduw moet worden aangepast, maar verder zie je dit draaien niet, omdat de <label>'s cirkelvormig zijn.

Sommige mensen gebruiken vanwege een handicap niet de muis of aanraking om naar bepaalde links, tekstvelden, en dergelijke te gaan, maar de Tab-toets. Normaal genomen wordt een <dd> door de Tab-toets overgeslagen. Door aan de <dd> het attribuut tabindex="0" te geven, wordt deze toch bezocht, kan deze toch 'focus' krijgen.

Elke keer als de Tab-toets wordt ingedrukt, wordt een volgende <dd> bezocht. Als een <dd> focus heeft, wordt deze binnen het venster van de browser gepositioneerd. Hierdoor zijn de officiële teksten ook te lezen voor gebruikers van de Tab-toets.

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, 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 inmiddels Blink, inclusief het daar nog in gebruikte -webkit-. Hierdoor is het tot voor kort door Opera gebruikte voorvoegsel -o- niet meer nodig.)

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

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

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 wordt hiervan alleen <main> gebruikt. Dit geeft het begin van de belangrijkste inhoud van de pagina aan.

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.

Dat is allemaal een wonderschoon verhaal, maar in dit voorbeeld worden dus maar liefst 61 <input>'s en 92 bijbehorende <label>'s gebruikt. Normaal genomen worden deze elementen binnen een <form> gebruikt. Hier worden ze gebruikt om het tonen en verbergen van het officiële artikel te regelen.

Dat is nou niet direct semantisch te noemen. En er zijn dan ook nogal wat mensen die vinden dat dit zo niet mag. Persoonlijk zie ik het bezwaar niet. Het is niet semantisch, dat geef ik direct toe. Maar semantiek is geen doel op zichzelf. Het is bedoeld om schermlezers en dergelijke niet in de war te brengen.

Aan elke <input> en elke <label> is hier de WAI-ARIA-code aria-hidden="true" toegevoegd, waardoor ze door schermlezers volledig worden genegeerd. Omdat ze met display: none; worden verborgen, leveren ze ook geen problemen op voor gebruikers van de Tab-toets.

Hoewel <input> en <label> hier niet semantisch worden gebruikt, leveren ze daardoor toch geen problemen op. En zie ik geen reden, waarom je ze niet zou kunnen gebruiken.

WAI-ARIA-codes

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

Er wordt in dit voorbeeld één WAI-ARIA-code gebruikt: aria-hidden.

aria-hidden

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

In dit geval kunnen de <input>'s met radioknoppen en aankruisvakjes nogal verwarrend zijn, als ze worden voorgelezen. Het doel van deze knoppen is volstrekt onduidelijk. Bovendien zijn ze niet nodig voor een schermlezer, want ook de <dd>'s met de officiële teksten zijn gewoon zichtbaar voor een schermlezer. Dat ze links buiten het scherm staan geparkeerd, maakt voor een schermlezer niets uit.

Verbergen van de <dd>'s voor een schermlezer is ook niet echt nodig, want een schermlezer kan snel zo'n <dd> passeren en naar het volgende artikel gaan.

Hetzelfde geldt voor de bij de knoppen horende <label>'s: overbodig en verwarrend voor schermlezers.

Daarom worden de <input>'s en de <label>'s verborgen. Dit gebeurt bij alle <input>'s en <label>'s op dezelfde manier. Door het toevoegen van aria-hidden="true" wordt het element volledig genegeerd door schermlezers. Drie voorbeelden:

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.

Boven de <dl> staan 61 <input>'s: dertig aankruisvakjes en 31 radioknoppen. 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 te vrezen valt dat bezoekers ietwat opgewonden raken, als ze pas na 62 keer de Tab-toets indrukken de eerste zinvolle ontmoeting hebben.

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 <dd>'s, waarin de officiële teksten staan. Bij alle <dd>'s is de html hetzelfde:

<dd tabindex="0">

Door de toevoeging van tabindex="0" kan de <dd> focus krijgen bij gebruik van de Tab-toets, terwijl een <dd> dat normaal genomen niet kan krijgen.

Als elders op de pagina nog een tabindex wordt gebruikt, kan dat dus 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 knoppen binnen de <dl> 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.

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

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

In resoluties groter dan 800x600 is ook in- en uitzoomen en – voor zover de browser dat kan – een kleinere en grotere letter getest. Er is ingezoomd en vergroot tot zover de browser kan, maar niet verder dan 200%.

Er is getest met behulp van muis en toetsenbord, behalve op de iPad, Android en Windows Phone, waar een touchscreen is gebruikt. Op Windows 8.1 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 OSX.

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

Alleen op de hierboven genoemde systemen en browsers is getest. Er is dus niet getest op bijvoorbeeld 'n Blackberry. De kans is (heel erg) groot dat dit voorbeeld niet (volledig) werkt op niet-geteste systemen en apparaten. Om het wel (volledig) werkend te krijgen, zul je vaak (kleine) wijzigingen en/of (kleine) aanvullingen moeten aanbrengen, bijvoorbeeld met JavaScript.

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

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

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

Bekende problemen (en oplossingen)

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

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

Internet Explorer 9

Internet Explorer 9 kent linear-gradient niet. In deze browser is de achtergrond van de lijst effen grijs, zonder verloop.

Als je beslist Internet Explorer 9 ook een verlopende achtergrond wilt geven, kun je op internet zoeken naar een zogenaamde 'polyfill' voor linear-gradient. Een polyfill is een JavaScript dat zorgt dat een bepaalde eigenschap ook werkt in browsers die de eigenschap nog niet ondersteunen. Zo'n polyfill moet heel grondig getest worden, want er is nogal verschil in kwaliteit. Daarom beperk ik het gebruik van polyfills tot wat echt absoluut noodzakelijk is. En wordt er hier geen gebruik van gemaakt.

Een betrouwbare site om naar polyfills te zoeken is Modernizr/wiki/HTML5-Cross-Browser-Polyfills.

Validatie

@-webkit-keyframes bovenin de stylesheet geeft een fout bij het valideren van de css. Omdat bekend is, wat deze fout veroorzaakt, maakt dit verder niets uit.

Wijzigingen

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

:

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.

lijst-107-dl.html: de pagina met het voorbeeld.

De tekst van het verdrag in normaal Nederlands is (met toestemming) overgenomen van www.cmo.nl/vnarena-vo/levensbeschouwing/basisopdrachten/mensenrechten-universeel-of-niet/bron-uvrm-in-normaal-nederlands. Als iemand deze tekst buiten dit voorbeeld wil gebruiken, moet dus eerst contact worden opgenomen met het Centrum voor Mondiaal Onderwijs.

(Het Centrum voor Mondiaal Onderwijs maakt lesmateriaal voor basis- en voortgezet onderwijs voor verschillende vakken of projecten. De onderwerpen: ontwikkelings­samenwerking, oorlog & vrede, mensenrechten, milieu, duurzame ontwikkeling en Europa.)

lijst-107.pdf: de uitleg (aangepast aan de inhoud van de download).

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

107-css-dl:

lijst-107-dl.css: stylesheet voor lijst-107-dl.html.

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

<!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 wordt de breedte van de lijst aangepast aan de grootte van het venster, en ook de manier van openen van de officiële teksten wordt aangepast.

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.

<input type="radio" id="r-d" name="toon" aria-hidden="true">

<input type="checkbox" id="c-i" aria-hidden="true"> <input type="radio" id="r-i" name="toon" aria-hidden="true"> <input type="checkbox" id="c-1" aria-hidden="true"> <input type="radio" id="r-1" name="toon" aria-hidden="true">

(...) tot en met (...)

<input type="checkbox" id="c-30" aria-hidden="true"> <input type="radio" id="r-30" name="toon" aria-hidden="true">

Boven de <dl> staan 31 <input>'s type="radio" (radioknoppen) en dertig <input>'s type="checkbox" (aankruisvakjes). Deze in totaal 61 knoppen hebben geen enkel nut voor schermlezers, maar kunnen wel heel verwarrend zijn. Met behulp van het attribuut aria-hidden="true" worden ze verborgen voor schermlezers. Meer hierover bij WAI-ARIA-codes.

Bij input worden deze <input>'s verborgen met behulp van display: none;. Hierdoor leveren ze ook geen problemen op voor gebruikers van de Tab-toets.

(In principe zouden ze door het gebruik van display: none; ook genegeerd moeten worden door schermlezers, ook zonder aria-hidden="true" te gebruiken. Maar in het verleden gebeurde dat niet altijd. En omdat veel schermlezers peperduur zijn, zal niet iedereen met de nieuwste versie werken. Voor de zekerheid wordt dat dus ook gebruikt.)

Oorspronkelijk stonden de dertig aankruisvakjes boven de 31 radioknoppen, maar door ze om en om neer te zetten kon de selector input[type="checkbox"]:not(:checked) + input[type="radio"]:checked~ dl span label worden gebruikt. Anders hadden dertig regels als checkbox nr 3 + radioknop nr 3 moeten worden gebruikt.

Het zou nog mooier zijn geweest, als de <input>'s gelijk voor de bijbehorende <dd> konden worden neergezet. Dan had een algemene selector als input + dd kunnen worden gebruikt, in plaats van dertig aparte regels. Dat kan echter niet, want dan zou je de <input>'s buiten een <dt> of <dd> neer moeten zetten, maar binnen de <dl>. En dat kan niet. Daarom staan ze helemaal buiten de <dl>.

<label for="r-d" aria-hidden="true"></label>

Bij de gelijk hierboven genoemde 61 <input>'s horen in totaal 92 <label>'s. Ook deze hebben geen enkel nut voor schermlezers, maar kunnen wel voor verwarring zorgen. Daarom worden ook deze verborgen met behulp van het attribuut aria-hidden="true". Meer hierover bij WAI-ARIA-codes.

<dd tabindex="0">

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 <dd> bij gebruik van de Tab-toets genegeerd. Door het attribuut tabindex="0" toe te voegen, worden nu ook de <dd>'s bezocht. Dat maakt het mogelijk in de css de selector dd:focus te gebruiken om daarmee de tekst in de <dd> zichtbaar te maken.

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 blauw gekleurd. Alle niet-essentiële code is bruin. (In de inhoudsopgave staat alles in een gewone letter vanwege de leesbaarheid.)

Omdat deze site nou eenmaal (voornamelijk) op css is gericht, wordt hieronder álle css besproken.

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

/* lijst-107-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;}}

Bij dl is een animatie toegevoegd om een bug in oudere versies van Android browser en, tot mijn verbazing, recente versies van alle browsers met uitzondering van Firefox op iOS op te lossen. Die animatie wordt hier opgegeven.

Op een aantal plaatsen wordt in een selector gebruik gemaakt van het teken ~ (de 'general sibling'-selector) om de <dd> zichtbaar te maken. Genoemde browsers tonen de <dd> echter niet, omdat ze problemen hebben met de ~. Door het toevoegen van een animatie wordt de <dd> toch getoond.

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

Achtergrondkleurtje.

color: black;

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

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

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

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

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

margin: 0; padding: 0;

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

input

Alle <input>'s.

Het tonen en verbergen van de <dd>'s met de officiële teksten wordt geregeld door een serie van 31 radioknoppen en dertig aankruisvakjes. Deze knoppen zelf worden niet gebruikt, ze werken volledig door het aanklikken of aanraken van de bijbehorende <label>'s.

display: none;

Omdat de <input>'s zelf niet worden aangeraakt of aangeklikt, kunnen ze worden verborgen. Dit heeft als bijkomend voordeel dat ze ook ontoegankelijk worden voor de Tab-toets, zodat gebruikers van de Tab-toets niet 61 keer de Tab-toets moeten indrukken, voordat er iets nuttigs gebeurt.

h1

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

background: white;

Witte achtergrond.

color: black;

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

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

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

Ik heb dit 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.

max-width: 799px;

De <dl> krijgt bij dl een maximumbreedte van 800 px. Anders zou je in bredere browservensters hele lange regels tekst krijgen, wat het lezen erg lastig maakt. Daar komt nog een border links van 1 px bij. In totaal is de <dl> dus maximaal 801 px breed.

De <h1> wordt maximaal 799 px breed. Iets hieronder wordt links en rechts een border van 1 px toegevoegd. De totale maximumbreedte wordt hiermee 1 + 799 + 1 = 801 px, net zo breed als de <dl>.

font-size: 1.2em;

Een <h1> heeft standaard een hele grote letter. Hier wordt dat beperkt tot een iets grotere letter dan de rest van de tekst.

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.

text-align: center;

Tekst horizontaal centreren.

margin: 20px auto 0;

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

Boven een kleine marge tussen <h1> en bovenkant van het browservenster. Onderaan geen marge. Links en rechts auto, wat hier hetzelfde betekent als evenveel. Hierdoor staat de <h1> altijd horizontaal gecentreerd, ongeacht de breedte van het venster.

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

border: black solid;

Zwart randje. De breedte wordt gelijk hieronder opgegeven.

border-width: 1px 1px 0;

Kleur en stijl zijn gelijk hierboven al opgegeven. Die zijn overal hetzelfde. Het apart opgeven van kleur, stijl en breedte bespaart in dit geval wat css.

Omdat voor links geen breedte is opgegeven, krijgt links automatisch dezelfde breedte als rechts. Hier staat dus eigenlijk 1px 1px 0 1px in de volgorde boven – rechts – onder – links. Aan alle kanten een border, behalve aan de onderkant.

padding: 5px 0;

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

Kleine ruimte tussen boven- en onderkant van de tekst en de buitenkant van de <h1>.

h1 + p

De <p>'s die in de html na een <h1> komen. Aangezien er maar één <h1> is, is er ook maar één <p> die hieraan voldoet. Het is de <p> met 'De leesbare versie is afkomstig van het Centrum voor Mondiaal Onderwijs.'.

background: white;

Witte achtergrond.

color: black;

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

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

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

Ik heb dit 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.

max-width: 799px;

De <dl> krijgt bij dl een maximumbreedte van 800 px. Anders zou je in bredere browservensters hele lange regels tekst krijgen, wat het lezen erg lastig maakt. Daar komt nog een border links van 1 px bij. In totaal is de <dl> dus maximaal 801 px breed.

De <p> wordt maximaal 799 px breed. Iets hieronder wordt links en rechts een border van 1 px toegevoegd. De totale maximumbreedte wordt hiermee 1 + 799 + 1 = 801 px, net zo breed als de <dl>.

font-size: 0.8em;

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

text-align: center;

Tekst horizontaal centreren.

margin: 0 auto;

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

Boven en onder geen marge. Links en rechts auto, wat hier hetzelfde betekent als evenveel. Hierdoor staat de <p> altijd horizontaal gecentreerd, ongeacht de breedte van het browservenster.

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

border: black solid;

Zwart randje. De breedte wordt gelijk hieronder opgegeven.

border-width: 0 1px;

Kleur en stijl zijn gelijk hierboven al opgegeven. Die zijn overal hetzelfde. Het apart opgeven van kleur, stijl en breedte bespaart in dit geval wat css.

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

padding-bottom: 5px;

Kleine ruimte onder de tekst.

dl

Alle <dl>'s. Dat is er hier maar eentje: de <dl> waar de hele handel in staat (op de gelijk hierboven beschreven <h1> en <p> na).

-webkit-animation: bugfix infinite 1s;

In oudere versies van Android browser en alle browsers op iOS met uitzondering van Firefox zit een bug, waardoor de <dd> met de officiële tekst niet wordt geopend. Met behulp van deze regel wordt de <dd> toch geopend. Meer hierover bij @-webkit-keyframes bugfix.

background: white;

Witte achtergrond.

color: black;

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

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

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

Ik heb dit 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.

max-width: 800px;

Maximumbreedte.

Een blok-element zoals een <dl> wordt normaal genomen even breed als z'n ouder. Dat is hier het blok-element <main>. Omdat bij <main> geen breedte is opgegeven, wordt ook <main> even breed als z'n ouder, het blok-element <body>. Ook geen breedte voor opgegeven dus <body> wordt weer even breed als de ouder daarvan: <html>. <html> is het buitenste element. Omdat ook hier geen breedte is opgegeven, wordt dit even breed als het venster van de browser.

Via deze hele keten wordt <dl> ook even breed als het venster van de browser. In brede vensters zou de tekst in de <dl> hierdoor heel breed worden, waardoor deze lastig te lezen is. Door de maximumbreedte te beperken, wordt dit voorkomen.

margin: 0 auto;

Omdat voor links geen waarde is opgegeven, krijgt links automatisch dezelfde waarde als 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 <dl> staat dus altijd horizontaal gecentreerd, ongeacht de breedte van het venster van de browser.

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

border: black solid;

Zwart randje. De breedte wordt gelijk hieronder opgegeven.

border-width: 0 0 1px 1px;

Kleur en stijl zijn gelijk hierboven al opgegeven. Die zijn overal hetzelfde. Het apart opgeven van kleur, stijl en breedte bespaart in dit geval wat css.

Boven en rechts geen border, onder en links border van 1 px breed.

position: relative;

Om de nakomelingen van de <dl> te kunnen positioneren ten opzichte van de <dl>, moet de <dl> zelf gepositioneerd zijn. Omdat verder niets voor top en dergelijke wordt opgegeven, heeft dit geen enkele invloed op de <dl> zelf.

dt

Alle <dt>'s. Hierbinnen staat de leesbare versie van het Verdrag, die altijd zichtbaar is.

background: #dedede;

Grijze achtergrond. Hieronder krijgen de <dt>'s met behulp van linear-gradient een verlopende achtergrondkleur. Internet Explorer 9 kent dat niet en negeert daarom de regel hieronder. Alle andere browsers kennen dat wel, en omdat de linear-gradient onder deze regel staat, 'wint' die achtergrond van deze gewone achtergrondkleur.

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

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

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

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

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

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

linear-gradient valt in een aantal delen uiteen:

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

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

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

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

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

color: black;

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

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

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

Ik heb dit 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.

min-height: 3em; Afbeelding 7: bij te weinig hoogte is er te weinig ruimte voor de knoppen

Minimumhoogte.

Zonder minimumhoogte is er in <dt>'s met weinig tekst te weinig ruimte voor de knoppen links van de tekst. Op de afbeelding is de minimumhoogte weggelaten, waardoor de knoppen over elkaar heen komen te staan.

margin-top: -1px; Afbeelding 8: dubbele border corrigeren

De <dt>'s 1 px omhoog zetten.

Hieronder krijgen de <dt>'s een border van 1 px breed aan boven- en onderkant. De onderste en bovenste border van 2 <dt>'s komen tegen elkaar aan te staan, waardoor er tussen twee <dt>'s een border van 2 px komt te staan, zoals op de afbeelding is te zien. De rest van de borders is overal 1 px breed, dus dit ziet er niet erg netjes uit.

Door de <dt>'s 1 px naar boven te zetten, komen de twee borders over elkaar heen te staan en is de border tussen de <dt>'s ook nog maar 1 px breed.

border: black solid;

Zwart randje. De breedte wordt gelijk hieronder opgegeven.

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

Kleur en stijl zijn gelijk hierboven al opgegeven. Die zijn overal hetzelfde. Het apart opgeven van kleur, stijl en breedte bespaart in dit geval wat css.

Alleen aan de linkerkant geen border.

padding: 4px;

Kleine afstand tussen buitenkant van en tekst in de <dt>'s.

padding-left: 3px;

Hier gelijk boven is aan alle kanten een padding van 4 px opgegeven. De knoppen links van de tekst staan net iets beter, als de padding daar aan de linkerkant 3 px is.

position: relative;

Om de nakomelingen van de <dt> te kunnen positioneren ten opzichte van de <dt>, moet de <dt> zelf gepositioneerd zijn. Omdat verder niets voor top en dergelijke wordt opgegeven, heeft dit geen enkele invloed op de <dt> zelf.

dt > span:first-of-type

Afbeelding 9: de spans met de knoppen

Dit zijn de <span>'s, waarbinnen de knoppen links van de leesbare versie staan. Op de afbeelding is het het grijze vlak tussen de lijntjes.

Als je alleen naar de <span>'s binnen de <dt> kijkt, met weglating van de <label>'s en dergelijke, is de structuur als volgt:

<dt> <span> <span>Artikelnummer</span> </span> <span>Leesbare versie</span> </dt>

dt: alle <dt>'s. Hierbinnen staan de leesbare versies.

span:first-of-type: het moet de eerste <span> binnen een element zijn. Dat zijn er in bovenstaande code twee. De bovenste <span> is de eerste <span> binnen de <dt>. De tweede <span> staat binnen de bovenste <span> en is daarmee de eerste <span> binnen die bovenste <spa>n. De onderste <span> is de tweede <span> binnen de <dt>, dus die valt gelijk af.

Er zijn twee eerste <span>'s binnen de <dt>, de twee bovenste. Dat is er in dit geval nog eentje te veel.

>: de <span> moet een direct kind van de <dt> zijn. Daaraan voldoen de eerste en de laatste <span>. Maar niet de tweede <span>, want die is een direct kind van de bovenste <spa>n, en niet van de <dt>.

Alles bij elkaar:

dt > span:first-of-type: een <span> die een direct kind is van een <dt>, maar alleen de eerste <span>. Alleen de eerste <span> uit bovenstaande code voldoet aan beide eisen.

width: 74px;

Breedte. Hierbinnen passen de twee knoppen links van de leesbare versie.

border-right: #999 solid 1px;

Rechts donkergrijze border.

position: absolute; top: 0; bottom: 0;

Binnen deze <span> zitten twee knoppen, die verticaal gecentreerd moeten worden. De tekst rechts naast deze knoppen varieert in hoogte. Op een of andere manier moet deze <span> die hoogte volgen, zodat de knoppen verticaal gecentreerd kunnen blijven ten opzichte van de tekst ernaast, ongeacht de hoogte van de tekst.

Bij dt heeft de <dt>, waar deze <span> in zit, een minimumhoogte van 3 em gekregen. Maar dat is de minimumhoogte: de tekst kan prima hoger worden. En als die tekst hoger wordt, wordt ook de <dt> hoger. Maar de <span> met de knoppen niet.

Daarom wordt deze <span> absoluut gepositioneerd. Dat positioneren gebeurt ten opzichte van de eerste voorouder die zelf een positie heeft, en dat is de <dt>. Met top: 0; en bottom: 0; vult de <span> altijd de volle hoogte van de <dt>. Als de knoppen binnen de <span> verticaal gecentreerd worden, staan ze hierdoor automatisch ook verticaal gecentreerd binnen de <dt>, en daarmee ook ten opzichte van de tekst rechts naast de knoppen.

Een <span is een inline-element. Daarbij zijn eigenschappen als breedte niet te gebruiken. Door de <span> absoluut te positioneren, verandert het in een soort blok-element, waardoor breedte en dergelijke wel zijn te gebruiken.

span span

Alle <span>'s die binnen een andere <span> staan. Dat zijn hier alleen de <span>'s met de artikelnummers.

Dit is een wat listige selector. Hier levert het geen problemen op, maar dat zou wel kunnen. Als je bijvoorbeeld een <span> gebruikt om een andere taal in de leesbare versie aan te geven, valt ook die <span> onder deze selector. Als zoiets het geval is, zul je dus iets aan deze selector moeten aanpassen. Bijvoorbeeld veranderen in span:first-child span.

background: white;

Witte achtergrond.

color: black;

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

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

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

Ik heb dit 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: 30px; height: 30px;

Breedte en hoogte 30 px. Oftewel: een vierkant.

line-height: 30px;

Tekst wordt normaal genomen halverwege de regelhoogte gezet. Door de regelhoogte even hoog te maken als de hoogte van de <span>, staat de tekst verticaal in het midden van de <span>.

text-align: center;

Tekst horizontaal centreren.

margin-top: -16px;

Iets hieronder wordt deze <span> met artikelnummers halverwege de hoogte van de buitenste <span> gezet. Door de <span> met artikelnummers weer de halve hoogte van de <span> terug omhoog te plaatsen, staat de <span> en daarmee de knop met artikelnummers in het verticaal midden van de buitenste <span>. En omdat deze buitenste <span> even hoog is als de <dt>, staat de <span> met de artikelnummers daarmee ook in het midden van de <dt>.

De knop is 30 px hoog, dus de helft omhoog zou 15 px zijn. Rechts van deze <span> met artikelnummers staat echter nog een knop, en die heeft aan de onderkant wat schaduw. Daarom wordt die knop geen 15, maar 16 px terug omhoog gezet. Om de knop met artikelnummers op gelijke hoogte met z'n buurvrouw te houden, wordt deze daarom ook 16 px omhoog gezet.

border: #999 solid 1px;

Donkergrijze border.

border-radius: 50%;

Ronde hoeken. Omdat maar één waarde is opgegeven, hebben de hoeken dezelfde hoogte en breedte. Oftewel: ze zijn cirkelvormig.

De hoogte en breedte wordt genomen ten opzichte van het element, waar de border-radius bij hoort. Die <span> heeft hierboven een breedte een hoogte van 30 px gekregen. Omdat de border-radius 50% hiervan is, lopen de ronde hoeken door tot halverwege de <span>, zonder dat er nog een recht stuk border tussen de hoeken zit. Waarmee de hele <span> is omgetoverd in een cirkel.

position: absolute;

Om de <span> met de knop op de goede plaats te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier de buitenste <span>, die voor het grijze blokje met de knoppen links zorgt.

Een <span> is een inline-element. Bij een inline-element zijn eigenschappen als breedte en hoogte niet te gebruiken. Door de <span> absoluut te positioneren, verandert deze in een soort blok-element, waardoor dit soort eigenschappen wel zijn te gebruiken.

top: 50%;

Halverwege de hoogte van de buitenste <span> neerzetten.

Hierboven wordt de <span> met een negatieve margin-top weer een stuk omhoog gezet, waardoor de <span> met de knop altijd verticaal gecentreerd staat.

label:first-of-type

Binnen de <dt>'s zitten drie <label>'s. De eerste van die drie <label>'s zit binnen een <span> en is daarmee de eerste <label> binnen die <span>.

De tweede <label> is de eerste <label> die rechtstreeks binnen de <dt> zit en is daarmee ook een eerste <label>.

De derde <label> is de tweede <label> die rechtstreeks binnen de <dt> zit en is daarmee dus niet de eerste <label>.

Deze selector geldt hierdoor alleen voor de eerste en tweede <label> binnen de <dt>.

De eerste van deze twee <label>'s zorgt voor de schaduw bij en het sluitkruis over het artikelnummer, als in bredere browservensters een officieel artikel is geopend.

De tweede van deze twee <label>'s zorgt voor het plusteken en de schaduw in de rechterknop in bredere vensters, waarmee een <dd> met officiële tekst kan worden geopend.

display: none;

In kleinere browservensters wordt dit <label> helemaal niet gebruikt. In grotere browservensters moet het pas worden getoond, als een officiële tekst is geopend. In beide gevallen moet het dus worden verborgen. Op het moment dat dat nodig is, wordt het dan later in grotere vensters weer zichtbaar gemaakt.

label:nth-of-type(2)

De <label>'s die de tweede <label> zijn. In elke <dt> zitten drie <label>'s. De eerste <label> zit in een <span> binnen de <dt>. Alleen de tweede en derde <label> zitten direct in de <dt>. Waarmee alleen de derde <label> de tweede <label> is, namelijk de tweede <label> direct in de <dt>.

Mogelijk is dit wat verwarrend: drie <label>'s binnen de <dt> en het volgnummer '2' selecteert de derde <label>. Maar bij dit soort volgnummers tellen alleen de elementen die dezelfde ouder hebben mee. Alleen de tweede en derde <label> hebben als gemeenschappelijke ouder de <dt>. De eerste <label> heeft als ouder een <span> en telt hierdoor niet mee.

Waarmee deze selector voor de derde <label> binnen de <d>t's is. Dit is de <label> die voor de groene en rode knop zorgt.

background: palegreen;

Achtergrond lichtgroen.

color: black;

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

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

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

Ik heb dit 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-shadow: 3px 4px 3px black; Afbeelding 10: knop met schaduw

Schaduw aan de knop 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 drie getallen aangepast. De getallen die hier worden gebruikt, leveren de schaduw op, zoals die hierboven bij de afbeelding is te zien: rechtsonder de knop. Hieronder heb ik de waarden iets veranderd, zodat het effect van de verschillende waarden duidelijker is te zien.

Afbeelding 11: schaduw alleen rechts van knop

3px: het eerste getal, hier 3px, geeft de verplaatsing in horizontale richting aan: 3 px naar rechts. Als dit getal 0 zou zijn, zou de linkerkant van de schaduw gelijkvallen met de linkerkant van de <span>, nu is de schaduw 3 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 gebruikt: alleen een horizontale verschuiving van 30 px.

Afbeelding 12: schaduw alleen onder knop

4px: voor het tweede getal geldt precies hetzelfde, maar dan in verticale richting. De bovenkant van de schaduw wordt 4 px naar beneden verplaatst.

Om bijstaande afbeelding te krijgen, zijn de waarden 0 30px 0 gebruikt: alleen een verticale verschuiving van 30 px.

Afbeelding 13: schaduw met alleen vervaging

3px: het derde getal geeft de breedte van de vervaging aan. De schaduw vervaagt hier over een afstand van 3 px. Om bijstaande afbeelding te krijgen, zijn de waarden 0 0 30px 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.

Met een vierde getal kun je de breedte van de schaduw aangeven, maar dat is hier niet gebruikt.

black: de kleur van de schaduw. Als je geen kleur opgeeft, wordt de voorgrondkleur gebruikt. Dat is hier zwart, dus eigenlijk hoef je geen kleur op te geven. Maar in sommige versies van Android browser en UC browser op Android werkt box-shadow niet, als je geen kleur opgeeft.

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: 30px; height: 30px;

Breedte en hoogte 30 px. Oftewel: een vierkant.

margin-top: -16px;

Iets hieronder wordt de <label> halverwege de hoogte van de buitenste <span> gezet. Door de <label> weer de halve hoogte van de <label> terug omhoog te plaatsen, staat de <label> met de knop in het midden van de buitenste <span>. En omdat deze buitenste <span> even hoog is als de <dt>, staat de knop daarmee ook in het midden van de <dt>.

De <label> is 30 px hoog, dus de helft omhoog zou 15 px zijn. Maar de <label> heeft aan de onderkant wat schaduw. Daarom wordt de <label> geen 15, maar 16 px terug omhoog gezet.

border: #999 solid 1px;

Donkergrijze border.

border-radius: 50%;

Ronde hoeken. Omdat maar één waarde is opgegeven, hebben de hoeken dezelfde hoogte en breedte. Oftewel: ze zijn cirkelvormig.

De hoogte en breedte wordt genomen ten opzichte van het element, waar de border-radius bij hoort. Die <label> heeft hierboven een breedte en hoogte van 30 px gekregen. Omdat de border-radius 50% hiervan is, lopen de ronde hoeken door tot halverwege de <label>, zonder dat er nog een recht stuk border tussen de hoeken zit. Waarmee de hele <label> is omgetoverd in een cirkel.

position: absolute;

Om de <label> met de knop op de goede plaats te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier de <span>, die voor het grijze blokje met de knoppen links zorgt.

Een <label> is een inline-element. Daarbij zijn eigenschappen als breedte niet te gebruiken. Door de <label> absoluut te positioneren, verandert het in een soort blok-element, waardoor breedte en dergelijke wel zijn te gebruiken.

top: 50%;

Halverwege de hoogte van de buitenste <span> neerzetten.

Hierboven wordt de <label> met een negatieve margin-top weer een stuk omhoog gezet, waardoor de <label> met de knop altijd verticaal gecentreerd staat.

left: 39px;

Naast de knop met het artikelnummer neerzetten.

label::before

Bij alle <label>'s met behulp van ::before een pseudo-element maken. Dit pseudo-element wordt gebruikt om het plusteken in de knoppen te maken. Door het draaien van de <label> verandert het plusteken in een sluitkruisje.

Afbeelding 14: de eerste helft van sluitkruisje en plus

Dit pseudo-element wordt half zo groot als de bijbehorende <label>. Door het pseudo-element aan twee kanten een border te geven en het op de juiste plaats neer te zetten, ontstaat de helft van het plusteken.

Op de afbeelding is het deel van het plusteken te zien, dat met behulp van dit pseudo-element wordt gemaakt. Op de linkerknop is de <label> een kwartslag gedraaid, waardoor het plusteken in een sluitkruisje is veranderd. Het resterende deel van het plusteken wordt hieronder met behulp van ::after gemaakt.

Dit is een wat omslachtige manier om een simpel plusteken of sluitkruisje te maken. Het bleek echter onmogelijk met gewone tekst of symbolen een enigszins acceptabel plusteken en sluitkruisje te krijgen. Vandaar.

Omdat de meeste <label>'s vroeger of later een knop met een plusteken of sluitkruisje krijgen, kan dat hier in één keer worden opgegeven. Als het niet getoond moet worden, wordt het gewoon verborgen.

content: "";

Ook als er verder niets in het pseudo-element staat, moet deze eigenschap aanwezig zijn. Dat er geen tekst en dergelijke in staat, geef je aan door twee aanhalingstekens achter elkaar te zetten met niets ertussen.

width: 15px; height: 15px; Afbeelding 15: pseudo-element met sluitkruisje en plus zichtbaar gemaakt

De <label> waar dit pseudo-element bij hoort, is 30 px breed en hoog. Het pseudo-element wordt half zo hoog en breed. Op de afbeelding heeft het pseudo-element even een zwarte achtergrond gekregen, waardoor zichtbaar wordt dat het een doodgewoon vierkant is.

border: black solid;

Zwart randje. De breedte wordt gelijk hieronder opgegeven.

border-width: 1px 1px 0 0;

Kleur en stijl zijn gelijk hierboven al opgegeven. Die zijn overal hetzelfde. Het apart opgeven van kleur, stijl en breedte bespaart in dit geval wat css.

Boven en rechts een border, onder en links niet. Op de afbeelding hierboven is te zien, waar die borders komen te staan. Hiermee zijn twee van de vier lijntjes van het kruis klaar.

position: absolute;

Om het pseudo-element 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 <label>, waar dit pseudo-element bij hoort, want alle <label>'s zijn, op verschillende plaatsen in de css, absoluut gepositioneerd.

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

top: 15px;

Op 15 px vanaf de bovenkant van de <label> neerzetten. Hiermee staat het precies in het midden van de <label>. Waardoor de twee borders, die de helft van het plusteken vormen, ook precies in het midden staan.

label::after

Afbeelding 16: de tweede helft van sluitkruisje en plus

Bij alle <label>'s met behulp van ::after een pseudo-element maken. Dit pseudo-element wordt gebruikt om het plusteken in de knoppen te maken. Door het draaien van de <label> verandert het plusteken in een sluitkruisje.

content: ""; width: 15px; height: 15px; border: black solid; border-width: 0 0 1px 1px; position: absolute; top: 0; left: 15px;

Dit is de tweede helft van plusteken en sluitkruisje. Het verhaal is precies hetzelfde als hier iets boven bij label::before. Alleen zit de border hier aan de onderkant en links. En de positie is iets anders dan bij ::before, zodat de borders goed aansluiten op die van het met ::before aangemaakte pseudo-element.

span label::before, span label::after

Voor deze elementen geldt ook de eerder bij label::before en label::after opgegeven css, voor zover die hier niet wordt gewijzigd.

span label: de <label>'s binnen een <spa>n. Binnen elke <dt> zitten drie <label>'s. Alleen de eerste van die drie <label>'s zit binnen een <span>. Het is de <label> die in grotere browservensters voor het sluitkruisje over en de schaduw bij de knop met het artikelnummer zorgt.

::before en ::after: bij de <label>'s zijn hierboven bij label::before en label::after met behulp van ::before en ::after pseudo-elementen gemaakt, waarin onder andere een plusteken en sluitkruisje staan.

Alles bij elkaar:

span label::before, span label::after: de met behulp van ::before en ::after bij <label>'s die binnen een <span> staan gemaakte pseudo-elementen.

border-color: rgba(0, 0, 0, 0.6);

Bij label::before en label::after is een zwarte border opgegeven, die wordt gebruikt om plusteken en sluitkruisje te maken. Als dat sluitkruisje over de artikelnummers wordt gezet, worden deze slecht leesbaar. Daarom wordt voor deze sluitkruisjes de kleur doorzichtig gemaakt.

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

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

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

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

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

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

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

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

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

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

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

In dit voorbeeld is deze achtergrondkleur enigszins doorzichtig: 0.6. Hierdoor zie je de artikelnummers nog redelijk duidelijk door het sluitkruisje heen.

dt span:nth-of-type(2)

De <span> waarbinnen de leesbare versie staat die altijd zichtbaar is.

Als je alleen naar de <span>'s binnen de <dt> kijkt, met weglating van de <label>'s en dergelijke, is de structuur als volgt:

<dt> <span> <span>Artikelnummer</span> </span> <span>Leesbare versie</span> </dt>

dt: alle <dt>'s. Hierbinnen staan de leesbare versies.

span:nth-of-type(2): het moet de tweede <span> binnen een element zijn. De bovenste <span> is de eerste <span> binnen <dt>. De <span> met artikelnummer is de eerste <span> binnen de buitenste <span>. Alleen de onderste <span> is een tweede <span>, namelijk de tweede <span> binnen de <dt>.

Mogelijk is dit wat verwarrend: drie <spans>'s binnen de <dt> en het volgnummer '2' selecteert de derde <span>. Maar bij dit soort volgnummers tellen alleen de elementen die dezelfde ouder hebben mee. Alleen de eerste en derde <span> hebben als gemeenschappelijke ouder de <dt>. De tweede <span> heeft als ouder een andere <span> en telt hierdoor niet mee.

Waarmee deze selector voor de derde <span> binnen de <dt>'s is. Dit is de <span>, waarbinnen de leesbare versie staat die altijd zichtbaar is.

display: inline-block; Afbeelding 17: tekst staat over de knoppen heen

Een <span> is een inline-element. Als daaraan een marge aan de linkerkant wordt gegeven, zoals hieronder gebeurt, is die marge alleen in de eerste regel aanwezig. Waardoor de tekst in tweede en volgende regels over en onder de knoppen links van de tekst komt te staan, zoals op de afbeelding is te zien.

Met inline-block wordt de <span> een soort kruising tussen een inline- en een blok-element. Het blijft een inline-element, maar eigenschappen zoals marge werken hetzelfde als bij een blok-element.

margin-left: 78px;

Links een marge van 78 px. Hiermee komt de <span> met de leesbare versie rechts naast de knoppen te staan.

dd

Alle <dd>'s. Hierbinnen staat de tekst met de officiële versie. De <dd> wordt pas zichtbaar, als een knop wordt aangeklikt of aangeraakt, of als de <dd> focus krijgt door middel van de Tab-toets.

Het grootste deel van de opmaak wordt hier al opgegeven. Hoewel de <dd>'s in eerste instantie onzichtbaar zijn, kunnen ze al gewoon worden opgemaakt.

background: white;

Witte achtergrond.

color: black;

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

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

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

Ik heb dit 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.

border: black solid;

Zwart randje. De breedte wordt gelijk hieronder opgegeven.

border-width: 0 1px 1px;

Kleur en stijl zijn gelijk hierboven al opgegeven. Die zijn overal hetzelfde. Het apart opgeven van kleur, stijl en breedte bespaart in dit geval wat css.

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

Behalve aan de bovenkant overal een border.

margin: 0;

Afhankelijk van de browser kan de <dd> een eind inspringen. Hiermee wordt dat uitgeschakeld.

padding: 5px 5px 30px;

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

Aan alle kanten 5 px afstand tussen tekst in en buitenkant van de <dd>. Alleen aan de onderkant is de afstand 30 px, omdat de officiële tekst binnen de <dd> anders moeilijk is te onderscheiden van de eenvoudige tekst uit de <dt>.

position: absolute;

Om de <dd> 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 <dl>, waarbinnen deze <dd>'s zitten.

left: -20000px;

Links buiten het scherm parkeren, zodat de <dd> onzichtbaar is. Op het moment dat de <dd> getoond moet worden, wordt de positie veranderd en de <dd> op het scherm gezet.

Je zou ook visibility: hidden; of display: none; kunnen gebruiken, maar dan negeren schermlezers de <dd> volledig. Nu is de <dd> gewoon aanwezig, alleen zie je hem niet. Hierdoor wordt hij door schermlezers gewoon voorgelezen.

z-index: 10;

Een z-index werkt alleen in sommige omstandigheden, zoals bij een gepositioneerd element. Hierboven is de <dd> absoluut gepositioneerd, dus dat is geregeld.

In grotere browservensters wordt de <dd> in eerste instantie over de eronder staande teksten neergezet. Die eronder staande teksten horen bij volgende <dt>'s. In de html volgen die op de <dd> die wordt geopend. Daardoor wordt de tekst van de <dd> ónder de tekst van de <dt>'s gezet, waardoor deze niet te zien is.

Door de z-index te verhogen, komt de <dd> bovenaan te staan, ook al komt hij in de html voor de lager zittende <dd>'s.

dd p

Alle paragrafen binnen de <dd>'s.

text-indent: -15px;

Eerste regel 15 px naar links zetten.

margin: 5px 0 0 15px Afbeelding 18: eerste regel in uitgevouwen tekst staat iets naar links

Een <p> heeft van zichzelf een marge aan boven- en onderkant. Hier wordt dat veranderd in een marge van 5 px aan de bovenkant, en geen marge aan de onderkant. Rechts komt ook geen marge en links een marge van 15 px.

Alle tekst binnen de <dd> krijgt links een marge van 15 px.

Maar de eerste regel is hier gelijk boven 15 px naar links gezet. Daardoor krijg je het effect dat de eerste regel van de <p> links buiten de tekst uitsteekt, zoals op de afbeelding is te zien.

dd p:first-of-type

Voor deze elementen geldt ook de eerder bij dd p opgegeven css.

De eerste <p> binnen de <dd>'s. Dit is de <p> waarbinnen 'Artikel' en artikelnummer staan.

font-size: 1.2em;

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

#c-i:checked ~ dl dd:first-of-type

Hiermee wordt één van de <dd>'s met de officiële versie zichtbaar gemaakt. De opmaak van de <dd> is al opgegeven bij dd.

#c-i:checked: als het element met id="c-i" is aangevinkt. Dit is <input> type 'checkbox', een aankruisvakje.

Omdat dit aankruisvakje bij de inleiding hoort, heeft het als 'volgnummer' een 'i' gekregen. De aankruisvakjes staan boven de <dl>, niet erin. Anders zou deze selector niet kunnen werken.

~: 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: #c-i voor de ~ en dl na de ~ hebben beide als ouder <main>.

dl: alle <dl>'s. Dat is er hier maar eentje. Omdat dit volgt op #c-i:checked, wordt de <dl> alleen aangesproken, als het aankruisvakje is aangevinkt.

dd:first-of-type: de eerste <dd> binnen de <dl>. Dit is de <dd> waarin de officiële inleiding, de preambule, staat.

Alles bij elkaar:

#c-i:checked ~ dl dd:first-of-type: de eerste <dd> binnen de <dl> die in de html ergens na het element (aankruisvakje) met id="c-i" staat, maar alleen als dat aankruisvakje is aangevinkt.

input#c-i staat boven de <dl>, maar is bij input verborgen met display: none;. Het aankruisvakje wordt aangestuurd door een <label>, die binnen de <dt> met de 'Inleiding' staat. Het is de tweede <label> binnen de <dt>, die eruit ziet als een groene knop. De css voor dit <label> is opgegeven bij label:nth-of-type(2).

Door het aanraken of aanklikken van deze groene knop, die dus eigenlijk een <label> is, wordt het vinkje geplaatst of weggehaald. Dat de <label> een heel eind van de bijbehorende <input> af staat, maakt geen enkel verschil voor de werking.

Elke <dt> heeft een eigen <label>, dat met behulp van het attribuut for is gekoppeld aan een bijbehorend aankruisvakje. Omdat het aankruisvakjes zijn, kunnen er meerdere tegelijk zijn aangevinkt. Waardoor er meerdere officiële teksten gelijktijdig zichtbaar kunnen zijn.

margin-left: 77px;

Op 78 px vanaf links neerzetten. Met deze marge komt het rechts naast de knoppen te staan, precies uitgelijnd met de <dd> die al zichtbaar is.

position: static;

Bij dd zijn de <dd>'s absoluut gepositioneerd en met left: -20000px; ver buiten het scherm geparkeerd, gezellig ergens bij de buren links in de slaapkamer of zo.

Door de absolute positie te veranderen in een statische positie, heeft left geen effect meer: de <dd> komt nu te staan op de plaats, waar hij normaal genomen, zonder absolute positie, zou komen te staan. Door de absolute positie te veranderen in de (standaard) statische positie, schuiven lagere artikelen automatisch naar beneden, want de <dd> neemt nu zijn normale ruimte in.

Hierdoor kun je het officiële artikel lezen en daarna gewoon doorgaan met de volgende leesbare versie, zonder dat je weer terug omhoog moet scrollen.

(In grotere browservensters gebeurt dat pas na nog 'n klik of aanraking, dat wordt verderop geregeld. Daar is voldoende ruimte om niet steeds heen en weer te moeten scrollen.)

#c-1:checked ~ dl dd:nth-of-type(2)

{margin-left: 77px; position: static;}

(...) tot en met (...)

#c-30:checked ~ dl dd:nth-of-type(31) {margin-left: 77px; position: static;}

#c-1 tot en met #c-30 zijn de <input>'s (aankruisvakjes) die horen bij de eerste tot en met dertigste <dd> met de officiële versie. Ze hebben elk een bijbehorend <label>. Dat <labe>l staat in de <dt> die bij het artikel hoort.

De werking en dergelijke is verder precies hetzelfde als hierboven bij #c-i:checked ~ dl dd:first-of-type. De id verandert wel, omdat elk artikel een eigen aankruisvakje heeft. Verder verandert het volgnummer van de <dd>: dd:nth-of-type(2) tot en met dd:nth-of-type(31). Wat enigszins verwarrend is: bij het eerste artikel hoort de tweede <dd>, omdat voor het eerste artikel nog een <dd> met de inleiding staat. Bij het tweede artikel hoort de derde <dd>, enz. Hier valt helaas niets aan te doen.

#c-i:checked ~ dl dt:first-of-type label:nth-of-type(2)

Voor dit element geldt ook de eerder bij label:nth-of-type(2) opgegeven css, voor zover die hier niet wordt gewijzigd.

Als de <label> met de groene knop is aangeklikt of aangeraakt, wordt een vinkje in de bijbehorende <input> gezet. Daar zie je echter niets van, want die <input> is bij input verborgen met behulp van display: none;. Daarom moet op een andere manier duidelijk worden gemaakt dat een vinkje is geplaatst. Daar zorgt deze selector voor: de groene knop met plusteken verandert in een rode knop met sluitkruisje.

#c-i:checked: als het element met id="c-i" is aangevinkt. Dit element is een <input> type 'checkbox', een aankruisvakje.

Omdat dit aankruisvakje bij de inleiding hoort, heeft het als 'volgnummer' een 'i' gekregen. De aankruisvakjes staan boven de <dl>, niet erin. Anders zou deze selector niet kunnen werken.

~: 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: #c-i en de na ~ staande dl hebben beide als ouder <main>.

dl: alle <dl>'s. Dat is er hier maar eentje. Omdat dit volgt op #c-i:checked, wordt de <dl> alleen aangesproken, als het aankruisvakje is aangevinkt.

dt:first-of-type: de eerste <dt> binnen de <dl>. Dit is de <dt> waarin 'Inleiding' staat.

label:nth-of-type(2): de <label>'s die de tweede <label> zijn. In elke <dt> zitten drie <label>'s. De eerste <label> zit in een <span> binnen de <dt>. Alleen de tweede en derde <label> zitten direct in de <dt>. Waarmee alleen de derde <label> de tweede <label> is, namelijk de tweede <label> direct in de <dt>.

Mogelijk is dit wat verwarrend: drie <label>'s binnen de <dt> en het volgnummer '2' selecteert de derde <label>. Maar bij dit soort volgnummers tellen alleen de elementen die dezelfde ouder hebben mee. Alleen de tweede en derde <label> hebben als gemeenschappelijke ouder de <dt>. De eerste <label> heeft als ouder een <span> en telt hierdoor niet mee.

Waarmee deze selector voor de derde <label> binnen de <dt>'s is. Dit is de <label> die voor de groene en rode knop zorgt.

Alles bij elkaar:

#c-i:checked ~ dl dt:first-of-type label:nth-of-type(2): de tweede <label> binnen de eerste <dt> binnen de <dl> die in de html ergens na het element (aankruisvakje) met id="c-i" staat, maar alleen als dat aankruisvakje is aangevinkt.

Oftewel: doe iets met de <label> die voor de groene knop zorgt, als de bij die groene knop horende <input> is aangevinkt.

background: #fdf;

Achtergrond rood. (Nou ja, rood..., lichtrood. Denk ik, want ik ben wat kleurenzwak.)

box-shadow: -3px 0 2px black;

Schaduw aan de buitenkant van de knop verplaatsen. Een uitgebreide uitleg hoe dit werkt, is te vinden bij box-shadow: 3px 4px 3px black;. Alleen zijn de waarden hier anders, omdat de schaduw nu linksboven de knop komt te staan.

De opgegeven waarden lijken niet te kloppen voor een schaduw linksboven, maar iets hieronder wordt de hele <label> 45 graden gedraaid, en dan kloppen ze wel.

display: block;

In grotere browservensters wordt bij label:nth-of-type(2) dit <label> verborgen met display: none;. Om de <label>, als het bijbehorende aankruisvakje is aangevinkt, zichtbaar te maken, moet display: none; ongedaan worden gemaakt.

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

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

Het plusteken in de groene knop is gemaakt met behulp van twee bij label::before en label::after gemaakte pseudo-elementen. Deze pseudo-elementen draaien vrolijk mee met de <label>, waardoor het plusteken in een sluitkruisje verandert.

#c-1:checked ~ dl dt:nth-of-type(2) label:nth-of-type(2)

{background: #fdf; box-shadow: -3px 0 2px black; display: block; -ms-transform: rotate(45deg); -webkit-transform: rotate(45deg); transform: rotate(45deg);}

(...) tot en met (...)

#c-30:checked ~ dl dt:nth-of-type(31) label:nth-of-type(2) {background: #fdf; box-shadow: -3px 0 2px black; display: block; -ms-transform: rotate(45deg); -webkit-transform: rotate(45deg); transform: rotate(45deg);}

#c-1 tot en met #c-30 zijn de <input>'s (aankruisvakjes) die horen bij de eerste tot en met dertigste <dd> met de officiële tekst. Ze hebben elk een bijbehorend <label>. Dat <label> staat in de <dt> die bij het artikel hoort.

De werking en dergelijke is verder precies hetzelfde als hierboven bij #c-i:checked ~ dl dt:first-of-type label:nth-of-type(2). De id van de <input> verandert wel, omdat elk artikel een eigen aankruisvakje heeft. Verder verandert het volgnummer van de <dt>: dt:nth-of-type(2) tot en met dt:nth-of-type(31). Wat enigszins verwarrend is: bij het eerste artikel hoort de tweede <dt>, omdat voor het eerste artikel nog een <dt> met de inleiding staat. Bij het tweede artikel hoort de derde <dt>, enz. Hier valt helaas niets aan te doen.

dd:focus

Als een <dd> focus heeft.

Binnen de <dd>'s staan de officiële teksten. Door het toevoegen van tabindex="0" aan de <dd>'s, worden deze ook bereikbaar voor gebruikers van de Tab-toets. Als een <dd> focus heeft, kan deze hierdoor zichtbaar worden gemaakt.

right: 0; left: 77px;

De <dd> met de officiële tekst is bij dd met left: -20000px; links buiten het scherm geparkeerd. Nu wordt hij met left: 77px; rechts van de knoppen neergezet.

right: 0; zou eigenlijk niet nodig moeten zijn, maar sommige versies van Android browser en UC browser op Android maken anders één lange regel van de <dd>, waardoor een deel van de tekst rechts buiten het browservenster verdwijnt.

css voor vensters minimaal 760 px breed én minimaal 500 px hoog

@media screen and (min-width: 760px) and (min-height: 500px)

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 760 px breed én minimaal 500 px hoog zijn. In deze vensters wordt de officiële versie bij de eerste aanraking van of klik op de rechterknop met behulp van een radioknop geopend. Zodra een andere officiële tekst wordt geopend, sluit de vorige. Pas bij een tweede klik of aanraking blijft de officiële tekst geopend.

@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: 760px): het venster moet minimaal 760 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: 500px): het venster moet minimaal 500 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: 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 }.

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.

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.

dl

Alle <dl>'s. Dat is er hier maar eentje.

margin-bottom: 300px;

Bij eerste opening zijn de <dd>'s in grotere browservensters absoluut gepositioneerd. <dd>'s met meer tekst kunnen daardoor gedeeltelijk onder het venster verdwijnen. Door een extra marge aan de onderkant wordt dat voorkomen.

span label:first-of-type

De eerste <label>'s die binnen een <span> staan.

Binnen elke <dt> staan drie <label>'s. Alleen de eerste van deze drie <label>'s staat binnen een <span>. Feitelijk is :first-of-type dus niet nodig en zou span label genoeg moeten zijn.

Maar bij label:first-of-type zijn deze <label>'s verborgen met display: none;. En de selector label:first-of-type heeft meer specificiteit, meer 'gewicht', dan de selector span label. Hoewel span label lager in de css staat, 'wint' hierdoor toch label:first-of-type.

Door span label te veranderen in span label:first-of-type krijgt deze selector meer specificiteit, meer 'gewicht', waardoor deze nu 'wint' van de eerdere selector.

Deze <label>'s worden boven de knop met het artikelnummer gezet. Elke <dt> heeft een eigen <label>, maar ze zijn met behulp van het for-attribuut allemaal aan dezelfde radioknop met id="r-d" gekoppeld.

De <label>'s worden hier boven het artikelnummer gezet en werken ook al, alleen zijn ze nu nog onzichtbaar. Bij aanraken van of klikken op dit <label>, wordt de 31e radioknop geselecteerd. Deze hoort bij geen enkel artikel, waardoor de geopende <dd> verdwijnt.

Zodra met een aanraking van of klik op de rechterknop een <dd> met officiële tekst zichtbaar is gemaakt, worden ze zichtbaar. Althans: het sluitkruisje in en de schaduw bij de <label> worden zichtbaar. De <label> zelf was er dus stiekem al die tijd al. De schaduw wordt geregeld bij de eerste selector iets hieronder die begint met input[type="checkbox"]:not(:checked) ..., het sluitkruisje bij de tweede selector iets hieronder die begint met input[type="checkbox"]:not(:checked) ....

display: block;

Bij label:first-of-type zijn deze <label>'s verborgen met display: none;, omdat ze in kleinere browservensters niet worden gebruikt. Nu worden ze voor grotere vensters zichtbaar gemaakt.

width: 30px; height: 30px; margin-top: -16px; border-radius: 50%; position: absolute; top: 50%;

De knop binnen dit <label> moet precies boven de knop met het artikel komen te staan. Daarom is een groot deel van de css voor dit <label> hetzelfde als de css voor de <span> met het artikelnummer. De beschrijving van deze css is bij span span te vinden, maar is weinig interessant: de <label> wordt gewoon exact boven de knop met het artikelnummer gezet.

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

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

Bij label::before en label::after is met behulp van twee pseudo-elementen in alle <label>'s een plusteken gemaakt. Door draaiing kan dat plusteken worden veranderd in een sluitkruisje. In dit <label> is het plusteken niet nodig: alleen het sluitkruisje wordt gebruikt. Daarom kan de <label> gelijk hier al 45 graden worden gedraaid.

span label::before, span label::after

Met behulp van ::before en ::after gemaakte pseudo-elementen bij de <label>'s, die in een <span> staan.

Binnen elke <dt> staan drie <label>'s. Alleen de eerste van deze drie <label>'s staat binnen een <span>. Dit <label> staat boven de knop met het artikelnummer.

display: none;

Bij label::before en label::after is met behulp van twee pseudo-elementen een sluitkruisje gemaakt. Dat sluitkruisje is ook aanwezig in deze <label>'s. Het wordt hier verborgen. Hier iets onder, bij de tweede selector die begint met input[type="checkbox"]:not(:checked)..., wordt het, als dat nodig is, weer zichtbaar gemaakt.

Omdat de <label> verder niet zichtbaar is, merk je niets van dit <label>.

input[type="checkbox"]:not(:checked) + input[type="radio"]:checked ~ dl span label

Even diep adem halen, de hond 'n schop geven en dertig keer opdrukken. Daarna kun je deze selector makkelijk aan. Als je hem in stukjes hakt, valt het best mee.

(Als ik die hond was, zou ik je trouwens na die schop fors bijten. Maar dat terzijde.)

input[type="checkbox"]: alle <inputs> met type="checkbox". Dit zijn de dertig aankruisvakjes boven de <dl>.

:not(:checked): maar alleen als deze :not (niet) :checked (aangevinkt) zijn. De haakjes rondom :checked staan daar, omdat het deel dat bij :not hoort altijd tussen haakjes staat.

Het eerste deel samen:

input[type="checkbox"]:not(:checked): alle aankruisvakjes die niet zijn aangevinkt.

+: het element achter de + moet in de html direct volgen op het element voor de +. In dit geval gaat het om een radioknop die gelijk op een aankruisvakje volgt.

input[type="radio"]:checked: alle <input>'s met type="radio", maar alleen als deze zijn geselecteerd.

De eerste helft samen:

input[type="checkbox"]:not(:checked) + input[type="radio"]:checked: als er een niet-aangevinkt aankruisvakje is dat in de html direct wordt gevolgd door een geselecteerde radioknop. Er zijn dertig aankruisvakjes, die elk worden gevolgd door 'n radioknop. Er zijn dus dertig kansen dat deze combinatie bestaat.

~: 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: het aankruisvakje en de radioknop voor de ~ en dl na de ~ hebben beide als ouder <main>.

dl span label: <label>'s die binnen een <span> in de <dl> staan. In elke <dt> staan drie <label>'s. Alleen de eerste <label> hiervan staat binnen een <span>.

Alles samen:

input[type="checkbox"]:not(:checked) + input[type="radio"]:checked ~ dl span label: als in de html direct na een niet-aangevinkt aankruisvakje een geselecteerde radioknop volgt, doe dan iets met de <label>'s die in een <span> zitten binnen de <dl>.

De bedoeling is dat de artikelnummers worden veranderd in een soort knop met sluitkruisje en schaduw, om duidelijk te maken dat de <dd> met de officiële tekst hiermee weer gesloten kan worden. Dat werkt echter alleen als de <dd> met een radioknop is geopend (wat alleen in grotere browservensters kan).

Als de <dd> is geopend met behulp van het aankruisvakje, heeft het geen nut om dit <label> te tonen, omdat het bij de 31 radioknoppen hoort. Daarom wordt eerst gekeken of het aankruisvakje direct voor deze radioknop niet is aangevinkt. Als dat wel zo is, geldt deze selector niet.

(Oorspronkelijk stonden hiervoor in de css dertig aparte regels met volgnummers, id's, en dergelijke. Door de aankruisvakjes en radioknoppen in de html afwisselend neer te zetten, kon dit worden teruggebracht tot één regel met een + tussen aankruisvakje en radioknop.)

box-shadow: -3px 0 2px black;

Schaduw linksboven aan de buitenkant van de knop tonen. Een uitgebreide uitleg hoe dit werkt, is te vinden bij box-shadow: 3px 4px 3px black;. Alleen zijn de waarden hier anders, omdat de schaduw nu linksboven de knop komt te staan.

De opgegeven waarden lijken niet te kloppen voor een schaduw linksboven, maar iets hierboven bij span label:first-of-type is de hele <label> 45 graden gedraaid, en dan kloppen ze wel.

input[type="checkbox"]:not(:checked) + input[type="radio"]:checked ~ dl span label::before, input[type="checkbox"]:not(:checked) + input[type="radio"]:checked ~ dl span label::after

Dit zijn twee vrijwel dezelfde selectors: de eerste eindigt voor de komma met '::before', de tweede begint na de komma. Dat halveert de ellende alvast.

Deze twee selectors werken precies hetzelfde als input[type="checkbox"]:not(:checked) + input[type="radio"]:checked~ dl span label iets hierboven. Alleen gaat het nu niet om de <label> zelf, maar om de bij label::before en label::after gemaakte pseudo-elementen, die samen voor het sluitkruisje zorgen.

display: block;

De pseudo-elementen zijn iets hierboven bij span label::before, span label::after verborgen met behulp van display: none;. Hier worden ze weer zichtbaar gemaakt.

dt > label:first-of-type

De bij deze selector staande css is vrijwel hetzelfde als die bij label:nth-of-type(2). Maar omdat deze selector specifiek voor grotere browservensters is, staat het toch hier apart. Dan blijft de css voor grotere vensters wat bij elkaar, wat veel overzichtelijker is. Het kost wel wat meer css, maar in dit geval moet dat dan maar.

De eerste <label>'s binnen de <dt>'s, maar het teken > geeft aan dat ze ook nog een direct kind van de <dt> moeten zijn.

Er zitten drie <label>'s binnen de <dt>. De eerste <label> zit binnen een <span>. Deze is wel een eerste <label>, maar geen direct kind van de <dt>. De tweede <label> is een direct kind van de <dt>, en tevens de eerste <label> binnen de <dt>. De derde <label> is weliswaar een direct kind van de <dt>, maar niet de eerste <label>.

Afbeelding 19: de twee knoppen links van de tekst

Deze selector geldt dus alleen voor de tweede <label> binnen de <dt>'s. Dit zijn de <label>'s die bij de radioknoppen horen. Het is op de afbeelding de rechterknop. Bij klikken op of aanraken van deze knop, opent de <dd> met de officiële versie. Tevens verandert de grijze knop in een groene knop, waarmee de <dd> blijvend geopend kan worden, net zoals in kleinere browservensters.

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

Schaduw aan de buitenkant van de knop plaatsen. Een uitgebreide uitleg hoe dit werkt, is te vinden bij box-shadow: 3px 4px 3px black;.

display: block;

Bij label:first-of-type zijn deze <label>'s verborgen, omdat ze in kleinere browservensters niet worden gebruikt. Hier worden ze zichtbaar gemaakt.

width: 30px; height: 30px;

Breedte en hoogte 30 px. Oftewel: een vierkant.

margin-top: -16px;

Iets hieronder wordt de <label> halverwege de hoogte van de <dt> gezet. Door de <label> weer de halve hoogte van de <label> terug omhoog te plaatsen, staat de knop in de <label> verticaal in het midden van de <dt>.

De knop links van deze <label> staat halverwege de buitenste <span> in de <dt>. Die <span> is even hoog als de <dt>. Hierdoor staan beide knoppen even hoog.

De <label> is 30 px hoog, dus de helft omhoog zou 15 px zijn. Vanwege de schaduw die bij sommige knoppen aanwezig is, komt 16 px echter beter uit.

border: #999 solid 1px;

Donkergrijze border.

border-radius: 50%;

Ronde hoeken. Omdat maar één waarde is opgegeven, hebben de hoeken dezelfde hoogte en breedte. Oftewel: ze zijn cirkelvormig.

De hoogte en breedte wordt genomen ten opzichte van het element, waar de border-radius bij hoort. Die <label> heeft hierboven een breedte en hoogte van 30 px gekregen. Omdat de border-radius 50% hiervan is, lopen de ronde hoeken door tot halverwege de <label>, zonder dat er nog een recht stuk border tussen de hoeken is. Waarmee de hele <label> is omgetoverd in een cirkel.

position: absolute;

Om de <label> met de knop op de goede plaats te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier de <dt> met de eenvoudige tekst.

Een <label> is een inline-element. Daarbij zijn eigenschappen als breedte niet te gebruiken. Door de <label> absoluut te positioneren, verandert het in een soort blok-element, waardoor breedte en dergelijke wel zijn te gebruiken.

top: 50%;

Halverwege de hoogte van de <dt> neerzetten.

Hierboven wordt de <label> met een negatieve margin-top weer een stuk omhoog gezet, waardoor de <label> met de knop altijd verticaal gecentreerd staat.

left: 39px;

Rechts van de knop met het artikelnummer neerzetten.

label:nth-of-type(2)

De <label>'s die de tweede <label> zijn. In elke <dt> zitten drie <label>'s. De eerste <label> zit in een <span> binnen de <dt>. Alleen de tweede en derde <label> zitten direct in de <dt>. Waarmee alleen de derde <label> de tweede <label> is, namelijk de tweede <label> direct in de <dt>.

Mogelijk is dit wat verwarrend: drie <label>'s binnen de <dt> en het volgnummer '2' selecteert de derde <label>. Maar bij dit soort volgnummers tellen alleen de elementen die dezelfde ouder hebben mee. Alleen de tweede en derde <label> hebben als gemeenschappelijke ouder de <dt>. De eerste <label> heeft als ouder een <span> en telt hierdoor niet mee.

Waarmee deze selector voor de derde <label> binnen de <dt>'s is. Dit is de <label> die voor de groene en rode knop zorgt.

display: none;

Verbergen. In bredere browservensters verschijnt eerst een <label> met een grijze knop, die bij een radioknop hoort. Pas als deze radioknop is geselecteerd, moet de <label> met de groene knop worden getoond.

#r-i:checked ~ dl dt:first-of-type label:nth-of-type(2)

Hiermee wordt de groene knop bij de inleiding zichtbaar gemaakt.

#r-i:checked: als het element met id="r-i" is geselecteerd. Dit is de radioknop die bij de inleiding hoort.

Omdat deze radioknop bij de inleiding hoort, heeft hij als 'volgnummer' een 'i' gekregen. De radioknoppen staan boven de <dl>, niet erin. Anders zou deze selector niet kunnen werken.

~: 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: #r-i voor de ~ en dl na de ~ hebben beide als ouder <main>.

dl dt:first-of-type: de eerste <dt> binnen de <dl>. Dit is de <dt> waarin de eenvoudige versie van de inleiding, de preambule, staat.

label:nth-of-type(2): de <label>'s die de tweede <label> zijn. In elke <dt> zitten drie <label>'s. De eerste <label> zit in een <span> binnen de <dt>. Alleen de tweede en derde <label> zitten direct in de <dt>. Waarmee alleen de derde <label> de tweede <label> is, namelijk de tweede <label> direct in de <dt>.

Mogelijk is dit wat verwarrend: drie <label>'s binnen de <dt> en het volgnummer '2' selecteert de derde <label>. Maar bij dit soort volgnummers tellen alleen de elementen die dezelfde ouder hebben mee. Alleen de tweede en derde <label> hebben als gemeenschappelijke ouder de <dt>. De eerste <label> heeft als ouder een <span> en telt hierdoor niet mee.

Waarmee deze selector voor de derde <label> binnen de <dt>'s is. Dit is de <label> die voor de groene en rode knop zorgt.

Alles samen:

#r-i:checked ~ dl dt:first-of-type label:nth-of-type(2): doe iets met de tweede <label> binnen de eerste <dt> binnen de <dl>, maar alleen als de bijbehorende radioknop is geselecteerd.

display: block;

Toon het <label> met de groene knop. Dit <label> is iets hierboven bij label:nth-of-type(2) verborgen, nu wordt het zichtbaar gemaakt.

#r-1:checked ~ dl dt:nth-of-type(2) label:nth-of-type(2)

{display: block;}

(...) tot en met (...)

#r-30:checked ~ dl dt:nth-of-type(31) label:nth-of-type(2) {display: block;}

#r-1 tot en met #r-30 zijn de <input>'s (radioknoppen) die horen bij de eerste tot en met dertigste <dd> met de officiële tekst. Ze hebben elk een bijbehorend <label>. Dat <label> staat in de <dt> die bij het artikel hoort.

De werking en dergelijke is verder precies hetzelfde als hierboven bij #r-i:checked ~ dl dt:first-of-type label:nth-of-type(2). De id verandert wel, omdat elk artikel een eigen radioknop heeft. Verder verandert het volgnummer van de <dt>: dt:nth-of-type(2) tot en met dt:nth-of-type(31). Wat enigszins verwarrend is: bij het eerste artikel hoort de tweede <dt>, omdat voor het eerste artikel nog een <dt> met de inleiding staat. Bij het tweede artikel hoort de derde <dt>, enz. Hier valt helaas niets aan te doen.

#r-i:checked ~ dl dd:first-of-type

#r-i:checked: als het element met id="r-i" is geselecteerd. Dit is de radioknop die bij de inleiding hoort.

Omdat deze radioknop bij de inleiding hoort, heeft hij als 'volgnummer' een 'i' gekregen. De radioknoppen staan boven de <dl>, niet erin. Anders zou deze selector niet kunnen werken.

~: 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: #r-i voor de ~ en dl na de ~ hebben beide als ouder <main>.

dd:first-of-type: de eerste <dd> binnen de <dl>. Dit is de <dd> waarin de officiële inleiding, de preambule, staat.

right: 0; left: 77px;

De <dd> met de officiële tekst is bij dd met left: -20000px; links buiten het scherm geparkeerd. Nu wordt hij met left: 77px; rechts van de knoppen neergezet.

right: 0; zou eigenlijk niet nodig moeten zijn, maar sommige versies van Android browser en UC browser op Android maken anders één lange regel van de <dd>, waardoor een deel van de tekst rechts buiten het browservenster verdwijnt.

#r-1:checked ~ dl dd:nth-of-type(2)

{right: 0; left: 77px;}

(...) tot en met (...)

#r-30:checked ~ dl dd:nth-of-type(31) {right: 0; left: 77px;}

#r-1 tot en met #r-30 zijn de <input>'s (radioknoppen) die horen bij de eerste tot en met dertigste <dd> met de officiële tekst. Ze hebben elk een bijbehorend <label>. Dat <label> staat in de <dt> die bij het artikel hoort.

De werking en dergelijke is verder precies hetzelfde als hierboven bij #r-i:checked ~ dl dd:first-of-type. De id van de <input> verandert wel, omdat elk artikel een eigen radioknop heeft. Verder verandert het volgnummer van de <dd>: dd:nth-of-type(2) tot en met dd:nth-of-type(31). Wat enigszins verwarrend is: bij het eerste artikel hoort de tweede <dd>, omdat voor het eerste artikel nog een <dd> met de inleiding staat. Bij het tweede artikel hoort de derde <dd>, enz. Hier valt helaas niets aan te doen.