Skip links en inhoudsopgave

Bij hoveren over, aanraken van of tabben naar één van de thumbnails opent een grotere afbeelding met onderschrift - uitleg

Laatst aangepast: .

Afbeelding 1: geopende foto's in kleinere en grotere vensters

Korte omschrijving

Als je met de cursor over een van de kleine thumbnails hovert, er eentje aanraakt of er met de Tab-toets naartoe gaat, opent rechts een grote afbeelding met bijbehorende tekst.

BELANGRIJK

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

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

Als je dit lastig vindt, kun je bovenaan de pagina de hele handel downloaden. In de download zit 'n voorbeeld dat wel naadloos aansluit op de uitleg in de download.

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

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

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

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

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

Opmerkingen

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

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

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

Achterliggend idee

Aanvulling 11 maart 2020:

In tegenstelling tot wat hieronder (en mogelijk ook nog elders in deze tekst) staat, worden background-images nu meestal gelijk bij openen van de pagina gedownload.

Op Firefox en Safari na zijn vrijwel alle browsers gebaseerd op Blink, de weergave-machine van Chromium. Dit geldt voor bijvoorbeeld Google Chrome, Edge en Opera. En in 2019 heeft Blink dit veranderd: background-images worden nu net als gewone <img>'s gedownload.

Door de manier waarop de afbeeldingen hier worden gebruikt, is het downloaden ook niet te voorkomen door gebruik van het nieuwere attribuut loading = "lazy" bij <img>. Ook de Intersection Observer API biedt geen oplossing. Beide technieken werken alleen, als de afbeeldingen door scrollen binnen het browservenster worden gebracht.

Overigens maakt dat voor de werking van dit voorbeeld verder niets uit. Alleen kun je nu dus eigenlijk net zo goed gewone <img>'s gebruiken in plaats van background-images.

In deze later gemaakte slideshow wordt voortijdig downloaden voorkomen met behulp van JavaScript, maar dat is een veel omslachtiger methode.

Omdat oudere versies van Internet Explorer niet meer worden ondersteund, kon de code voor dit voorbeeld een heel stuk worden verbeterd.

Bij openen van de pagina zie je 34 kleine afbeeldingen, zogenaamde 'thumbnails'. (Een Nederlandse vertaling als 'miniatuur' is nooit echt in gebruik geraakt, dus ik blijf ook het algemeen gebruikte 'thumbnail' gebruiken.) 34 kleine afbeeldingen, dat zou betekenen dat er 34 aanroepen naar de server moeten worden gedaan. Iets wat tamelijk veel tijd kost.

Afbeelding 2: de 34 thumbnails, die in werkelijkheid samen een achtergrond-afbeelding zijn

In werkelijkheid zijn de 34 thumbnails dan ook geen 34 kleine afbeeldingen, maar is het één grote achtergrond-afbeelding, waarop 34 kleinere afbeeldingen zijn gemonteerd. Dat spaart 33 aanroepen naar de server uit. Bijkomend voordeel: de randjes rondom de thumbnails zijn ook al aanwezig, want dat is gewoon de achtergrond van de grote afbeelding, die door een kiertje zichtbaar is. Je wordt dus dubbel genept: geen thumbnails en geen randjes. Zo'n grote afbeelding die bestaat uit een aantal kleinere afbeeldingen, heet een 'sprite'.

De vier kolommen worden gevormd door vier <div>'s die naar links worden gefloat. Elke <div> vult horizontaal een kwart van de achtergrond-afbeelding. Binnen deze vier <div>'s staat weer een serie <div>'s, eentje voor elke zogenaamde thumbnail. Aan deze <div>'s is een counter gekoppeld, die voor de nummering wordt gebruikt. De nummers die je op de thumbnails ziet zitten dus niet in de html, ze worden met behulp van css automatisch gemaakt.

De 34 <div>'s zijn met behulp van :hover en :focus gevoelig gemaakt voor hoveren met de muis, klikken, aanraken en focus. Door het gebruik van tabindex kunnen ook gebruikers van de Tab-toets de grote afbeeldingen openen.

Op iOS is een miniem stukje JavaScript nodig, omdat aanraken daar anders geen effect heeft. Als JavaScript uit staat, heb je nauwelijks iets aan iOS. Dat daar wat JavaScript nodig is, zal dus geen probleem zijn.

Zodra een thumbnail (of eigenlijk: de <div> boven die thumbnail) op een van bovengenoemde manieren wordt benaderd, opent een grotere afbeelding van de thumbnail. Die grotere afbeelding is een achtergrond-afbeelding in een <span> met class="foto". De <span> wordt met behulp van display: none; verborgen, tot de thumbnail wordt benaderd.

Pas als :hover of :focus bij de <div> boven de thumbnail wordt geactiveerd, krijgt de <span> een achtergrond-afbeelding. Daardoor wordt de grotere afbeelding pas gedownload, als de <span> daadwerkelijk wordt getoond. Zou je de achtergrond-afbeelding op de normale manier aan de <span> geven, of als je <img> zou gebruiken in plaats van background-image, dan zouden alle grote afbeeldingen gelijk bij openen van de pagina worden gedownload, ook als je ze verbergt met behulp van display: none;. Nu worden alleen de grote afbeeldingen gedownload, die daadwerkelijk moeten worden getoond.

Bij gebruik van een muis is dit wel wat betrekkelijk, want om bij de binnenste thumbnails te komen zul je over de meer naar buiten gelegen thumbs moeten hoveren. Waardoor de bij die thumbs horende grote afbeeldingen ook worden gedownload, of je die nu wilt zien of niet. Maar hoveren met de muis zal meestal op een desktopcomputer of een laptop (met een touchpad) gebeuren, en daar zal dat downloaden niet zo'n probleem zijn. Op een smartphone en dergelijke kun je gelijk de goede thumbnail aanraken en hoef je niet de buitenste thumbnails te passeren, dus juist daar wordt onnodig downloaden voorkomen. En juist daar is dat belangrijk, omdat de internetverbinding (veel) slechter kan zijn.

Je zou dit ongewild openen bij het van meer naar buiten gelegen thumbnails waarschijnlijk kunnen oplossen door :hover pas na een kleine vertraging (transition-delay of zoiets) te laten werken, maar daarvoor vind ik dit niet belangrijk genoeg.

Op een hogeresolutiescherm is een veel betere kwaliteit afbeelding mogelijk. Daarom zijn van elke grote afbeelding twee stuks aanwezig: eentje van 480 x 360 px voor gewone beeldschermen en eentje van 960 x 720 px voor hogeresolutieschermen. Meer hierover is te lezen bij Hogeresolutieschermen.

In browservensters met een maximale breedte van 480 px wordt de grote afbeelding over de thumbnails gezet: de afbeelding vult zoveel mogelijk van het venster. Als dat nodig is, wordt de afbeelding verkleind, tot hij in het venster past.

In vensters met een breedte tussen 480 en 760 px gebeurt hetzelfde. De afbeelding wordt daarbij vergroot, tot zoveel mogelijk van het venster is gevuld. Als je de browser de afbeelding laat vergroten, levert dat vaak geen mooi resultaat op. Daarom wordt ook hier de afbeelding van 960 x 720 px gebruikt. Deze wordt dan verkleind, tot hij in het venster past. Verkleinen kan een browser wel goed, dus dat is geen probleem.

In vensters smaller dan 760 px wordt de omgeving van de grote afbeelding donker gemaakt, omdat de thumbnails anders nogal storend afleiden van de grote foto.

Bij browservensters breder dan 760 px is er voldoende ruimte om de grote afbeelding niet over, maar naast de thumbnails te zetten. Hier wordt op een gewoon beeldscherm altijd de afbeelding van 480 x 360 gebruikt, en op een hogeresolutiescherm altijd de afbeelding van 960 x 720 px. De afbeelding wordt nu altijd op een grootte van 480 x 360 px weergegeven.

De twee links onderaan de thumbs hebben geen speciale functie of zo. Ze laten alleen zien dat er meer mogelijk is dan alleen thumbnails. Er hadden ook gewoon nog twee staande foto's kunnen staan.

Als iets is verborgen met display: none; of visibility: hidden;, wordt dit genegeerd door schermlezers, zoals blinden die gebruiken. Bij een foto is dat niet zo'n probleem. Maar ook een blinde kan wat hebben aan de onderschriften bij een foto. Daarom worden die teksten niet verborgen met display: none; of visibility: hidden;. Ze worden niet verborgen, maar links buiten het scherm geparkeerd met behulp van left: -20000px;. Als de foto zichtbaar wordt, wordt de bijbehorende tekst binnen het scherm geplaatst en daardoor zichtbaar.

Het maakt voor een schermlezer niets uit, als iets buiten het scherm staat. Op deze manier kun je dus teksten en dergelijke voor een ziende verbergen, tot ze nodig zijn, terwijl een schermlezer ze gewoon kan voorlezen.

De plaats van de onderschriften is een verhaal op zich, omdat de grootte van het venster van de browser niet bekend is. Want daardoor is ook de grootte van de grote afbeelding niet bekend. En ook niet waar de onderkant van de grote afbeelding precies staat, zodat het niet altijd mogelijk is het onderschrift precies op die afbeelding te zetten aan te laten sluiten.

Met behulp van media query's, calc() en dergelijke wordt het onderschrift zo goed mogelijk neergezet, maar dat lukt niet altijd helemaal goed. Wanneer het onderschrift niet helemaal goed aansluit, worden daarom ronde hoekjes en dergelijke gebruikt, zodat het er beter uitziet.

(Als je de onderschriften altijd perfect wilt plaatsen, ontkom je niet aan JavaScript. Daarmee kun je de plaats van de grote afbeelding opvragen en dan aan de hand daarvan het onderschrift neerzetten. Maar deze site gaat nou eenmaal over css en html, en niet over JavaScript.)

Hieronder staan vier willekeurig gekozen voorbeelden van de plaatsing van het onderschrift. In smallere browservensters vullen onderschrift en grote afbeelding de volle breedte van het venster. In iets bredere liggende vensters heeft het onderschrift een andere breedte dan de grote afbeelding. Omdat dat minder mooi is, heeft het onderschrift hier afgeronde hoeken en een kadertje. In de breedste vensters is het onderschrift weer even breed als de grote afbeelding.

Afbeelding 3
Afbeelding 3: de plaatsing van het onderschrift in vier willekeurige vensters van verschillende grootte. In kleinere vensters (linksboven en rechtsonder) staat het onderschrift gelijk onder de grote afbeelding. In niet al te brede liggende vensters (linksonder) staat het onderschrift onder de foto, waarbij de hoeken zijn afgerond. In grotere vensters (rechtsboven) staat het onderschrift iets onder de foto.

Dan zijn er verder nog wat aanpassingen nodig voor problemen, die zich specifiek in bepaalde browsers voordoen. Zo raakt bijvoorbeeld Internet Explorer op een touchscreen nogal van streek, als een verborgen afbeelding zichtbaar moet worden gemaakt. De ziel is alleen met pointer-events: none; weer tot rust te brengen. Dit soort dingen wordt bij de uitleg van de code besproken.

Hogeresolutie­schermen

Vaak wordt dit soort schermen Retina-schermen genoemd, maar Retina is gewoon de merknaam van Apple voor een hogeresolutiescherm.

Er komen steeds meer apparaten met een hogere resolutie, dan op de desktop gebruikelijk is: meer dpi, dots per inch. Van oudsher wordt helaas 'inch' gebruikt als eenheid. Een nieuwere eenheid is dpcm: dots per centimeter. De beste eenheid voor het meten van de resolutie van een computerscherm is dppx: dots per px unit, maar deze wordt nog lang niet overal ondersteund. 1 dppx is even groot als 96 dpi, de standaardresolutie van een gewone desktop monitor (Apple had een iets andere dpi).

Als je meer pixels in een inch stopt, waardoor de pixels dichter op elkaar staan, krijg je fijnere afbeeldingen. Vooral bij ronde lijnen en dergelijke is dit goed te merken. Een ronde lijn die wordt weergegeven met 72 px per inch is grover, dan diezelfde lijn die met 300 px per inch wordt weergegeven.

Een lijn die op een normale desktopmonitor 4 px breed is, zou op zo'n hogeresolutiescherm van 300 dpi maar 1 px breed zijn. Superduidelijk, dat wel, maar zonder vergrootglas niet te zien. Omdat de pixels vier keer zo dicht op elkaar staan. Bestaande sites die vier (of meer) keer zo klein worden weergegeven, als waar ze voor bedoeld zijn, maken alleen opticiens vrolijk.

Althans: je zou die kleinere weergave op een hogeresolutiescherm verwachten. Maar gelukkig wordt dat voorkomen. Apparaten met een hogeresolutiescherm geven een 'valse' resolutie op. Een iPad met een hogeresolutiescherm geeft niet het aantal 'schermpixels' op, maar het aantal 'css-pixels'. En dat is hetzelfde als bij een 'normale' desktopmonitor. Hierdoor ziet een site er op een iPad hetzelfde uit als op een desktopmonitor.

Niet alleen de iPad heeft dit handigheidje, alle hogeresolutieschermen doen dit. Anders zouden ze volstrekt onbruikbaar zijn voor heel veel sites.

Met behulp van media query's kun je testen op onder andere de resolutie. Dit geeft de mogelijkheid naar hogeresolutieschermen afbeeldingen van een hogere kwaliteit te sturen, terwijl je voor gewone beeldschermen afbeeldingen van mindere kwaliteit kunt gebruiken. Dat is belangrijk, omdat die afbeeldingen van hogere kwaliteit (veel) groter zijn in omvang. Door te testen op resolutie, kun je naar een gewoon beeldscherm de veel kleinere afbeeldingen van mindere kwaliteit sturen.

Helaas zijn er nogal wat sites die dit testen op resolutie doen op een manier, die alleen werkt op een iPad/iPhone en in Safari. Door dat te doen werk je mee aan de kans op net zo'n monopolie, als Internet Explorer ooit had. Dat heeft ons jarenlang grote ellende opgeleverd. Het lijkt me niet handig om dat nog eens te gaan herhalen met Apple, temeer niet omdat Apple zich steeds meer als een gediplomeerd patenttrol begint te gedragen en veelbelovende pogingen doet Microsoft van de troon te stoten als meest onsympathiek bedrijf in de ICT.

In de vorige versie van dit voorbeeld zat bij elke thumbnail maar één grote afbeelding. Hier zijn dat er twee: eentje van 480 x 360 px (of 360 x 480 px voor een staande afbeelding) en eentje van 960 x 720 px (of 720 x 960 px voor een staande afbeelding). Beide afbeeldingen zijn volledig hetzelfde, alleen de afmetingen verschillen. De grotere afbeeldingen eindigen allemaal op '-2x.jpg', de kleinere missen het '-2x' en eindigen op '.jpg'.

Het verhaal hieronder is een stuk simpeler, dan het in werkelijkheid is. Dat heeft twee redenen: ik wil het niet te ingewikkeld maken, en ik ben zelf ook geen expert op het gebied van afbeeldingen. Dingen als (lossless) comprimeren, anti-aliasing en subpixels bijvoorbeeld, laat ik buiten beschouwing. Kennis daarvan is ook niet echt nodig voor dit voorbeeld.

Een jpg-afbeelding – het hier gebruikte formaat – is een zogenaamde bitmap-afbeelding. Wat voor het oog mooie, in elkaar overlopende kleuren en soepele rondingen zijn, bestaat in feite helemaal niet. Het zijn kleine blokjes, die alleen maar zo soepel en vervloeiend zijn, omdat ogen makkelijk voor de gek te houden zijn.

Hieronder staat een stukje van een detail van een vleugel op de zevende foto, vijftien keer vergroot. Dat mooie ronde adertje (of hoe dat ook heet bij 'n insect) blijkt opgebouwd te zijn uit 'n verzameling rotsblokken, waar Stonehenge nog iets van kan leren. Maar als je deze rotspartij niet vergroot, blijkt het er op een beeldscherm prima uit te zien. Omdat mensenogen gewoon niet zo goed zijn.

Althans: tot voor niet zo heel lang geleden zag het er overal mooi uit.

Afbeelding 4: bij sterk vergroten van een foto worden de blokjes zichtbaar

Bij een gewoon beeldscherm komt één blokje op de afbeelding hierboven ongeveer overeen met één dot op de monitor. En omdat je oog zo makkelijk kan worden genept, lijkt dit 'n echte weergave van de werkelijkheid en zie je de aparte dots niet.

Een gewoon beeldscherm heeft meestal 96 dots per inch, oftewel 96 dpi. Een Apple-beeldscherm heeft er 72 per inch.

(Op papier is je oog trouwens minder goed voor de gek te houden, daarom zijn voor een afdruk ruwweg vier keer zoveel dots nodig voor een enigszins acceptabele kwaliteit. Daardoor zijn veel afbeeldingen op internet eigenlijk niet af te drukken: ze bevatten gewoon te weinig pixels voor een kwalitatief goede papieren afdruk.)

En toen kwamen er hogeresolutieschermen. Een hogeresolutiescherm heeft meer dpi, meer dots per inch. Meestal is dat nu nog niet meer dan twee keer zoveel als een gewoon beeldscherm, maar er zijn ook nog hogere resoluties.

Als een scherm een resolutie, een dichtheid, van bijvoorbeeld 200 dpi heeft, is dat ongeveer twee keer zoveel als de resolutie van een gewoon beeldscherm. De dots staan twee keer zo dicht op elkaar, waardoor je veel fijnere details kunt weergeven. Maar die arme afbeelding kan dat helemaal niet aan, want die is bedoeld voor een gewoon beeldscherm met 96 dpi. Op zo'n gewoon beeldscherm zit in de afbeelding voor elke dot op het beeldscherm ongeveer 'n eigen pixel in de afbeelding, waardoor beeldscherm en afbeelding goed op elkaar aansluiten en samen een gelukkige relatie hebben. Op een hogeresolutiescherm merkt de tot dan gelukkige afbeelding opeens dat hij te weinig pixels heeft om het hogeresolutiescherm tevreden te stellen, waardoor de relatie tussen afbeelding en beeldscherm opeens een stuk minder goed wordt. En de weergave van de afbeelding slechter.

Je zou dit kunnen oplossen door de afbeelding twee (of bij nog hogere resoluties drie, vier, ...) keer zo klein weer te geven. Dan vallen de pixels binnen de afbeelding weer gelijk met de dots op het beeldscherm. Dat heeft alleen één niet geheel onbelangrijk nadeel: de afbeelding is weliswaar mooi scherp, maar wel twee (drie, vier, ...) keer zo klein, omdat de pixels dichter bij elkaar staan. Want het aantal pixel in de afbeelding neemt niet op wonderbaarlijke wijze toe.

Als alle afbeeldingen opeens twee (drie, vier, ...) keer zo klein zouden worden op een hogeresolutiescherm, zou dat een ramp zijn voor alle bestaande websites. Geen foto zou nog zonder vergrootglas te bekijken zijn. En hogeresolutieschermen zouden niet verkocht worden, want wat heb je aan zo'n fantastisch scherm, als je 'n vergrootglas nodig hebt om iets te kunnen zien.

Daarom is voor een andere oplossing gekozen: de afbeelding wordt even groot weergegeven als op een gewoon beeldscherm. Waardoor bij een resolutie van 200 dpi van het beeldscherm en een resolutie van 96 dpi van de afbeelding gewoon de helft van de pixels ontbreekt. Die bestaat gewoon niet. De browser probeert die missende pixels zelf aan te vullen. Dat gaat nog niet eens zo slecht, maar het eindresultaat is toch merkbaar slechter, dan wanneer de afbeelding zelf een hogere resolutie zou hebben.

De browser zet als het ware tussen elke twee pixel van de afbeelding één nieuwe pixel, waarbij zo goed mogelijk wordt geraden welke kleur die pixel moet hebben. Maar als een detail heel fijn is, zoals iets hieronder op de afbeelding bij de adertjes in de vleugel, kan de browser die heel fijne details niet spontaan fabriceren. Omdat die hele fijne adertjes stomweg ontbreken in de afbeelding.

Je kunt dit probleem oplossen door alleen nog hogeresolutie-afbeeldingen te gebruiken. Maar daar maak je je niet populair mee, want dan downloadt een piepkleine smartphone een joekel van een afbeelding in superkwaliteit, geschikt voor een breedbeeldbeeldscherm .

De oplossing bestaat uit het gebruiken van meerdere afbeeldingen. Dat is iets meer werk, maar ook weer niet zoveel, omdat het om 'n vrij simpele handeling gaat, die je zelfs kunt automatiseren voor 'n hele serie afbeeldingen.

De afbeeldingen die eindigen op -2x.jpg hebben een afmeting van 960 x 720 px. De andere afbeeldingen hebben een afmeting van 480 x 360 px. Afgezien van de afmetingen, zijn ze verder precies hetzelfde. Als je nou een afbeelding van 960 px breed weergeeft op een breedte van 480 px, dan heb je opeens twee keer zoveel px op dezelfde ruimte. Oftewel: ongeveer dezelfde resolutie als een hogeresolutiescherm van 200 dpi.

Afbeelding 5
Afbeelding 5: een detail uit de zevende afbeelding. Links de afbeelding van 480 x 360 px, rechts die van 960 x 720 px. Hoewel de rechterafbeelding zelfs nog iets meer is vergroot dan de linker, zijn de details van de vleugel toch veel beter te zien.

Op de afbeelding hiernaast is het enige verschil tussen de afbeeldingen de afmeting. Als je ze niet zou vergroten of verkleinen, is de rechterafbeelding twee keer zo groot als de linker. De rechterafbeelding is echter wel verkleind, waardoor deze een hogere resolutie, meer dpi, heeft gekregen. Het verschil in kwaliteit is duidelijk zichtbaar: op de linkerafbeelding zijn de fijnere lijntjes binnen de vleugel stomweg afwezig. En wat niet aanwezig is, kan ook niet worden weergegeven door de browser, ook al doet deze nog zo haar best.

Voor een gewoon beeldscherm is de kwaliteit van de linkerafbeelding goed genoeg, want dat beeldscherm is toch niet in staat de fijne lijntjes weer te geven. Een hogeresolutiescherm kan dat wel.

Als je op een hogeresolutiescherm een afbeelding van 960 x 720 px en een afbeelding van 480 x 360 px naast elkaar op een breedte van 480 px bekijkt, zie je duidelijk verschil in kwaliteit. Beide afbeeldingen worden op een grootte van 480x360 px weergegeven, dus de grote afbeelding heeft in hoogte en breedte twee keer zoveel pixel ter beschikking en kan dus beter details weergeven. Die alleen op een hogeresolutiescherm te zien zijn, omdat een gewoon scherm stomweg te grof is om die details weer te geven. Het verschil in kwaliteit komt ruwweg overeen met het verschil in beide afbeeldingen iets hierboven.

Je kunt je afvragen, waarom dan niet altijd de beste kwaliteit afbeelding wordt gebruikt. Dat heeft te maken met de grootte van de bestanden. Elke pixel in een afbeelding is opgebouwd uit drie kleuren: rood, groen en blauw. Elk van die drie kleuren kan 256 mogelijke waarden hebben: van volledig ontbrekend tot volledig aanwezig (knalrood bijvoorbeeld). Samen kunnen deze drie kleuren op 256 x 256 x 256 = 16.777.216 manieren worden gecombineerd. Dat levert 16.777.216 mogelijke kleuren op, ruim voldoende voor het menselijk oog. Van volledig wit (drie keer nul) tot volledig zwart (drie keer 255. 255, want een computer begint bij nul te tellen).

Voor elke pixel in de afbeelding zijn drie bytes nodig: eentje voor elke kleur. Een afbeelding van 100 x 100 px heeft daardoor een bestandsgrootte van 3 x 100 x 100 = 30.000 byte, oftewel 30 kB (kilobyte).

Een afbeelding van 200 x 200 px, twee keer zo groot als een afbeelding van 100 x 100 px, heeft een bestandsgrootte van 3 x 200 x 200 = 120.000 byte, 120 kB. Dat is vier keer zoveel. En dat moet allemaal worden gedownload. Als de monitor toch niet in staat is die kwalitatief betere afbeelding goed weer te geven, is het zinloos die te downloaden en kun je beter de kwaliteit downloaden die bij de monitor past. Dat gaat (veel) sneller en is, als je moet betalen voor de bandbreedte, (veel) goedkoper.

(Als iemand dit nou gaat uitproberen met twee afbeeldingen, dan blijkt bovenstaande niet te kloppen. Door slimme compressiemethoden is een bestand uiteindelijk (veel) kleiner, dan je zou verwachten. Als je bijvoorbeeld een effen blauw vlak van 30 x 30 px hebt, is een regel als 'geef een blauw vlak weer van daar naar daar' veel efficiënter dan het opslaan van 30 x 30 x 3 = 2700 byte.)

In dit voorbeeld wordt met behulp van media query's opgevraagd, wat voor soort scherm de computer heeft. Als dat een hogeresolutiescherm is, wordt de grote afbeelding gedownload (en heel gedetailleerd twee keer verkleind weergegeven op een grootte van 480 x 360 px). Bij een gewoon beeldscherm wordt de kleinere afbeelding van 480 x 360 px gedownload.

Eigenlijk zou ook de achtergrond-afbeelding met de thumbnails op een hogeresolutiescherm twee keer zo groot moeten zijn als op een gewoon scherm. Ik heb dat niet gedaan, omdat het maar om 'n soort voorvertoning van de grote afbeelding gaat. Omdat die thumbnails zo klein zijn, kun je toch geen details zien, hoge resolutie of niet.

Als het browservenster tussen de 480 en 760 px breed is, worden de grote afbeeldingen met behulp van css breder dan 480 px weergegeven. Als je een afbeelding van 480 px gaat vergroten tot een breedte van meer dan 480 px, loop je tegen hetzelfde probleem aan als op een hogeresolutiescherm: er missen pixels. De browser probeert die weer aan te vullen, maar dat gaat niet echt heel goed. Om dit aanvullen te voorkomen, wordt bij een vensterbreedte tussen 480 en 760 px ook de grote afbeelding van 960 px breed gedownload. Die hoeft niet vergroot te worden. De afbeelding moet wel worden verkleind, maar dat gaat veel beter dan vergroten.

Voor smartphones met een venster van bijvoorbeeld slechts 320 px breed zou je nog 'n derde maat foto's kunnen opnemen, zodat daarvoor geen te brede afbeelding van 480 px breed wordt gedownload. Dat zou een kleinere bestandsgrootte opleveren, maar dat verschil in bestandsgrootte is hier zo klein, dat dat volgens mij de moeite van het extra werk niet waard is.

In de (niet al te verre?) toekomst kan de css trouwens 'n heel stuk worden ingekort, omdat je dan gelijk bij background-image zelf kunt opgeven, welke afbeelding moet worden gedownload. Hiervoor zijn dan geen media query's meer nodig. In één van de ontwerpspecificaties voor css wordt hiervoor image-set gebruikt, maar dit wordt helaas nog nauwelijks ondersteund door browsers.

Als je beslist image-set al wilt gebruiken, kun je op internet zoeken naar een zogenaamde 'polyfill' voor image-set. 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.

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-min-device-pixel-ratio en hyphens 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-min-device-pixel-ratio

Hiervoor geldt niet alles, wat hierboven is geschreven. Dit is een door Apple bedachte eigenschap, die in geen enkele specificatie voorkomt en ook niet door andere browsers wordt ondersteund of ondersteund gaat worden. Het wordt gebruikt om in media query's de resolutiedichtheid op te vragen. Andere browsers gebruiken hiervoor het wel in de specificatie voorkomende min-resolution.

Op dit moment moet je daarom nog schrijven:

(-webkit-min-device-pixel-ratio: ...), (resolution: ...)

In de toekomst kun je – als Apple zich ook eindelijk aan de standaard gaat houden – volstaan met:

(resolution: ...)

hyphens

Op dit moment moet je nog het volgende schrijven:

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

In de toekomst kun je volstaan met:

{hyphens: ...;}

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.

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.

Normaal genomen wordt focus aangegeven door een kadertje rondom het element dat focus heeft. In het algemeen is het een bijzonder slecht idee om dat kadertje te verwijderen, omdat gebruikers van de Tab-toets dan niet meer kunnen zien, waar ze zijn aangekomen met de Tab-toets. Als je het kadertje verwijdert met behulp van css, moet je het daarom normaal genomen vervangen door iets anders. In dit geval heb ik het gewoon laten staan. Je zou het ook kunnen weghalen, want als met de Tab-toets een bepaalde thumbnail (eigenlijk een daarboven staande <div>) wordt bereikt, opent de bijbehorende grote afbeelding. Waardoor je dus prima kunt zien waar je bent.

In een vorige versie was dit kadertje weggehaald, maar de voornaamste reden daarvoor was het afschuwelijke onwijs dikke knalblauwe kadertje, waarmee Opera focus meende te moeten verontreinigen. Alle andere browsers hebben bescheidener kadertjes.

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 attribuut tabindex: <div tabindex="3">. Deze <div> zal nu als derde worden bezocht, ook al krijgt een simpele <div> normaal genomen nooit bezoek van de Tab-toets.

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

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 <div>'s, die boven de kleine afbeeldingen staan. Dit is de html van de <div> boven de eerste kleine afbeelding:

<div id="thumb-1" tabindex="0">

Door de toevoeging van tabindex="0" kan de <div> focus krijgen bij gebruik van de Tab-toets, terwijl een <div> 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 <div>'s boven de thumbnails worden bezocht. Precies zoals de bedoeling is. Maar als je wel een tabindex elders op de pagina gebruikt, moet je in zoveel mogelijk browsers op zoveel mogelijk systemen de volgorde bij gebruik van de Tab-toets controleren.

tabindex="..."

Op de plaats van de puntjes moet een positief getal worden ingevuld: het volgnummer. Positieve tabindexen worden hier niet gebruikt.

Muis, toetsenbord, touchpad en touchscreen

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

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

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

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

:hover

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

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

In dit voorbeeld verschijnt een grote afbeelding met onderschrift bij hoveren over een van de thumbnails.

:focus

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

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

Er is echter 'n tweede manier om naar links, invoervelden, en dergelijke te gaan: met behulp van de Tab-toets (sommige browsers gebruiken andere toetsen, maar het principe is hetzelfde). Met behulp van de Tab-toets kun je naar links, invoervelden, en dergelijke 'springen'. (Over het gebruik van de Tab-toets staat meer bij Tabindex.)

Waar je staat, wordt door alle browsers aangegeven met een of ander kadertje. De link en dergelijke met het kadertje eromheen 'heeft focus'. Dat wil zeggen dat je die link volgt, als je op de Enter-toets drukt, of dat je in dat veld tekst kunt gaan invoeren, enz.

Focus wordt hier gebruikt om de <div> boven de thumbnail bereikbaar te maken voor de Tab-toets. Daarvoor heeft elke <div> als attribuut tabindex="0" gekregen, omdat een <div> anders geen focus kan krijgen.

Het kadertje dat de focus aangeeft, moet nooit zonder meer worden weggehaald. Gebruikers van de Tab-toets hebben dan geen idee meer, waar ze zijn. Maar in dit voorbeeld zou het kadertje veilig kunnen worden weggehaald, omdat de grote afbeelding al aangeeft, welke <div> focus heeft.

Om :hover en :focus werkend te krijgen op iOS, is een minieme hoeveelheid JavaScript nodig. Meer daarover bij JavaScript.

De code aanpassen aan je eigen ontwerp

Toegankelijkheid en zoekmachines

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

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

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

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

Enkele tips die helpen bij toegankelijkheid:

Specifiek voor dit voorbeeld

Getest in

Laatst gecontroleerd op 18 oktober 2015.

Onder dit kopje staat alleen maar, hoe en waarin is getest. Eventuele problemen, ook die met betrekking tot zoomen en lettergroottes, staan hieronder bij Bekende problemen (en oplossingen). Het is belangrijk dat 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 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.

Wegvallen van delen van de grote afbeelding in exotische venstergroottes

Als een browservenster breder is dan 760 px én lager dan 450 px, vallen een deel van de grote afbeelding en/of het onderschrift weg. Dit is nogal een exotische maat, waarvan ik niet eens weet, of die wel bestaat. Maar voor de volledigheid vermeld ik het hier.

Dit doet zich alleen in landschapsstand voor. Draaien naar portretstand lost het probleem op.

Zoomen

Op de desktop is inzoomen (vergroten) geen probleem, maar op een touchscreen is het niet altijd een onverdeeld succes.

Android 4.4.2 (tablets)

Zoomen levert geen problemen op. Als de grote afbeelding en/of het onderschrift niet meer in het browservenster passen, zijn ze via scrollen volledig te bekijken.

Android 4.1.2 (smartphone)

Firefox: bij inzoomen blijft de grote afbeelding in het browservenster passen: de afbeelding wordt niet vergroot. Het onderschrift wordt wel vergroot. Hierdoor wordt de afbeelding feitelijk steeds kleiner bij inzoomen. In landschapsstand valt het onderschrift niet weg, in portretstand bij voldoende inzoomen wel.

Chrome: grote afbeelding en onderschrift worden vergroot en kunnen dus buiten het venster komen te staan. Door scrollen zijn tekst en afbeelding volledig te bekijken.

UC browser en Android browser: bij inzoomen blijft de grote afbeelding in het browservenster passen: de afbeelding wordt niet vergroot. Het onderschrift wordt wel vergroot. Hierdoor wordt de afbeelding feitelijk steeds kleiner bij inzoomen. Omdat het onderschrift altijd binnen het venster blijft staan, kan de grote afbeelding érg klein worden.

iPad

Bij voldoende zoomen kunnen zowel grote afbeelding als onderschrift buiten het browservenster komen te staan. Als je je vinger op de bijbehorende thumbnail houdt, kún je scrollen. Maar omdat afbeelding en/of onderschrift gedeeltelijk buiten het venster staan, kun je niet alles van de afbeelding en/of het onderschrift zien én gelijktijdig de thumbnail aanraken.

Bij zoomen zijn dus niet de hele afbeelding en/of onderschrift te zien.

Windows Phone

Zelfde als gelijk hierboven voor de iPad. Maar omdat het hier om een veel kleiner scherm gaat, zie je nu haast niets van de grote afbeelding, omdat al snel het grootste deel buiten het browservenster staat.

Windows 8 touchscreen

Grote afbeelding en onderschrift kunnen beide buiten het browservenster komen te staan. Scrollen door aanraking kan niet, maar scrollen met de pijltjestoetsen werkt prima, zodat de hele afbeelding en onderschrift te zien zijn.

UC browser op Android

  • UC browser op Android kent calc() en de eenheid vw niet. In bepaalde maten browservensters is de grote afbeelding breder dan het onderschrift. Het onderschrift hoort dan horizontaal gecentreerd te worden. In deze browser wordt het onderschrift ook in die situaties helemaal links in het venster geplaatst.
  • UC browser op Android onderstreept links niet. Ook a {text-decoration: underline;} werkt niet.

    De twee links onderaan de thumbs staan in een span met class="link". Wat wel werkt: .link a {text-decoration: underline;}. Ik heb dat niet gedaan, omdat dat liederlijk lelijk is.

Android browser

Versies ouder dan 4.4 kennen de eenheid vw niet. Hetzelfde geldt voor calc(). De exacte versie is niet te zeggen, omdat fabrikanten Android browser kunnen aanpassen. In bepaalde maten browservensters is de grote afbeelding breder dan het onderschrift. Het onderschrift hoort dan horizontaal gecentreerd te worden. In versies van deze browser die vw en/of calc() niet ondersteunen, wordt het onderschrift ook in die situaties helemaal links in het venster geplaatst.

Valideren

De validator van w3c herkent pointer-events en calc() nog niet. Wat dus twee foutmeldingen oplevert. Ook -webkit-min-device-pixel wordt niet herkend, maar dit zal ook in de toekomst niet worden herkend, omdat dit een eigen brouwsel van Apple is.

Omdat de reden van de foutmeldingen duidelijk is, zijn ze hier verder geen probleem.

Wijzigingen

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

26 december 2007:

Nieuw opgenomen.

:

De code is volledig herschreven. De zichtbare gevolgen daarvan:

18 oktober 2015

11 maart 2020:

Ook background-images worden nu meestal, net als gewone <img>’s, gelijk bij openen van de pagina gedownload. Bovenaan Achterliggend idee is een korte correctie toegevoegd.

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.

afbeelding-016-dl.html: de pagina met het voorbeeld.

afbeelding-016.pdf: deze uitleg (aangepast aan de inhoud van de download).

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

016-css-dl:

afbeelding-016-dl.css: stylesheet voor afbeelding-016-dl.html.

016-files-dl:

afbeelding-016-link-dl.html: hulppagina achter links.

016-pics:

afbeeldingen.

De afbeeldingen die eindigen op '-2x.jpg' hebben een dubbele breedte en hoogte. Ze zijn bedoeld voor hogeresolutieschermen en browservensters met een breedte tussen 480 en 760 px.

De afbeeldingen zijn afkomstig van PD Photo.org.

De afbeeldingen zijn binnen het publiek domein geplaatst, zoals omschreven op creativecommons.org/publicdomain/zero/1.0/deed.nl.

HTML

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

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

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

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

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

Als je dit lastig vindt, kun je bovenaan de pagina de hele handel downloaden. In de download zit 'n voorbeeld dat wel naadloos aansluit op de uitleg in de download.

<!DOCTYPE html>

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

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

Gebruik het volledige doctype, inclusief de eventuele url, anders werkt het niet goed.

Het hier gebruikte doctype is dat van html5. Dit kan zonder enig probleem worden gebruikt: het werkt zelfs in Internet Explorer 6.

<html lang="nl">

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

<meta charset="utf-8">

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

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

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

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

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

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

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

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

Nieuwe sites of pagina's kunnen echter wel rekening houden met de veel kleinere vensters van mobiele apparaten. Op deze pagina bijvoorbeeld passen de positie en de maten van de grote afbeeldingen en de onderschriften zich aan de breedte en hoogte van het venster aan: nooit breder of hoger dan het venster.

Maar die stomme mobiele browser weet dat niet, dus die gaat ervan uit dat ook deze pagina 980 px breed is, en verkleint die dan. Dat is ongeveer even behulpzaam als de gedienstige kelner die behulpzaam de stoel naar achteren trekt, net als jij wilt gaan zitten.

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

Een iPad in portretstand bijvoorbeeld is 768 px breed. De kreet width=device-width zegt tegen de mobiele browser dat de breedte van de weer te geven pagina gelijk is aan de breedte van het apparaat. Voor een iPad in portretstand dus 768 px.

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

<div id="thumb-1" tabindex="0">

Voor elke grote afbeelding is een <div> aanwezig, waarbinnen <span>'s voor de grote afbeelding en het onderschrift zitten. Om deze <div>'s toegankelijk te maken voor gebruikers van de Tab-toets, is tabindex="0" toegevoegd. Meer daarover kun je vinden bij Tabindex.

CSS

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

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

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

Als je dit lastig vindt, kun je bovenaan de pagina de hele handel downloaden. In de download zit 'n voorbeeld dat wel naadloos aansluit op de uitleg in de download.

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

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

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

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

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

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

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

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

Dat comprimeren kun je met de hand doen, maar er bestaan ook hulpmiddelen voor. Als je op internet zoekt naar 'css' en 'compress' of 'comprimeren', vind je tal van sites, waar je dat automatisch kunt laten doen.

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

css voor alle vensters

/* afbeelding-016-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.

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.

counter-reset: volgnummer;

Voor het nummeren van de thumbnails wordt een zogenaamde css-counter, een teller, gebruikt. Bij elke <div> boven een thumbnail wordt die teller met 1 verhoogd, waarna dat nummer op de thumb wordt gezet.

Met behulp van counter-reset wordt de beginstand van de teller opgegeven. Als nog geen teller met de hier gebruikte naam bestaat, zoals hier het geval is, wordt deze aangemaakt. Dat gebeurt hier: de teller krijgt de fantastisch creatieve naam 'volgnummer'.

Je kunt ook een beginwaarde aangeven. Omdat hier alleen een naam en geen beginwaarde is opgegeven, begint de teller bij 0. Bij de eerste <div> wordt die dan verhoogd tot 1, waarna die 1 wordt getoond. Bij de tweede <div> wordt het 2, enz.

background: #002;

Donkerblauwe achtergrondkleur.

Normaal genomen zou ik bij een achtergrondkleur ook altijd color opgeven. Dat bepaalt de voorgrondkleur, waaronder de tekstkleur. 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.

In dit geval doe ik dat niet, omdat op deze pagina alleen tekst staat in elementen die zelf al een achtergrond- en voorgrondkleur krijgen. Waarmee het risico op te weinig contrast dus niet bestaat op deze pagina.

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

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

font-size: 110%;

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

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.

margin: 0; padding: 0;

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

#inleiding

Het element met id="inleiding". De <div> waarin de tekst staat, die wordt getoond in browservensters met een minimale breedte van 760 px.

display: none;

Verbergen. In vensters met een minimale breedte van 760 px wordt hij later weer zichtbaar gemaakt.

#thumbs

Het element met id="thumbs". De <div> waar, op div#inleiding na, alles in zit.

background: url(../016-pics/thumbnails.jpg);

Achtergrond-afbeelding met de thumbnails.

In een vorige versie, waarin oudere versies van Internet Explorer nog werden ondersteund, was er niet één achtergrond-afbeelding, maar waren er 34 afzonderlijke kleine thumbnails. Waarvoor 34 aanroepen naar de server nodig waren.

Door de thumbnails te monteren op één grote achtergrond-afbeelding, is nu nog maar één aanroep naar de server nodig, wat veel sneller werkt. Bovendien zijn de randjes rondom de thumbnails ook al aanwezig: dat is gewoon de achtergrondkleur van de achtergrond-afbeelding, die zichtbaar is door de kiertjes tussen thumbnails.

width: 245px; height: 450px; Afbeelding 6: zonder hoogte en breedte is de achtergrond effen zwart

Breedte en hoogte van deze <div> zijn precies hetzelfde als de afmetingen van de achtergrond-afbeelding.

Normaal genomen wordt een blok-element zoals een <div> even breed als z'n ouder. Dat is hier <body>. En normaal genomen wordt een <div> automatisch precies hoog genoeg, om de inhoud ervan weer te kunnen geven. Soms is dat is echter niet zo, bijvoorbeeld als die inhoud wordt gefloat.

Binnen div#thumbs staan vier <div>'s, voor elke kolom met thumbnails eentje. Deze vier <div>'s worden naar links gefloat. Hierdoor krijgt div#thumbs geen breedte en hoogte. En zonder breedte en hoogte zou je niets van de achtergrond-afbeelding zien,

want een achtergrond-afbeelding heeft zelf geen hoogte en breedte. Die vult alleen maar het element waar de achtergrond-afbeelding in zit.

Op de afbeelding zijn breedte en hoogte weggelaten. Alles werkt nog steeds, de nummering van de thumbnails is aanwezig, enz. Maar omdat #thumbs geen breedte en hoogte heeft, ontbreekt de achtergrond-afbeelding. Wat het mogelijk 'n tikkeltje lastig maakt om te kiezen, welke grote afbeelding je wilt zien. Daarom worden breedte en hoogte in dit geval handmatig opgegeven. Dan heeft de <div> een breedte en hoogte en kan de achtergrond-afbeelding worden getoond.

margin: 6px 0 0 6px;

Kleine afstand tot de zijkant van het browservenster aan boven- en linkerkant.

#thumbs > div

De <div>'s binnen het element met id="thumbs". Dit zijn de vier <div>'s waarbinnen de vier kolommen boven de thumbnails staan.

Er staan meer <div>'s binnen #thumbs. Boven elke thumbnail staat ook weer een eigen <div>. Deze css heeft alleen betrekking op de vier <div>'s met de kolommen. Daarom wordt aan de selector het teken > toegevoegd. Nu geldt deze regel alleen voor <div>'s die een direct kind van #thumbs zijn, niet voor dieper geneste <div>'s.

Onderstaande (sterk ingekorte) html hoort bij de vierde kolom:

<div id="thumbs"> <div> <div id="thumb-27" tabindex="0"> (...) <div id="thumb-34" tabindex="0"> (...) </div> </div>

De css bij deze selector geldt wel voor de <div> die gelijk onder <div id="thumbs"> staat, want dat is een direct kind van div#thumbs. Maar niet voor div#thumb-27 en div#thumb-34, want die zijn geen directe kinderen van div#thumbs.

float: left;

Zo hoog mogelijk en zo ver mogelijk naar links neerzetten.

Normaal genomen wordt een <div> op een nieuwe regel gezet. Daardoor zouden de vier <div>'s met kolommen niet onder, maar naast elkaar komen te staan. Door ze naar links te floaten, komen ze naast elkaar te staan.

width: 60px;

Met deze breedte zijn ze precies even breed als een thumbnail.

height: 450px;

Met deze hoogte bestrijken ze precies een kolom met thumbnails.

margin-left: 1px;

Tussen de op de achtergrond-afbeelding gemonteerde thumbnails zit een kier van 1 px, waardoor de achtergrondkleur van de achtergrond-afbeelding zichtbaar is. Door links een marge van 1 px te geven, komen de kolommen niet boven deze kier te staan.

Je zou de <div>'s ook 1 px breder kunnen maken, dan staan ze ook op de goede plaats. Maar binnen deze vier <div>'s voor de kolommen komen de <div>'s die bij de thumbnails horen. Als je over één van die <div>'s hovert, openen de bijbehorende grote afbeelding en onderschrift. Die <div>'s worden even breed als de <div> voor de kolom, waar ze in zitten.

Als je de <div> voor de kolom 61 px breed maakt, wordt ook de bij de thumbnail horende <div> 61 px breed. Daardoor zou hoveren ook werken boven de kier tussen de thumbnails. Als je in plaats daarvan de breedte 60 px maakt en een marge van 1 px gebruikt, werkt hoveren boven de kier tussen de thumbnails niet, omdat hoveren niet werkt boven een marge.

Het gaat hier maar om een kier van 1 px, maar het is een goede gewoonte dingen enigszins op dezelfde manier te doen, zodat het een soort automatisme is. Bij een kier van 10 px zou het wel verwarrend zijn, als hoveren over die kier een grote afbeelding opent.

div[id^="thumb-"]

Als deze selector in stukjes wordt gehakt, wordt het wat minder ingewikkeld, dan het mogelijk op het eerste oog lijkt. De css bij deze selector moet voor alle 34 <div>' boven een thumbnail gelden, maar niet voor andere <div>'s. Je zou die 34 <div>'s een class kunnen geven, maar dit werkt ook.

div: alle <div>'s. Maar omdat er nog wat achteraan komt, geldt dit toch niet voor álle <div>'s.

[]: als een element een bepaalde eigenschap, attribuut, id, of zoiets moet hebben, geef je dat aan door die eigenschap, attribuut, id, en dergelijke tussen twee teksthaken te zetten.

id="thumb-": (de ^ voor de = komt gelijk hieronder aan de beurt). Tussen de twee teksthaken staat deze voorwaarde. Daarom geldt deze selector alleen voor een <div> met id="thumb-". Uiteraard zou je dan simpeler gewoon #thumb- of div#thumb- kunnen gebruiken, want er is maar één element met deze id op de pagina. En hier komt de ^ om de hoek kijken:

id^="thumb-": voor de = staat een ^. Alleen een = wil zeggen: precies gelijk aan. Maar de combinatie ^= geeft aan, dat de id alleen moet beginnen met 'thumb-'. Er mag van alles op volgen. Dat komt goed uit, want de 34 <div>'s die bereikt moeten worden, hebben allemaal als begin van hun id 'thumb-', gevolgd door een eigen volgnummer. Maar ook id='thumb-sinterklaas' of 'thumb-o-wat-is-mijn-grote-teen-toch-mooi' voldoen aan deze selector.

div[id^="thumb-"]: de hele selector in normale taal: <div>'s die een id hebben die begint met 'thumb-'.

height: 45px;

De thumbnails zijn 45 px hoog. De bijbehorende <div> krijgt dezelfde hoogte.

Een breedte hoeft niet opgegeven te worden, want normaal genomen wordt een blok-element zoals een <div> automatisch even breed als z'n ouder. Dat is hier één van de <div>'s voor de kolommen, die bij #thumbs > div een breedte van 60 px hebben gekregen. Daardoor krijgen deze <div>'s diezelfde breedte: even breed als de thumbnails.

margin-top: 1px;

Tussen de thumbnails zit een kier van 1 px, waardoor de achtergrondkleur van de achtergrond-afbeelding zichtbaar is. Door aan de bovenkant een marge van 1 px te geven, komen de <div>'s niet boven deze kier te staan.

Je zou de <div>'s ook 1 px hoger kunnen maken, dan staan ze ook op de goede plaats. Maar als je over een van de <div>'s hovert, openen de bijbehorende grote afbeelding en onderschrift. Zou je de <div>'s 46 px hoog maken, dan staan ze wel op de goede plaats, maar dan werkt hoveren ook boven die kier. Als je in plaats daarvan de hoogte 45 px maakt en een marge van 1 px gebruikt, werkt hoveren boven de kier tussen de thumbnails niet, omdat hoveren niet werkt boven een marge.

Het gaat hier maar om een kier van 1 px, maar het is een goede gewoonte dingen enigszins op dezelfde manier te doen, zodat het een soort automatisme is. Bij een kier van 10 px zou het wel verwarrend zijn, als hoveren over die kier een grote afbeelding opent.

div[id^="thumb-"]::before

div[id^="thumb-"]: alle <div>'s die een id hebben die begint met 'thumb-'. Dat zijn de 34 <div>'s boven de thumbnails. Hoe dit deel van de selector precies werkt, wordt iets hierboven bij div[id^="thumb-"] besproken.

Met behulp van ::before wordt bij de <div>'s een pseudo-element gemaakt, waarmee het volgnummer van de thumbnail op de thumb wordt gezet.

content: counter(volgnummer);

De inhoud van het met behulp van ::before aangemaakte pseudo-element. Dat is hier een teller ('counter') met de naam 'volgnummer'. Die teller moet al zijn aangemaakt, voor hij kan worden gebruikt. Dat is bij body gebeurd met counter-reset: volgnummer;.

counter-increment: volgnummer;

Verhoog de teller met de naam 'volgnummer'. Omdat geen waarde is opgegeven, waarmee verhoogd moet worden, wordt met 1 verhoogd. Bij het aanmaken van de teller heeft deze de waarde 0 gekregen. Bij de eerste <div> wordt dit veranderd in 1, bij de tweede <div> in 2, enz.

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

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 behoorlijk doorzichtig: 0.3. Hierdoor zie je de thumbs nog enigszins door de achtergrond heen, maar zijn de volgnummers toch altijd goed zichtbaar, ook op lichtere thumbs.

color: #ffffcf;

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

border-radius: 4px;

Ronde hoekjes. Er is hier geen border, maar dit werkt ook voor de achtergrondkleur.

padding: 0 2px;

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

De achtergrondkleur loopt door onder de padding. Een klein beetje achtergrondkleur rondom de getallen voorkomt dat een getal moeilijk zichtbaar wordt, doordat het precies aan een lichter stukje van de thumbnail grenst. 2 px links en rechts is voldoende.

Boven en onder is geen padding nodig, omdat de regelhoogte toch al altijd iets hoger is dan de tekst, dus daar is al wat achtergrondkleur aanwezig.

div.staand

Voor deze elementen geldt ook de eerder bij div[id^="thumb-"] opgegeven css, voor zover die hier niet wordt gewijzigd.

De <div>'s met class="staand". Dit zijn de twee <div>'s die boven een staande thumbnail zitten.

height: 80px;

De staande thumbnails zijn 80 px hoog, dus deze <div>'s moeten ook die hoogte krijgen.

.foto

De elementen met class="foto". De <span>'s waarbinnen de grote afbeelding zit.

background-color: rgba(100, 100, 100, 0.9);

Achtergrondkleur. Een uitleg over rgba() is te vinden bij background: rgba(0, 0, 0, 0.3);.

Drie keer het getal 100 levert een gemiddeld grijs op. Een doorzichtigheid van 0.9 laat de grote afbeelding duidelijk uitkomen, terwijl de thumbnails nog 'n heel klein beetje door de achtergrond heen te zien zijn.

Deze achtergrondkleur wordt alleen gebruikt in kleinere browservensters, waar de grote afbeelding bij gebrek aan ruimte boven de thumbnails wordt gezet. Als de thumbnails duidelijk zichtbaar zouden blijven, is dat heel storend.

background-position: 50%;

De grote afbeelding is een achtergrond-afbeelding. Deze moet zowel horizontaal als verticaal in het midden van de <span> worden gezet. Omdat de <span> zelf in kleinere browservensters het hele venster vult, staat de afbeelding hierdoor altijd midden in het venster.

background-repeat: no-repeat;

Een achtergrond-afbeelding wordt normaal genomen herhaald, tot de hele achtergrond van het element is gevuld. Hoewel hier heel mooie foto's bij zitten, is één foto toch wel genoeg.

background-size: contain; Afbeelding 7: zonder aanpassingen wordt de foto mogelijk vervormd weergegeven

Een van de nieuwere css-eigenschappen.

Een afbeelding heeft een bepaalde verhouding. Bij de hier gebruikte afbeeldingen is die 4 x 3 (bij de staande 3 x 4): de breedte is een derde meer dan de hoogte. 480 px breed, 360 px hoog (de staande 360 px breed en 480 px hoog).

De maten van het venster van de browser hebben hoogst waarschijnlijk niet precies dezelfde verhouding. Als je de afbeelding gewoon het venster zou laten vullen, zou de hoogte daardoor meer of minder toe‑ of afnemen dan de breedte. Wat een lachspiegeleffect zou opleveren, of er zouden delen van de afbeelding wegvallen.

Deze eigenschap zorgt ervoor dat de afbeelding zo groot mogelijk wordt weergegeven, maar zonder vervorming. Zodra de hoogte óf de breedte niet meer past, wordt de afbeelding niet verder vergroot, waardoor vervorming wordt voorkomen.

Op de afbeelding staat twee keer dezelfde afbeelding in twee keer een venster van dezelfde grootte met vrijwel dezelfde css. Rechts staat de afbeelding, zoals die hoort te zijn. Links is alleen background-size: contain; weggelaten, wat een veel grotere bij (hommel?) oplevert, maar het arme beestje is wel de helft van z'n vleugels en voelsprieten kwijtgeraakt, want die pasten niet meer in het venster.

display: none;

De <span>'s verbergen. Zodra dat nodig is, worden ze zichtbaar gemaakt.

pointer-events: none;

Deze css-eigenschap moet niet worden verward met pointer-events uit JavaScript, die iets heel anders zijn.

Dit is nodig voor Internet Explorer 11 op een touchscreen en UC browser op Windows Phone. Deze browsers gaan zich uiterst vreemd gedragen, als op een touchscreen een <span> wordt geopend, die eerst met display: none; was verborgen. Maar alleen als in die <span> een afbeelding zit. En dat is precies wat hier het geval is bij span.foto.

Als je het scherm aanraakt op de plaats waar, na opening, de <span> met de afbeelding komt te staan, verschijnt de afbeelding in Internet Explorer 11 pas na een langdurige aanraking. In UC browser op Windows Phone verschijnt de afbeelding helemaal niet. Als je het scherm buiten die plaats aanraakt, werkt het normaal en blijven de afbeeldingen gelijk geopend.

Hetzelfde geldt bij aanraking op de plaats waar, na opening, de <span> met het onderschrift komt te staan. Dat de <span> met de afbeelding met display: none; is verborgen en dat de <span> met het onderschrift links buiten het scherm zijn geparkeerd, voorkomt dit vreemde gedrag niet. Terwijl in beide gevallen de <span> gewoon afwezig hoort te zijn en dus ook geen invloed zou moeten hebben.

Deze eigenschap voorkomt deze vreemde bug. Het zorgt ervoor dat een klik, een aanraking, hoveren, en dergelijke boven .foto volledig worden genegeerd, maar worden doorgegeven aan het onder .foto liggende element. Als je een geopende grote foto of een geopend onderschrift boven de thumbnails aanraakt, kun je dit goed zien: de bij de aangeraakte thumbnail horende grote afbeelding opent. Zonder pointer-events: none; zou de aanraking, klik, hover en dergelijke de onder de grote afbeelding liggende thumbnail niet bereiken, maar worden afgevangen door span.foto of span.tekst.

Dat is ook waar deze eigenschap voor is bedoeld: zorgen dat 'n element hoveren en dergelijke negeert. Normaal genomen zou ik hem niet gebruiken hier, maar het neutraliseert op wonderbaarlijke wijze deze bug.

position: fixed; Afbeelding 8: zonder gebruik van position: fixed kunnen de grote afbeeldingen te hoog worden neergezet

De positie van de <span> koppelen aan het venster van de browser. De afbeeldingen worden altijd op dezelfde plaats getoond, ook als wordt gescrold.

Dit is van belang in lage vensters. Als je daarin de thumbnails naar boven scrolt, omdat ze niet allemaal zichtbaar zijn, zou de afbeelding bij gebruik van bijvoorbeeld position: absolute; in plaats van position: fixed; te hoog worden neergezet. Waardoor aan de bovenkant een deel van de afbeelding wegvalt, zoals op de afbeelding is te zien.

De <span> waarin de achtergrond-afbeelding staat, is verder helemaal leeg. Daarom heeft die <span> geen grootte. En is er dus ook geen achtergrond om te vullen met een achtergrond-afbeelding. Daarom wordt hieronder met behulp van top, right, bottom en left een grootte aan de <span> gegeven.

top: 0; right: 0;

Altijd aan de boven- en rechterkant van het browservenster neerzetten.

Het gaat hier om de positie van de <span>. De afbeelding zelf is een achtergrond-afbeelding, die iets hoger met background-position: 50%; horizontaal en verticaal binnen deze <span> is gecentreerd. Ook als de <span> breder of hoger is dan de afbeelding, komt de afbeelding hierdoor toch altijd in het midden te staan.

bottom: 3rem; Afbeelding 9: links staat het onderschrift over de foto, rechts netjes eronder

Aan de onderkant van de <span> met de grote foto moet ruimte blijven voor een onderschrift.

In hogere browservensters is dat geen probleem, omdat er dan altijd wel ruimte aan de onderkant leeg blijft. Maar in lagere vensters bestaat de kans, dat een deel van de grote afbeelding onder het onderschrift komt te staan en daardoor niet te zien is, zoals op de linkerafbeelding.

Daarom wordt aan de onderkant van de <span> een ruimte van 3 rem vrijgelaten. Dat betekent wel, dat in deze ruimte ook geen achtergrondkleur is, waardoor de thumbnails in deze ruimte hinderlijk zichtbaar zouden zijn. Want het onderschrift vult niet in alle maten vensters deze ruimte volledig. Dit probleem wordt gelijk hieronder bij .foto::after opgelost.

Als eenheid is rem gebruikt, een tamelijk onbekende eenheid. De afkorting rem staat voor root em: de relatieve eenheid em, maar dan ten opzichte van de 'root', de basis van het document. Bij een pagina op een site is de 'root' altijd het <html>-element.

De grootte van een em is gebaseerd op de lettergrootte. Bij een grotere lettergrootte is de em groter dan bij een kleinere lettergrootte. Een normale em is afhankelijk van al z'n voorouders. Als een van die voorouders de lettergrootte vergroot of verkleint, geldt dat ook voor de nakomelingen van die voorouder.

De rem is altijd ten opzichte van de lettergrootte in <html>, ongeacht wat de voorouders van het element er onderweg van <html> naar het uiteindelijke element mee hebben gedaan.

De hoogte van de <span> met het onderschrift is ook 3 rem. Omdat hier hetzelfde voor geldt, zijn de lege ruimte onder de <span> en de hoogte van de <span> met het onderschrift altijd hetzelfde, ongeacht wat er in welke voorouder dan ook met de lettergrootte is gebeurd.

De tekst van de onderschriften paste in kleinere browservensters niet binnen de <span> die daarvoor was bedoeld. Daarom is de lettergrootte verkleind tot 0,75 em. Als voor de hoogte van de <span> voor de onderschriften em was gebruikt als eenheid, zou die hoogte mee veranderen en niet meer hetzelfde zijn als de ruimte onder de grote afbeelding.

Door voor de hoogte rem te gebruiken, kan de lettergrootte van het onderschrift worden veranderd, terwijl de hoogte toch hetzelfde blijft, want die is nu gebaseerd op de grootte van de em bij de root, bij <html>. En is dus nog even groot als de lege ruimte onder de grote afbeelding.

Je zou ook een eenheid als px kunnen gebruiken voor de hoogte van de <span> met de tekst en de ruimte onder de afbeelding. Maar een px is een absolute eenheid. De rem is een relatieve eenheid. Als het browservenster kleiner is, zoals op een smartphone, is de rem kleiner dan in een groter venster, zoals een desktop. En als de gebruiker de lettergrootte in de browser aanpast, verandert de rem mee. Een grotere letter levert een grotere rem op, terwijl een px voor de hoogte gewoon een px blijft en niet mee verandert.

left: 0;

De <span> helemaal aan de linkerkant van het venster van de browser laten beginnen.

.foto::after

Afbeelding 10: als de thumbnails niet goed worden afgedekt, leiden deze te veel af van de grote foto

Met behulp van ::after wordt bij de elementen met class="foto" – dat zijn de <span>'s met de grote afbeelding – een pseudo-element gemaakt, waarmee een mogelijke kier onder het onderschrift wordt gedicht.

De <span> met de grote afbeelding heeft bij .foto een grijze achtergrond gekregen, die de thumbnails afdekt. Onder de <span> is ruimte vrijgelaten voor een onderschrift. Dat onderschrift staat echter, afhankelijk van de maat van het venster van de browser, niet altijd precies in die vrijgelaten ruimte. Op de afbeelding staat het in een tamelijk smal en hoog venster gelijk onder de grote afbeelding, waarbij onder het onderschrift de thumbnails hinderlijk zichtbaar blijven.

Dit pseudo-element is bedoeld om die ruimte te vullen met dezelfde achtergrondkleur als de rest van het venster.

(Het op de afbeelding gebruikte venster is opzettelijk héél smal gemaakt. Normaal genomen zul je niet snel in een venster van deze afmeting foto's gaan bekijken.)

content: "";

Ook als er geen tekst of zo in het met behulp van ::after pseudo-element staat, moet content worden gebruikt. Dat er verder niets in staat, geef je aan door de ruimte tussen de aanhalingstekens leeg te laten.

background: rgba(100, 100, 100, 0.9);

Achtergrondkleur. Een uitleg over rgba() is te vinden bij background: rgba(0, 0, 0, 0.3);. Drie keer het getal 100 levert een gemiddeld grijs op. Een doorzichtigheid van 0.9 laat de grote afbeelding duidelijk uitkomen, terwijl de thumbnails nog 'n heel klein beetje door de achtergrond heen te zien zijn. Dit is dezelfde achtergrondkleur als de <span> met de grote afbeelding bij .foto heeft gekregen.

width: 100%;

Volle breedte van het venster van de browser vullen.

Een breedte in procenten wordt altijd genomen ten opzichte van de ouder van het element. Dit pseudo-element hoort bij de <span> met de grote afbeelding. Die <span> vult de volle breedte van het venster, dus dit pseudo-element ook.

height: 200px;

Hieronder bij bottom: -200px; wordt het pseudo-element 200 px beneden de <span> met de grote afbeelding neergezet. Door het een hoogte van 200 px te geven, wordt een ruimte van 200 px onder de <span> met de grote afbeelding gevuld met de achtergrondkleur.

Omdat dit alleen in (heel) kleine browservensters speelt, zou dit voor elke situatie voldoende moeten zijn.

(Omdat alleen bottom wordt opgegeven en geen top, wordt de hoogte van 200 px gemeten vanaf de onderkant van het pseudo-element.)

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 is gepositioneerd. Dat is hier span.foto, de <span> waar dit pseudo-element bij hoort.

Een pseudo-element is van zichzelf een inline-element. Dat betekent onder andere dat je eigenschappen als hoogte en breedte niet kunt gebruiken. Door het absoluut te positioneren verandert het in een soort blok-element, waardoor je dit soort eigenschappen wel kunt gebruiken.

bottom: -200px;

200 px onder de <span> met de grote afbeelding neerzetten.

.tekst

De elementen met class="tekst". De <span>'s waar de onderschriften in staan.

color: black;

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

Hoewel dit de standaardkleur is, geef ik de kleur toch op. Hieronder bij div[id^="thumb-"]:hover .tekst, div[id^="thumb-"]:focus .tekst wordt 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.

box-sizing: border-box;

In smallere browservensters moet de <span> met het onderschrift de volle breedte van het browservenster vullen. Als je margin, border of padding gebruikt, wordt dat standaard bij die breedte opgeteld. Waardoor het onderschrift dus de breedte van het venster zou krijgen plus daarbij nog een eventuele marge en dergelijke

In dit geval is het makkelijker om de <span> met het onderschrift even breed te maken als het venster van de browser, maar de marge en dergelijke bínnen die breedte te zetten. Dan kan de <span> nooit breder worden dan het venster, waardoor er delen zouden kunnen verdwijnen buiten het venster.

height: 3rem;

Een hoogte van 3 rem. Een rem is een em, maar dan ten opzichte van de 'root', hier het <html>-element. Daardoor is deze 3 rem altijd exact hetzelfde als de kier van 3 rem onder span.foto, ongeacht de lettergrootte.

Een uitgebreider verhaal over het waarom van deze wat onbekende eenheid is hierboven bij .foto te vinden onder bottom: 3rem;.

font-size: 0.75em;

Iets kleinere letter. Voor grotere browservensters wordt de lettergrootte later weer vergroot.

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

padding: 3px 5px;

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

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

pointer-events: none;

Deze eigenschap is nodig voor een bug in Internet Explorer 11 op touchscreens en UC browser op Windows phone. Het zorgt ervoor dat aanrakingen, klikken, hoveren, en dergelijke op deze <span>'s volledig wordt genegeerd. Een uitgebreidere uitleg is hierboven bij .foto onder pointer-events: none;.

position: fixed; Afbeelding 11: het onderschrift staat midden over de foto

De positie van de <span> koppelen aan het venster van de browser. De onderschriften staan altijd op dezelfde plaats, ook als wordt gescrold.

Dit is van belang in lage vensters. Als je daarin de thumbnails naar boven scrolt, omdat ze niet allemaal zichtbaar zijn, zou het onderschrift bij gebruik van bijvoorbeeld position: absolute; in plaats van position: fixed; te hoog worden neergezet. Hierdoor zou het onderschrift soms niet onder, maar over de grote afbeelding worden geplaatst, zoals op de afbeelding is te zien.

top: calc(50% + 37.5vw – 24px);

Ik zou hier nu graag in een gloedvol betoog willen uitdragen dat ik begrijp wat hier gebeurt. En dat hier Einsteiniaanse hogere wiskunde achter zit van een wonderschone genialiteit.

Helaas.

Ik heb werkelijk geen flauw idee, waarom deze berekening werkt. Althans: sommige dingen begrijp ik. Maar waar die 37.5 vw vandaan komt???

Bovenstaande toverspreuk zorgt ervoor dat in vensters in portretstand het onderschrift precies onder de grote afbeelding komt te staan. In landschapsstand kan het onderschrift smaller zijn dan de afbeelding en is dat foeilelijk. Voor landschapsstand staat verderop bij .tekst andere css. In browservensters breder dan 759 px geldt dit ook niet, want daar is de hele weergave anders. Dat wordt verderop bij css voor vensters minimaal 760 px breed geregeld. De css hier heeft dus alleen betrekking op vensters in portretstand smaller dan 760 px.

Goed, de toverformule.

De plaatsing en grootte van de grote afbeelding is afhankelijk van stand en grootte van het browservenster. Daardoor staat de onderkant van de grote afbeelding niet op een vaste plaats. Maar het zou leuk zijn, als het onderschrift toch altijd gelijk onder de grote afbeelding komt te staan.

Daarvoor ben ik uitgebreid aan het spelen gegaan. Op een gegeven moment had ik 'n soort formule met wel tien getallen, die bleek te werken. Door vereenvoudigen is daar uiteindelijk bovenstaande berekening uit overgebleven. Zo stond er een versie eerder bijvoorbeeld (100vw / 2.66). Dat kun je ook zelf uitrekenen en dan blijkt dat gewoon hetzelfde te zijn als 37,5 vw.

Helaas heb ik die uitgebreide formule per ongeluk niet bewaard. En aangezien ik niet weet, wat ik heb gedaan – wat trouwens wel vaker gebeurt –, kan ik die ook niet reconstrueren. Jammer, want iemand met enigszins wiskundige aanleg zou mogelijk kunnen uitleggen, waarom dit werkt.

Bij een andere grootte van de grote afbeeldingen, waarbij de plaatsing van de grote afbeelding dus verandert en daardoor ook de plaats van de onderkant van de grote foto, zou je met de waarden 37.5vw en 24px moeten gaan experimenteren om nieuwe juiste waarden te vinden.

top: gewoon de positie vanaf de bovenkant.

calc(): met behulp van calc() kun je allerlei berekeningen uitvoeren, zelfs met waarden die verschillende eenheden gebruiken. In deze berekening bijvoorbeeld worden de waarden %, vw en px gebruikt. De uiteindelijke eenheid is afhankelijk van een aantal dingen, waaronder de eigenschap waarvoor calc() wordt gebruikt. Hier is de uiteindelijke eenheid px.

Het deel tussen de haakjes wordt berekend. Hierbij gelden de normale voorrangsregels, zoals die ook bij gewoon rekenen gelden.

50%: zet de <span> verticaal halverwege het venster van de browser neer. Als je het onderschrift daar laat staan, komt het uiteraard midden op de grote afbeelding te staan. Daarom wordt het een eindje omlaag verplaatst:

+ 37.5vw: 1 vw is 1% van de hoogte van het venster van de browser. Ongeacht hoe hoog dat venster is. 37.5vw is dus altijd gelijk aan 37,5% van de volle hoogte van het venster. Ongeacht hoe hoog of hoe laag tussenliggende voorouders van deze <span> zijn.

Deze hoeveelheid wordt opgeteld bij de 50% die gelijk hierboven is gebruikt. Het onderschrift staat nu dus op 50% + 37,5 vw van de bovenkant van het venster. Omdat twee relatieve eenheden zijn gebruikt, past deze plaats zich automatisch aan de hoogte van het venster aan. 50% is altijd de helft, hoe hoog of hoe laag het venster ook is. En 1 vw is 1%, dus die eenheid past zich ook aan de hoogte van het venster aan.

Die 37,5 vw heb ik gewoon door uitproberen gevonden. Nu blijkt echter dat het onderschrift iets te laag staat. En eigenaardig genoeg staat het altijd dezelfde hoeveelheid te laag: 24 px:

– 24px: zet het onderschrift weer 24 px naar boven. Dit is een absolute eenheid: 24 px is altijd 24 px, hoe hoog of hoe laag het browservenster ook is. Waarom nou precies deze hoeveelheid px, een absolute eenheid, werkt in combinatie met de relatieve 50% en 37,5 vw: ik heb geen flauw idee.

Ongetwijfeld is dit door iemand met voldoende wiskundige kennis te verklaren, maar ik had de pest aan mijn wiskundeleraar en hij aan mij, dus helaas.

right: 0;
Afbeelding 12
Afbeelding 12: hoewel je de <span>'s niet ziet, zijn ze wel aanwezig. Als je de achtergrondkleur hier al zou geven, is dat duidelijk zichtbaar. De bovenste lichte streep hoort bij de liggende foto's, de onderste bij de staande.

De <span> met het onderschrift moet in smallere browservensters helemaal tot de rechterkant van het venster staan. Voor bredere vensters wordt dat later aangepast.

Hier iets onder wordt de linkerkant van de <span> met left: -20000px; links buiten het scherm geparkeerd. Omdat de linkerkant 20000px links buiten het scherm staat, is redelijk zeker dat alle tekst in de <span> ook buiten het scherm staat, en dus onzichtbaar is. Een regel tekst die (meer dan) 20000 px lang is, is wat onwaarschijnlijk.

Dat geldt echter niet voor de achtergrondkleur van de <span>. De <span> loopt van left: -20000px; tot right: 0; en bestrijkt dus de volle breedte van het venster van de browser. Inclusief achtergrondkleur. Daarom wordt aan de <span> pas een achtergrondkleur gegeven bij div[id^="thumb-"]:hover .tekst, div[id^="thumb-"]:focus .tekst, als het onderschrift getoond moet worden.

bottom: 0;

Tot aan de onderkant van het browservenster laten doorlopen.

Iets hierboven is met top ook een positie ten opzichte van de bovenkant van het venster opgegeven. En er is een hoogte van 3 rem opgegeven.

Deze drie eigenschappen botsen met elkaar. Als je top en een hoogte opgeeft, staat bottom ook al vast. In dat geval winnen top en height en wordt bottom genegeerd.

De enige reden om hier al bottom op te geven: ik vind het overzichtelijker om zoveel mogelijk eigenschappen op één plaats toe te voegen. Maar daar kun je anders over denken.

Bij vensters in landschapsstand die maximaal 759 px breed zijn, en bij staande foto's in portretstand, wordt later speciaal voor die vensters top: auto; toegevoegd. Daarmee wordt top uitgeschakeld en wordt bottom: 0; wel effectief. De hoogte van 3 rem geldt dan vanaf de onderkant van het browservenster.

left: -20000px;

Linkerkant van de <span> met het onderschrift links buiten het scherm parkeren, zodat het onderschrift in de <span> links buiten het browservenster staat en dus onzichtbaar is.

Je zou de hele <span>, en dus ook de tekst daarin, ook kunnen verbergen met display: none;, maar dan zouden schermlezers de tekst ook negeren. Nu wordt het onderschrift gewoon voorgelezen, ook al staat het buiten het scherm. Hierdoor kunnen blinden, als je goede onderschriften gebruikt, toch een beschrijving van de afbeelding horen.

div[id^="thumb-"]:hover .foto, div[id^="thumb-"]:focus .foto

div[id^="thumb-"]: alle <div>'s die een id hebben die begint met 'thumb-'. Dat zijn de 34 <div>'s boven de thumbnails. Hoe dit deel van de selector precies werkt, wordt bij div[id^="thumb-"] besproken.

Als over één van deze <div>'s wordt gehoverd, of als één van deze <div>'s focus heeft, doe dan iets met de in die <div> zittende elementen met class="foto". Dat is er in elke <div> maar eentje: de <span> waarin de grote afbeelding wordt getoond.

display: block;

Bij .foto zijn deze <span>'s met behulp van display: none; verborgen. Nu worden ze zichtbaar gemaakt, waardoor ook de erin zittende grote afbeelding zichtbaar kan worden.

div[id^="thumb-"]:hover .foto, div[id^="thumb-"]:hover .tekst

Voor de eerste selector, die voor de komma, geldt ook de eerder bij div[id^="thumb-"]:hover .foto, div[id^="thumb-"]:focus .foto opgegeven css.

div[id^="thumb-"]: alle <div>'s die een id hebben die begint met 'thumb-'. Dat zijn de 34 <div>'s boven de thumbnails. Hoe dit deel van de selector precies werkt, wordt bij div[id^="thumb-"] besproken.

Als over één van deze <div>'s wordt gehoverd, doe dan iets met de daarin zittende elementen met class="foto" en class="tekst". In elke <div> zit maar één zo'n element: span.foto waarin de grote afbeelding wordt getoond en span.tekst waarin het onderschrift zit.

z-index: 10;

Dit is alleen van belang, als met de muis wordt gewerkt.

Als één van de 34 <div>'s boven de thumbnails focus heeft, worden bijbehorende grote afbeelding en onderschrift getoond. Als je nu tegelijkertijd met de muis over een andere thumbnail hovert, wordt ook die geopend. Er zijn dan dus twee grote afbeeldingen met twee onderschriften geopend.

Stel dat de tiende afbeelding is geopend, omdat de bijbehorende tiende <div> focus heeft. Als je nu over een eerdere <div> hovert, dus de eerste tot en met de negende, gebeurt er niets. Althans: je ziet niets. Door het hoveren openen nóg een grote afbeelding en onderschrift, maar die zie je niet, omdat de tiende <div> in de html na de eerste tot en met de negende <div> komen. Daardoor staan de tiende grote afbeelding en onderschrift altijd boven die van een hoger in de html staande <div>.

Maar als je over de elfde of latere <div> hovert, zie je wel de bij die <div> horende grote afbeelding en onderschrift. Want die staan lager in de html, en 'winnen' dus van de tiende <div>.

Ietwat verwarrend: als een <div> focus heeft, zie je de ene keer wel iets bij hoveren, en de andere keer niet.

Door bij hoveren aan de <div> waarover wordt gehoverd een hogere z-index te geven, worden de bij deze <div> horende grote afbeelding en onderschrift altijd getoond, ongeacht de volgorde in de html.

Een z-index werkt alleen, als het element voldoet aan één of meer voorwaarden. Eén van die voorwaarden is een absolute of fixed positie. span.foto en span.tekst zijn fixed gepositioneerd. Voor bredere browservensters wordt dat later veranderd in een absolute positie. In beide gevallen is dus aan één van de voorwaarden voldaan en zal z-index werken.

div[id^="thumb-"]:hover .tekst, div[id^="thumb-"]:focus .tekst

Voor de eerste selector (voor de komma) geldt ook de eerder bij div[id^="thumb-"]:hover .foto, div[id^="thumb-"]:hover .tekst opgegeven css.

div[id^="thumb-"]: alle <div>'s die een id hebben die begint met 'thumb-'. Dat zijn de 34 <div>'s boven de thumbnails. Hoe dit deel van de selector precies werkt, wordt bij div[id^="thumb-"] besproken.

Als over één van deze <div>'s wordt gehoverd, of als één van deze <div>'s focus heeft, doe dan iets met de daarin zittende elementen met class="tekst". In elke <div> zit maar één zo'n element: de <span> met het onderschrift.

background: #ffffcf;

Achtergrondkleurtje.

Normaal genomen zou ik dat hebben opgegeven bij .tekst, waar de rest van de css voor deze <span>'s ook is opgegeven. Dat kan echter niet, omdat de <span> al op het scherm staat. Je ziet hem niet, maar hij is er wel. Als daar al een achtergrondkleur zou worden gegeven, zou je de <span> wel zien. Vandaar dat in dit geval pas een achtergrondkleur wordt gegeven, als het onderschrift getoond moet worden.

Het is een goede gewoonte om bij een achtergrondkleur ook een voorgrondkleur op te geven. De voorgrondkleur is onder andere de kleur van de tekst. 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.

In dit geval is de voorgrondkleur al bij .tekst opgegeven, zodat ook dit is geregeld.

left: 0;

Bij .tekst zijn de <span>'s fixed gepositioneerd. Er wordt dus gepositioneerd ten opzichte van het venster van de browser, ongeacht hoe breed dit is.

Bij .tekst is de linkerkant van de <span> met left: -20000px; links buiten het scherm geparkeerd. Hierdoor staat ook de tekst van het in deze <span> zittende onderschrift links buiten het scherm en is dus niet zichtbaar.

Met left: 0; wordt de linkerkant van de <span> links in het venster van de browser gezet, waardoor het in de <span> zittende onderschrift ook binnen het venster komt te staan en zichtbaar wordt.

#thumb-1:hover .foto, #thumb-1:focus .foto

Voor dit element geldt ook de eerder bij div[id^="thumb-"]:hover .foto, div[id^="thumb-"]:focus .foto en div[id^="thumb-"]:hover .foto, div[id^="thumb-"]:hover .tekst opgegeven css.

Als over het element met id="thumb-1" wordt gehoverd, of als dit focus heeft, doe dan iets met de daarin zittende elementen met class="foto". Dat is hier maar één element: de <span> voor de grote afbeelding.

De <div> met id="thumb-1" hoort bij de eerste thumbnail. De daarin zittende span.foto hoort – volgt schokkende onthulling – bij de eerste grote foto. Wat kan het leven simpel en overzichtelijk zijn!

background-image: url(../016-pics/foto-01.jpg);

Achtergrond-afbeelding invoegen.

In heel veel situaties kan een afbeelding gewoon met <img> worden ingevoegd en worden verborgen met iets als display: none;. Dat zou hier ook kunnen, maar het heeft één heel groot nadeel: alle afbeeldingen worden bij openen van de pagina gedownload, ook als ze zijn verborgen en helemaal niet worden bekeken.

Datzelfde geldt voor 'gewone' achtergrond-afbeeldingen:

#thumb-1 {background-image: url(../016-pics/foto-01.jpg);

wordt altijd gedownload, of het nou wordt bekeken of niet.

Met 34 afbeeldingen kan dat nogal bezwaarlijk zijn op bijvoorbeeld een mobiele verbinding.

Door de achtergrond-afbeelding pas in te voegen, als daadwerkelijk over de <div> bij die afbeelding wordt gehoverd, of als deze focus heeft, wordt de afbeelding pas gedownload, als hij echt wordt bekeken. Als je geen enkele afbeelding zou bekijken, zou zelfs geen enkele afbeelding worden gedownload. (Behalve natuurlijk de afbeelding met de thumbnails, maar die heeft hier niets mee te maken.)

#thumb-2:hover .foto, #thumb-2:focus .foto

{background-image: url(../016-pics/foto-02.jpg);}

tot en met

#thumb-34:hover .foto, #thumb-34:focus .foto

{background-image: url(../016-pics/foto-34.jpg);}

De elementen met id="thumb-2" tot en met id="thumb-34". Dit zijn de <div>'s die bij de tweede tot en met 34e thumbnail horen. De namen van de achtergrond-afbeeldingen horen bij de bijbehorende grote afbeeldingen.

De css is exact hetzelfde als gelijk hierboven bij #thumb-1:hover .foto, #thumb-1:focus .foto, alleen het volgnummer van de <div> en het volgnummer van de achtergrond-afbeelding veranderen.

css voor vensters in portretstand

@media screen and (orientation: portrait)

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

De css die binnen deze media query staat, geldt alleen voor vensters in portretstand. In deze vensters wordt voor staande foto's een deel van de css aangepast.

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

screen: deze regel geldt alleen voor schermweergave.

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

(orientation: portrait): het scherm moet in portretstand zijn.

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

Dit is bedoeld voor tablets, smartphones, en dergelijke Voor desktop monitors zal de stand meestal niet echt van belang zijn. Maar in veel browsers werkt dit ook op de desktop. Als je de grootte van het browservenster verandert, zodat het de hoogte groter wordt dan de breedte (portretstand) wordt, werkt dit vaak ook op de desktop.

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

@media screen and (orientation: portrait) { 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 }.

.staand .tekst

De elementen met class="tekst" die binnen een element met class="staand" zitten. De <div>'s die bij de twee staande foto's horen, hebben een extra class 'staand' gekregen. Binnen deze <div>'s zit maar één element met class="tekst": de <span> met het onderschrift. Deze selector heeft dus betrekking op de onderschriften bij de staande foto's.

top: auto; Afbeelding 15: bij een staande afbeelding staat het onderschrift over de afbeelding, als niet wordt gecorrigeerd

Bij .tekst wordt de plaats van het onderschrift bij top berekend met een formule: calc(50% + 37.5vw - 24px). Deze is formule is door mijzelf bedacht en zo geniaal, dat ik er zelf niets van begrijp. Maar 't kreng werkt, en daar gaat het om.

Althans, het werkt bij liggende afbeeldingen. Bij een staande afbeelding werkt het dus niet, zoals op de afbeelding is te zien.

Bij .tekst is, naast top, ook bottom: 0; en height: 3rem; opgegeven. Die combinatie kan natuurlijk niet: bij een bepaalde top met een bepaalde height staat automatisch ook bottom vast. Omdat dit met elkaar botst, wordt bottom daar genegeerd.

Hier wordt top ingesteld op de standaardwaarde: auto. Nu blijven alleen bottom: 0; en height: 3rem; over. En dat kan wel: een hoogte van 3 rem vanaf de onderkant van het browservenster.

(Omdat span.tekst bij .tekst fixed is gepositioneerd, geldt bottom: 0; ten opzichte van het venster, hoe hoog of laag dit ook is.)

css voor vensters in landschapsstand en maximaal 759 px breed

@media screen and (orientation: landscape) and (max-width: 759px)

De opbouw van deze regel staat beschreven bij media screen and (orientation: portrait). Er zijn twee verschillen: de stand moet hier landschapsstand zijn, en er is een extra voorwaarde: het browservenster mag niet breder dan 759 px zijn (max-width: 759px).

De css binnen deze media query corrigeert de plaats van het onderschrift in deze vensters.

.tekst

Afbeelding 16
Afbeelding 16: links het veel te brede onderschrift zonder aanpassingen voor de landschapsstand, rechts met aanpassingen.

De elementen met class="tekst". De <span>'s waar de onderschriften in staan.

In een liggend venster kan het onderschrift breder of smaller worden dan de grote afbeelding, waar het onderschrift onder komt te staan. Dit geldt niet voor browservensters breder dan 759 px, want daarvoor wordt verderop de weergave volledig aangepast.

In portretstand vult de grote afbeelding altijd de volle breedte van het venster van de browser. Het onderschrift mag daar ook de volle breedte vullen, omdat het netjes aansluit op de grote foto.

In landschapsstand ligt dat anders: het onderschrift kan hier (veel) breder of smaller worden dan de grote afbeelding. Daarom wordt het uiterlijk van het onderschrift aangepast. Zou dat niet gebeuren, dan zou het een rechthoekig blok blijven, wat niet echt fraai is.

Bovendien werkt de formule die bij .tekst is opgegeven voor top niet meer, waardoor het onderschrift te hoog kan komen te staan, over de afbeelding heen.

Daarom worden hier plaats en uiterlijk van de <span>'s met het onderschrift aangepast voor deze vensters.

width: 80%;

Breedte. Een breedte in procenten wordt altijd genomen ten opzichte van de ouder van het element. Dat is hier één van de 34 <div>'s die boven de thumbnails staan. Deze <div>'s zijn even breed als het venster van de browser. De <span> met het onderschrift krijgt dus een breedte van 80% van het venster van de browser.

max-width: 480px;

De css hier is geldig voor vensters met een maximumbreedte van 759 px. Tot die breedte kan de grote afbeelding de volle breedte van het venster van de browser vullen. Dat zou hele lange regels opleveren, die daardoor slecht leesbaar zijn. Daarom wordt de breedte beperkt tot maximaal 480 px.

Dat is trouwens dezelfde breedte als het onderschrift in vensters breder dan 759 px krijgt, dus dat zou wat de hoeveelheid tekst in het onderschrift betreft geen probleem moeten zijn.

margin: 0 auto;

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

Boven en onder geen marge, links en rechts auto, wat hier hetzelfde betekent als evenveel. De <span> met het onderschrift staat dus altijd horizontaal gecentreerd, ongeacht de breedte van het venster van de browser. Deze manier van centreren van een blok-element kan alleen, als het te centreren element een breedte heeft.

Hier doet zich een eigenaardig verschijnsel voor. Bij .tekst zijn de <span>'s fixed gepositioneerd. Normaal genomen kan een element dat absoluut of fixed is gepositioneerd, niet horizontaal worden gecentreerd met behulp van het handige margin: 0 auto;.

Bij .tekst is echter ook right: 0; opgegeven. En bij hoveren over of focus op de <div> waar de <span> in zit, wordt bij div[id^="thumb-";]hover .tekst, div[id^="thumb-"]:focus .tekst aan de <span> left: 0; opgegeven.

Daardoor staat hier right: 0; én left: 0; én een maximumbreedte. Dat bijt elkaar natuurlijk. De maximumbreedte is 480 px, dus als het venster van de browser breder is dan 480 px, kan deze <span> onmogelijk gelijktijdig van helemaal links tot helemaal rechts lopen.

De browser raakt hier dermate van in de war, dat right: 0; en left: 0; gewoon worden genegeerd en margin: 0 auto; werkt. Oftewel: bij een absolute of fixed positie werkt margin: 0 auto; niet, tenzij je ook left: 0; en right: 0; opgeeft. (Een eigenaardigheid die trouwens nauwelijks bekend is en ikzelf zojuist ook pas voor het eerst heb ontdekt.)

border: black solid 1px;

Zwart randje.

border-radius: 10px 10px 0 0;

Linksboven en rechtsboven ronde hoek.

top: auto;

Bij .tekst wordt top berekend met behulp van top: calc(50% + 37.5vw – 24px);. Die formule werkt alleen bij vensters in portretstand. Daarom wordt hier de standaardinstelling aan top gegeven: auto. Waarmee het is uitgeschakeld.

Bij .tekst is ook bottom: 0; opgegeven, en ook een hoogte van 3 rem. Deze combinatie van top, hoogte en bottom kan niet. Als je een top opgeeft én een bepaalde hoogte, dan is bottom ook al bekend. Bij zo'n botsing wordt bottom gewoon genegeerd.

Nu is top uitgeschakeld en zijn alleen bottom: 0; en height: 3rem; over. En dat kan wel. Onderaan het venster van de browser neerzetten en vanaf daar 3 rem hoog maken. (Omdat bij .tekst een fixed positie aan de <span> is gegeven, wordt deze gepositioneerd ten opzichte van het venster van de browser.)

css voor vensters minimaal 760 px breed

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

De opbouw van deze regel staat beschreven bij media screen and (orientation: portrait). Alleen is de voorwaarde hier geen portretstand, maar een minimumbreedte van 760 px (min-width: 760px).

De css binnen deze media query zorgt ervoor dat in deze bredere vensters grote foto en onderschrift niet boven, maar naast de thumbnails komen te staan.

body

{position: relative;}

Het element waar de hele pagina in staat.

Een aantal nakomelingen van <body> moet worden gepositioneerd ten opzichte van <body>. Dat kan alleen als <body> zelf een positie heeft. Omdat er verder niets bij top en dergelijke wordt ingevuld, heeft dat verder geen invloed op <body> zelf.

#inleiding

Het element met id="inleiding". De <div> waar de korte tekst rechts van de thumbnails in staat.

background: #ffffcf;

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

display: block;

Bij #inleiding is deze <div> met display: none; bij gebrek aan ruimte verborgen voor smallere browservensters. Hier wordt hij zichtbaar gemaakt.

width: 350px;

Breedte.

Een hoogte is niet nodig, omdat een blok-element zoals een <div> normaal genomen automatisch voldoende hoogte krijgt voor de inhoud ervan.

padding: 4px;

Kleine afstand tussen tekst in en rand van de <div>.

position: absolute;

Om de <div> 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 <body>.

left: 376px;

376 px vanaf links neerzetten.

En nu doet zich een wonderbaarlijk verschijnsel voor: zonder enige aanleiding staat de <div> met de tekst ook 6 px vanaf de bovenkant van het venster van de browser. Spontaan. Uit zichzelf.

Dat komt goed uit, daar niet van, want bij #thumbs zijn de thumbnails ook op 6 px vanaf de bovenkant neergezet. En het is netter als alles op dezelfde hoogte staat. Bovendien zou er anders een stukje van de <div> aan de bovenkant zichtbaar blijven, als een grote afbeelding wordt getoond.

Maar waar komt die 6 px vandaan? Van een van de meest verwarrende dingen die css kent: het combineren van verticale marges.

div#thumbs heeft bij #thumbs aan de bovenkant een marge van 6 px gekregen.

Bij body is expliciet opgegeven, dat marges bij <body> verwijderd moeten worden.

div#thumbs, met z'n marge aan de bovenkant van 6 px, is een kind van <body>, die geen marge aan de bovenkant heeft. In dat geval worden beide marges gecombineerd, waardoor ook <body> een marge aan de bovenkant krijgt van 6 px.

Als je dit niet begrijpt: schaam je niet. In het rusthuis voor overspannen sitebouwers blijkt bij 73% van de rustenden dit volkomen niet-intuïtieve bedenksel de oorzaak te zijn. Oftewel: dit is echt liederlijk verwarrend en ingewikkeld, ook voor ervaren sitebouwers.

Dit verschijnsel is vaak de oorzaak van niet weg te rammen kieren. Niet weg te rammen, omdat de oorzaak in een totaal ander element blijkt te zitten met een verticale marge. (Vlaag van eerlijkheid: ik heb zojuist in steeds grotere staat van opwinding een kwartier lang gezocht, hoe het kon dat die verrekte #inleiding spontaan 6 px omlaag zakte, zonder enige opdracht daartoe...)

Je kunt dit verschijnsel voorkomen door een border of een padding aan <body> te geven, dan worden de marges niet gecombineerd. (Ik zei toch dat het ingewikkeld was?)

Waar het op neerkomt: <body> heeft dus, via div#thumbs, ook een marge aan de bovenkant van 6 px gekregen. En omdat div#inleiding is gepositioneerd ten opzichte van <body>, staat div#inleiding ook 6 px omlaag. Je hoeft geen top: 0; op te geven, omdat dat de standaardwaarde is.

(Even serieus: er zijn trouwens goede redenen voor dit ogenschijnlijk vreemde gebeuren. Je vergist je er alleen snel mee.)

.foto

De elementen met class="foto". De <span>'s waar de grote afbeeldingen in staan.

width: 480px; height: 360px;

Dit zijn de maten van de grote afbeeldingen. Voor de staande afbeeldingen worden die iets hieronder bij .staand .foto aangepast.

position: absolute;

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

left: 258px;

Rechts van de thumbnails neerzetten. In browservensters met een minimumbreedte van 760 px is er voldoende ruimte om de grote afbeelding niet op, maar naast de thumbnails neer te zetten.

Omdat de thumbnails 6 px vanaf de bovenkant van het venster staan, is het netter als de grote afbeeldingen daar ook worden neergezet. Dat gebeurt ook. Hoe dat kan, zonder dat iets als top of margin-top wordt gebruikt, staat bij #inleiding beschreven onder left: 376px;.

.staand .foto

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

De elementen met class="foto" die binnen een element met class="staand" zitten. De <div>'s die bij de twee staande foto's horen, hebben een extra class 'staand' gekregen. Binnen deze <div>'s zit maar één element met class="foto": de <span> met de grote afbeelding. Deze selector heeft dus betrekking op de staande foto's.

width: 360px; height: 480px;

Dit zijn de maten van de staande grote afbeeldingen.

left: 376px;

Bij .foto hierboven zijn deze <span>'s met left: 258px; rechts van de thumbnails neergezet. Hier wordt die afstand vergroot, omdat bij de staande afbeeldingen het onderschrift niet onder, maar tussen de afbeelding en de thumbnails wordt neergezet.

.foto::after

{display: none;}

Bij .foto::after wordt met behulp van een bij .foto gemaakt pseudo-element de onderkant van het browservenster verborgen, als een grote afbeelding wordt getoond. Dat is in vensters met een minimumbreedte van 760 niet nodig. Met display: none; wordt dit pseudo-element uitgeschakeld.

.tekst

De elementen met class="tekst". De <span>'s waar de onderschriften in zitten.

width: 480px;

De grote afbeeldingen zijn 480 px breed. Even breed maken. Voor onderschriften bij staande foto's wordt dit iets lager bij .staand .tekst aangepast.

height: auto;

Voor smalle browservensters heeft span.tekst bij .tekst een hoogte van 3 rem gekregen, zodat de plaats kan worden afgestemd op die van de grote afbeeldingen. Dat gebeurt hieronder met behulp van top, dus dit is niet meer nodig.

min-height: 84px;

Met een minimumhoogte van 84 px staat de onderkant van de <span> met het onderschrift altijd netjes gelijk met de onderkant van de thumbnails.

Als de lettergrootte wordt vergroot, kan de tekst buiten de <span> komen te staan. De <span> heeft een achtergrondkleur, maar de <span> groeit niet mee als met height een gewone hoogte wordt gegeven. Daardoor groeit ook de achtergrondkleur niet mee, waardoor de zwarte tekst moeilijk leesbaar wordt op de paarse achtergrond.

Door een minimumhoogte te gebruiken in plaats van een gewone height, groeit ook de <span> en dus de achtergrondkleur mee bij een andere lettergrootte.

font-size: 1em;

Hier is genoeg ruimte voor een letter van normale grootte.

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.

padding: 3px;

Kleine ruimte tussen tekst en buitenkant van de <span>.

position: absolute;

Om de <span> op de juiste plaats neer te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier <body>. Omdat ook span.foto, waarin de grote afbeeldingen staan, wordt gepositioneerd ten opzichte van <body>, worden onderschrift en afbeelding indirect ook ten opzichte van elkaar gepositioneerd. Waardoor het onderschrift altijd netjes onder de grote foto kan worden neergezet.

top: 366px;

Onder de grote afbeelding neerzetten. Voor onderschriften bij staande foto's wordt dit iets lager bij .staand .tekst aangepast.

bottom: auto;

Omdat hier met behulp van top van bovenaf wordt gepositioneerd, is bottom niet meer nodig.

div[id^="thumb-"]:hover .tekst, div[id^="thumb-"]:focus .tekst

div[id^="thumb-"]: alle <div>'s die een id hebben die begint met 'thumb-'. Dat zijn de 34 <div>'s boven de thumbnails. Hoe dit deel van de selector precies werkt, wordt bij div[id^="thumb-"] besproken.

Als over een van deze <div>'s wordt gehoverd, of als een van deze <div>'s focus heeft, doe dan iets met de daarin zittende elementen met class="tekst". Dat is hier maar één element: de <span> met het onderschrift.

background: #ffffcf;

Achtergrondkleurtje.

Normaal genomen zou ik dat hebben opgegeven bij .tekst, waar een groot deel van de rest van de css voor deze <span>'s ook is opgegeven. Dat kan echter niet, omdat de <span> al op het scherm staat. Je ziet hem niet, maar hij is er wel. Als daar al een achtergrondkleur zou worden gegeven, zou je de <span> wel zien. Vandaar dat in dit geval pas een achtergrondkleur wordt gegeven, als het onderschrift getoond moet worden.

Het is een goede gewoonte om bij een achtergrondkleur ook een voorgrondkleur op te geven. De voorgrondkleur is onder andere de kleur van de tekst. 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.

In dit geval is de voorgrondkleur al bij .tekst opgegeven, zodat ook dit is geregeld.

left: 258px;

Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier <body>. Op deze positie komt de linkerkant van het onderschrift gelijk te staan met de linkerkant van de grote afbeelding.

.staand .tekst

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

De elementen met class="tekst" die binnen een element met class="staand" zitten. De <div>'s die bij de twee staande foto's horen, hebben een extra class 'staand' gekregen. Binnen deze <div>'s zit maar één element met class="tekst": de <span> met het onderschrift. Deze selector heeft dus betrekking op de onderschriften bij de staande foto's.

width: 110px;

De onderschriften bij de staande grote afbeeldingen worden niet onder, maar naast de afbeelding gezet. Met deze breedte passen ze daar netjes naast.

min-height: 480px;

De staande afbeeldingen zijn 480 px hoog. Door de <span> minimaal deze hoogte te geven, wordt de achtergrondkleur ook altijd minimaal 480 px hoog, zodat deze even hoog is als de staande afbeelding.

Bij gebruik van height groeit de <span> niet mee bij een grotere lettergrootte. De tekst kan hierdoor buiten de <span> komen te staan, zonder dat de achtergrondkleur mee groeit. Door een minimumhoogte te gebruiken groeit de <span> en dus de achtergrondkleur daarvan mee met de lettergrootte.

top: 0;

Bij .tekst is voor de onderschriften top: 366px; opgegeven. Dat is prima voor de onderschriften die onder de grote afbeeldingen komen. Maar bij de staande afbeeldingen moet het onderschrift bovenaan komen te staan.

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

css voor (vensters minimaal 481 en maximaal 759 px breed) of (minimaal 360 px breed en hoge resolutie)

@media screen and (min-width: 481px) and (max-width: 759px), screen and (min-width: 360px) and (-webkit-min-device-pixel-ratio: 1.5), screen and (min-width: 360px) and (min-resolution: 144dpi)

Omdat deze media query (mede door toedoen van Apple) nogal ingewikkeld is, verwijs ik niet naar een eerdere uitleg, maar beschrijf hem hier volledig opnieuw.

De css die binnen deze media query staat zorgt ervoor dat op een hogeresolutiescherm, of als de grote afbeelding wordt vergroot, een betere kwaliteit afbeelding wordt gebruikt.

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

Er zijn hier drie voorwaarden. Als aan één van die voorwaarden wordt voldaan, is de hieronder staande css van toepassing op deze browservensters: als aan ... OF ... OF ... OF ... is voldaan, pas dan de hieronder staande css toe. In zo'n regel gebruik je niet het woord 'of', maar een komma.

De eerste voorwaarde is:

screen and (min-width: 481px) and (max-width: 759px)

De tweede voorwaarde is:

screen and (min-width: 360px) and (-webkit-min-device-pixel-ratio: 1.5)

De derde voorwaarde is:

screen and (min-width: 360px) and (min-resolution: 144dpi)

screen: in alle drie de voorwaarden hetzelfde. Deze regel geldt alleen voor schermweergave.

and: ook dit komt in alle drie de voorwaarden voor. Er komt nog een voorwaarde, waaraan moet worden voldaan. Het wordt in elk van de drie voorwaarden twee keer gebruikt. Daarom moet bínnen elk van deze drie voorwaarden ook weer aan drie voorwaarden worden voldaan. Aan de eerste voorwaarde bijvoorbeeld is pas voldaan als het een scherm is én een minimumbreedte van 481 px én een maximumbreedte van 759 px heeft.

Na het gemeenschappelijke begin verschillen de drie voorwaarden.

(min-width: 481px) and (max-width: 759px): de eerste voorwaarde. Het browservenster moet minstens 481 px en maximaal 759 px breed zijn. Oftewel: de breedte ligt tussen 480 en 760 px.

(min-width: 360px) and (-webkit-min-device-pixel-ratio: 1.5): de tweede voorwaarde. Deze is speciaal voor Safari en de browsers op iOS (omdat die gebruik maken van de weergave-machine van Safari). Apple houdt zich hier niet aan de standaard, maar gebruikt een eigen bedenksel: het deel dat met -webkit- begint. Het browservenster moet minstens 360 px breed zijn. De dichtheid van de pixels moet minstens anderhalf keer zo groot zijn als normaal. Oftewel: een hogeresolutiescherm, wat Apple 'retina' noemt.

(min-width: 360px) and (min-resolution: 144dpi): de derde voorwaarde. Deze geldt voor alle browsers, behalve Safari en de browsers op iOS. Het browservenster moet minstens 360 px breed zijn en er moeten minstens 144 dots per inch zijn. Oftewel: een hogeresolutiescherm.

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 aan het begin van dit stukje weggevallen, maar het geheel ziet er zo uit:

@media screen and (min-width: 481px) and (max-width: 759px), screen and (min-width: 360px) and (-webkit-min-device-pixel-ratio: 1.5), screen and (min-width: 360px) and (min-resolution: 144dpi) { 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 }.

Deze css is voor hogeresolutieschermen. Voor die schermen worden andere afbeeldingen gebruikt, omdat deze schermen een (veel) betere kwaliteit weer kunnen geven. Er is meer over te lezen bij Hogeresolutieschermen.

Daarnaast is deze css voor browservensters met een breedte tussen 480 en 760 px, omdat daar de grote foto's worden vergroot. En een foto vergroten in een browser levert meestal geen echt fraai resultaat op. Je kunt er meer over lezen bij Als het browservenster tussen de 480 en 760 px breed is, maar in feite levert het in de browser vergroten van een foto dezelfde problemen op als het tonen van een gewone foto op een hogeresolutiescherm.

In beide gevallen, voor hogeresolutieschermen en vergrotingen, wordt een afbeelding gebruikt die twee keer zo groot is als op een gewoon scherm of zonder vergroten. Op een hogeresolutiescherm wordt die grotere foto twee keer zo klein weergegeven, waardoor de afmetingen van de foto even groot zijn als bij de gewone foto. Maar de kwaliteit is veel beter.

Als de foto met grotere afmetingen moet worden weergegeven, moet worden vergroot, is dat ook geen probleem. Want de nu gebruikte foto ís eigenlijk al groter. De grotere foto kan wel te groot zijn voor het venster van de browser, maar dat is geen probleem, want verkleinen gaat wel goed in de browser.

#thumb-1:hover .foto, #thumb-1:focus .foto

{background-image: url(../016-pics/foto-01-2x.jpg);}

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

#thumb-34:hover .foto, #thumb-34:focus .foto {background-image: url(../016-pics/foto-34-2x.jpg);}

Bij hoveren over of focus van één van de 34 <div>'s boven een thumbnail de grote afbeelding weergeven. Dit werkt precies hetzelfde als bij #thumb-1:hover .foto, #thumb-1:focus .foto. Het enige verschil is dat een andere afbeelding wordt gebruikt. Bij de 'normale' weergave wordt voor bijvoorbeeld de eerste afbeelding 'foto-01.jpg' gebruikt, hier 'foto-01-2x.jpg'.

JavaScript

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

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

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

document.getElementsByTagName("body")

Zoek naar de elementen met de tag <body>. Jij en ik weten dat er maar één <body> is, maar een browser is nou eenmaal niet zo slim, dus die zoekt trouwhartig naar álle <body>'s. En vindt er uiteraard maar eentje.

[0]

De gevonden tags worden geretourneerd in de vorm van een lijst. Als er bijvoorbeeld honderd <div>'s zouden worden gevonden, heeft deze lijst honderd ingangen. Zo'n ingang kun je aanspreken door het volgnummer te gebruiken. En omdat computers dol zijn op '0', is het volgnummer van de eerste ingang '0', en geen '1'.

Uiteraard is er maar één <body> gevonden. Het volgnummer van die <body> is dus '0', de eerste ingang.

document.getElementsByTagName("body")[0]

Beide samen: doe iets met het element <body>.

addEventListener

Voeg aan <body> een 'eventlistener' toe. Dat is een ding dat luistert, of er iets gebeurt. Zo'n gebeurtenis kan een aanraking van het scherm zijn, een liefdevolle aai van de muis, een ram op het toetsenbord, van alles.

"touchstart"

In dit geval wordt naar het begin van een aanraking van het touchscreen geluisterd. Dat is nog niet zo interessant, het wordt pas echt opwindend wat er ná die eerste, inleidende aanraking gaat gebeuren... Vinden zij elkaar, of wordt het moord- en doodslag?

function () {return null; }

Helaas, ze vinden elkaar niet én het wordt geen moord- en doodslag.

function() is gewoon een soort aankondiging dat er iets gaat gebeuren. Erachter tussen de accolades staat, wat er gaat gebeuren: return null;. Doe niets. Helemaal niets. Vanavond niet, schat, ik heb hoofdpijn.

iOS heeft nogal moeite met het omzetten van :hover en dergelijke naar aanrakingen op een touchscreen. Applefans zullen ongetwijfeld zeggen dat het veel beter werkt dan op andere systemen, maar normale mensen worden er knettergestoord van.

In feite wordt hier gewoon gezegd: als het scherm wordt aangeraakt, blijf dan niet dom tot het jaar 3017 wachten op wat er verder gebeurt, maar reageer gelijk. Zonder dit stukje JavaScript openen de grote afbeeldingen en onderschriften niet, omdat de browser blijft wachten op het vervolg van de aanraking.

Bij de uitleg van deze code zijn allerlei haakjes en dergelijke weggelaten, want dat voert hier te ver. Als je je in dat soort dingen wilt verdiepen, kun je beter naar sites gaan die meer voor JavaScript zijn bedoeld.