Skip links en inhoudsopgave

Tekst verticaal weergeven - uitleg

Laatst aangepast: .

Op twee verschillende manieren gedraaide tekst

Korte omschrijving

Met behulp van de css-eigenschappen writing-mode of transform: rotate() tekst verticaal weergeven.

BELANGRIJK

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

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

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

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

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

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

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

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

Opmerkingen

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

Dit voorbeeld 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

Soms kan het handig (of gewoon leuk) zijn om tekst verticaal weer te geven. Er zijn twee css-eigenschappen die hiervoor zijn te gebruiken: writing-mode en transform: rotate(). De werking van deze twee eigenschappen verschilt op essentiële punten fors. Het verschil heel kort samengevat: writing-mode werkt op de tekst zelf, transform: rotate() werkt op het element, waar de tekst in zit.

writing-mode

Met writing-mode gedraaide tekst

writing-mode is eigenlijk bedoeld voor talen die van boven naar onder, in verticale richting, worden geschreven. Maar het is ook prima bruikbaar om gewone westerse tekst verticaal weer te geven.

Op de afbeelding staat een <div>, waarbinnen de tekst met behulp van writing-mode verticaal wordt weergegeven. Alleen de tekst wordt verticaal weergegeven, de <div> zelf gedraagt zich als een volkomen normale <div>. Als aan de <div> een hoogte of breedte is gegeven, verandert daar niets aan.

De border die de <div> heeft gekregen, is precies hetzelfde als de border bij de <div>'s met horizontale tekst.

Als tekst niet past kan worden gescrold

Ook eigenschappen als overflow werken op de normale manier, behalve dat soms de richting is veranderd. Op de afbeelding is de tekst zo sterk vergroot, dat deze niet meer binnen de <div> past. overflow is op auto gezet.

De oranje <div> met daarin gewone horizontale tekst kan in verticale richting worden gescrold. Afhankelijk van de browser kan er eventueel een verticale scrollbalk rechts van de <div> verschijnen. Dit is zoals elke fatsoenlijk opgevoede <div> zich gedraagt.

De witte <div> met verticale tekst kan in horizontale richting worden gescrold. Wat ook logisch is, want de tekst komt links buiten de <div> te staan. Afhankelijk van de browser kan er eventueel een horizontale scrollbalk onderaan de <div> verschijnen.

Op touchscreens kan de <div> vaak niet worden gescrold. Bij gebruik van overflow: auto;, zoals op de afbeelding hierboven, kan hierdoor in smallere browservensters een deel van de inhoud van de <div> onbereikbaar worden. Als je meer dan enkele woorden verticaal wilt weergeven, kun je daarom het best met behulp van media query's in smallere vensters de tekst gewoon horizontaal weergeven. Meer hierover is te vinden bij Bekende problemen (en oplossingen).

transform: rotate()

Met transform: rotate() gedraaide tekst

Bij transform hoort een aantal functies, waarmee het uiterlijk van de pagina kan worden veranderd. Eén van die functies is rotate(), waarmee een element kan worden gedraaid. Tussen de haakjes wordt het aantal graden opgegeven, waarmee het element moet worden gedraaid. Op de afbeelding is de witte <div> negentig graden gedraaid met behulp van transform: rotate(90deg);. Je kunt ook een ander aantal graden opgeven. Bij negentig graden komt de <div> precies verticaal te staan.

Anders dan writing-mode werkt transform op de <div> zelf, niet op de tekst erin: de hele <div> wordt gedraaid. Dat is op de afbeelding ook duidelijk te zien, want de <div> staat echt gedraaid ten opzichte van de <div>'s ernaast.

De <div>'s hebben borders, maar niet aan alle vier de kanten. Zolang de <div>'s netjes in dezelfde richting staan, lijken er overal borders aanwezig te zijn. Bij de gedraaide <div> mist aan een aantal kanten de border. De hele <div> wordt gedraaid, met border en al, waardoor je nu kunt zien dat niet aan alle kanten een border aanwezig is.

Hoogte en breedte van de <div> blijven hetzelfde. Dat wil zeggen: wat eerst de hoogte was, is nu de breedte, en wat eerst de breedte was, is nu de hoogte. Dat is fundamenteel anders dan bij writing-mode, waar de <div> zelf niet wordt gedraaid.

In smallere browservensters kan een deel van het gedraaide element buiten het venster komen te vallen. Met overflow: auto; kan op de desktop eventueel worden gescrold, hoewel dit bepaald niet handig is. Maar op veel touchscreens kan niet worden gescrold, of levert dit problemen op. Als je meer dan enkele woorden verticaal wilt weergeven, kun je daarom het best met behulp van media query's in smallere vensters de tekst gewoon horizontaal weergeven. Meer hierover is te vinden bij Bekende problemen (en oplossingen).

Tekst op en tekst onder de foto

In grotere browservensters wordt met behulp van transform: rotate(90deg); en een absolute positie het bijschrift in verticale richting rechts op de foto zelf gezet.

In grotere browservensters kan dat prima, omdat de foto daar groter kan zijn. Maar in kleinere vensters levert dit problemen op vanwege de veel kleinere foto. Het bijschrift zou daar een veel te groot deel van de afbeelding afdekken, als het op de foto wordt gezet. Daarom wordt het in smallere vensters niet op, maar onder de afbeelding gezet, zoals op de afbeelding is te zien.

De voorvoegsels -moz-, -ms- en -webkit-

Voordat een nieuwe css-eigenschap wordt ingevoerd, is er in de regel een experimentele fase. Browsers passen het dan al toe, maar met een aangepaste naam. Tijdens deze fase kunnen problemen worden opgelost en worden veldslagen uitgevochten, over hoe de standaard precies moet worden toegepast.

Als iedereen het overal over eens is en alle problemen zijn opgelost, wordt de officiële naam uit de standaard gebruikt.

De belangrijkste browsers hebben elk een eigen voorvoegsel:

Firefox: -moz-, naar de maker: Mozilla.

Op webkit gebaseerde browsers, zoals Google Chrome, Opera, Safari en Android browser: -webkit-.

(Google Chrome is van webkit overgestapt op een eigen weergave-machine: Blink. Blink gaat geen voorvoegsels gebruiken. Het is echter een aftakking van webkit, dus het zal nog wel even duren voor -webkit- hier helemaal uit is verdwenen. Ook Opera gebruikt Blink.)

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

In dit voorbeeld worden display: flex;, transform, transform-origin, writing-mode en -webkit-overflow-scrolling gebruikt.

Zodra de experimentele fase voorbij is, wordt het voorvoegsel weggelaten. Omdat dat moment niet bij alle browsers hetzelfde is, zet je nu ook al de officiële naam erbij. Deze wordt als laatste opgegeven. Bijvoorbeeld Android browser herkent -webkit-linear-gradient. Zodra Android browser linear-gradient gaat herkennen, zal dit -webkit-linear-gradient overrulen, omdat het er later in staat. Dat ze er beide in staan, is dus geen enkel probleem.

display: flex;

Op dit moment moet je nog het volgende schrijven:

{display: -webkit-flex; display: flex;}

In de toekomst kun je volstaan met:

{display: flex;}

transform

Op dit moment moet je nog het volgende schrijven:

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

In de toekomst kun je volstaan met:

{transform: ...;}

transform-origin

Op dit moment moet je nog het volgende schrijven:

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

In de toekomst kun je volstaan met:

{transform: ...;}

writing-mode

Op dit moment moet je nog het volgende schrijven:

{-ms-writing-mode: ...; -webkit-writing-mode: ...; writing-mode: ...;}

In de toekomst kun je volstaan met:

{writing-mode: ...;}

-webkit-overflow-scrolling

Dit is een apart geval, omdat het hier niet om een eigenschap gaat die uiteindelijk in een standaard gaat komen. Het is een uitbreiding van Apple, waarmee je aan kunt geven of scrollen op een touchscreen vloeiend of schoksgewijs moet gebeuren. Andere browsers hebben dit niet nodig. Daarom is hier de vorm zonder voorvoegsel niet nodig.

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. (Dit geldt dus niet voor het hierboven genoemde -webkit-overflow-scrolling, want hiervan bestaat alleen maar een -webkit-versie.)

Vanwege alle problemen met 'vendor prefixes' worden deze door steeds meer browsers niet meer gebruikt. Nieuwe, experimentele css-eigenschappen zitten inmiddels in bijvoorbeeld Firefox, Google Chrome en Safari achter een zogenaamde vlag: de gebruiker moet iets veranderen in de instellingen, waarna de eigenschap gebruikt (en getest) kan worden. Als alles werkt, zoals het hoort te werken, schakelt de browsermaker de vlag standaard in.

De code aanpassen aan je eigen ontwerp

Toegankelijkheid en zoekmachines

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

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

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

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

Enkele tips die helpen bij toegankelijkheid:

Specifiek voor dit voorbeeld

Getest in

Laatst gecontroleerd op 20 oktober 2016

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

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

Dit voorbeeld is getest op de volgende systemen:

Er is op de aan het begin van dit hoofdstukje genoemde controledatum getest in de meest recente versie van de browser, die op het betreffende besturingssysteem kon draaien. Het aantal geteste browsers en systemen is al tamelijk fors, en als ook nog rekening gehouden moet worden met (zwaar) verouderde browsers, is het gewoon niet meer te doen. Surfen met een verouderde browser is trouwens vragen om ellende, want updates van browsers hebben heel vaak met beveiligingsproblemen te maken.

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

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

Als dat relevant is, is op de desktop ook getest, als JavaScript uitstaat. Eventuele problemen staan hierboven bij Toegankelijkheid en zoekmachines onder het kopje Specifiek voor dit voorbeeld. (Op iOS, Android, Windows Phone en Windows 10 Mobile 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, VoiceOver en ChromeVox.

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 en Firefox op Windows 10.

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

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

ChromeVox is een schermlezer in de vorm van een extensie bij Google Chrome. Er is getest op een systeem met Kubuntu Linux.

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.

UC browser op Android, oudere versies van Android browser en oudere versies van Opera Mini op Android

De <div>'s staan allemaal onder elkaar

De <div>'s zijn met behulp van flex naast en onder elkaar gezet, omdat dit veel voordelen boven float heeft. Inmiddels wordt flexbox (waar flex een onderdeel van is) zo uitgebreid ondersteund, dat het gebruikt kan worden.

Oudere versies van Android browser en Opera Mini op Android ondersteunen flex niet.

UC browser op Android ondersteunt weliswaar een oudere versie van flex, maar daar heb je niets aan, omdat flex-wrap niet wordt ondersteund. UC browser zet daardoor de <p> en de negen <div>'s naast elkaar, waardoor ze onwerkbaar klein worden. De voor UC browser benodigde oudere versie van flex is daarom niet gebruikt.

In deze drie browsers worden <div>'s niet per drie naast elkaar gezet, maar allemaal onder elkaar. Dit is eventueel met kunst- en vliegwerk op te vangen door bijvoorbeeld met JavaScript of @supports te kijken of flex wordt ondersteund en dan, afhankelijk daarvan, in deze browsers float te gebruiken. Echt simpel is dat echter niet, omdat bijvoorbeeld UC browser flex wel, maar flex-wrap niet ondersteunt.

Omdat het in dit voorbeeld om de richting van de tekst gaat, en niet om de positie van de <div>'s, is dit verder zo gelaten. De verticale weergave van de tekst wordt wel gewoon ondersteund in deze browsers.

Oude versies van Opera verdwijnen in rap tempo. Android browser wordt al jaren niet mee meegeleverd met Android. UC browser op Android zal waarschijnlijk binnenkort ook flex op de juiste manier implementeren. Dit probleem zal dus vrij snel zijn uitgestorven.

Alle browsers

In smallere browservensters valt een deel van de verticale tekst in het voorbeeld met writing-mode weg

Als geen hoogte wordt gegeven aan de middelste <div> met de verticale tekst, gedraagt deze zich wat apart. Een <div> wordt normaal genomen automatisch even breed als z'n ouder. Maar in deze <div> is de tekst van richting veranderd, waardoor deze <div> zich anders gedraagt. In dit geval neemt niet de breedte, maar de hoogte van de <div> toe. In sommige browsers wordt alle tekst op één lange regel gezet, in andere op twee of drie regels. Maar de <div> wordt hoe dan ook behoorlijk hoog.

Om dit enigszins in de hand te houden, is aan de <div> bij #een div een hoogte gegeven. Daardoor kan in kleinere browservensters een (groot) deel van de inhoud wegvallen. Als je dit 'in het echt' wilt gebruiken, moet dit uiteraard worden voorkomen.

Je zou overflow op auto kunnen zetten, maar binnen een <div> kan op veel touchscreens niet worden gescrold. In Internet Explorer 11 en Edge kan de <div> op een touchscreen worden gescrold, behalve op Windows Phone 8.1. In Firefox en Chrome op Android kan de <div> ook worden gescrold. In alle andere geteste browsers kan de <div> niet worden gescrold op een touchscreen. Dat betekent dat tekst en dergelijke die links de <div> staat, volledig onbereikbaar is.

(Op iOS kan de <div> ook worden gescrold, maar zodra je ook maar 'n heel klein beetje inzoomt, kan de <div> niet meer worden gescrold. Waardoor mensen die iets slechter zien de tekst niet kunnen bekijken. Scrollen binnen een element is een al jaren bestaand probleem op iOS. Het is volstrekt onduidelijk, of dit ooit opgelost gaat worden, omdat Apple niet of nauwelijks reageert op de enorme hoeveelheid klachten hierover.)

In het voorbeeld is op het bovenstaande niet gelet en gewoon overflow: auto; gebruikt, waardoor er tekst verdwijnt in smallere browservensters. Hopelijk wordt hierdoor beter duidelijk, waarom je hier op moet letten.

Mogelijke oplossingen:

* Zet hoe dan ook niet meer tekst en dergelijke in de <div>, dan erin past. Als alles gewoon in de <div> past, valt er ook niets weg. Waterdicht is dit niet, want een grotere letter kan nog steeds problemen opleveren. (Zoomen kan wel altijd zonder problemen.)

* Haal de bij #een div opgegeven hoogte en overflow weg. Nu is de volledige inhoud van alle <div>'s te zien. De <div> met de verticale tekst kan nu echter (heel erg) hoog worden. Omdat gebruik is gemaakt van flexbox om de <div>'s naast elkaar te zetten, worden de <div> links en rechts van de <div> met de verticale tekst in dat geval ook hoger. (Wat er precies gebeurt als je hoogte en overflow weghaalt, wordt uitgebreider besproken bij #een div.)

* De enige afdoende oplossing: schakel met behulp van media query's writing-mode uit in smallere browservensters. De <div> gedraagt zich dan als een normale <div> en groeit gewoon mee met de hoeveelheid tekst en dergelijke en/of de lettergrootte. Je moet dan wel de bij #een div opgegeven hoogte en overflow verwijderen, want anders groeit de <div> niet altijd genoeg mee met de tekst. Deze methode is in dit voorbeeld, overigens om andere redenen, gebruikt bij het bijschrift bij de foto: in vensters smaller dan 640 px wordt dit gewoon horizontaal weergegeven.

Problemen met scrollen als bij het voorbeeld met transform de inhoud te groot is voor de <div>

Een deel van de tekst links verdwijnt

Bij gebruik van transform: rotate(); wordt niet de tekst, maar de <div> – met alles wat erin zit – gedraaid. Als de <div> breder is dan het venster van de browser, kan dat problemen opleveren.

Op de afbeelding staat een smartphone met een breedte van 320 px. In zo'n venster worden de <div>'s heel hoog en smal. Dat is niet echt fraai, maar voor dit voorbeeld maakt dat weinig uit.

De met behulp van transform gedraaide <div> is hierdoor echter breder (eigenlijk: hoger) geworden, dan het venster breed is. Dit is, op z'n zachtst gezegd, niet ideaal, want nu valt een deel van de inhoud van de <div> links en rechts buiten het browservenster.

Het deel dat rechts buiten het venster valt, kan worden gezien door horizontaal te scrollen. Maar het deel dat links buiten het venster valt, is op geen enkele manier zichtbaar te maken.

Om dit te voorkomen is bij #twee div:nth-of-type(5) een maximale hoogte van 100 vw gegeven aan de <div> gegeven. 100 vw is de breedte van het browservenster, ongeacht wat er waar dan ook aan andere maten is opgegeven. vw is altijd rechtstreeks ten opzichte van het browservenster. Met max-height: 100vw; wordt de hoogte van de <div> nooit meer dan de breedte van het venster. (De hoogte, want als de <div> wordt gedraaid, wordt de hoogte in feite de breedte.)

Door ook nog overflow: auto; op te geven is tekst en dergelijke die niet in de <div> past nu in principe met scrollen zichtbaar te maken. 'In principe', want dat scrollen werkt maar heel beperkt.

Op de desktop kan de <div> worden gescrold, maar dat is praktisch van weinig nut. Er zullen maar weinig desktops zijn met een scherm dat zo smal is.

Op een touchscreen is scrollen van deze gedraaide <div> een heel ander verhaal. In Internet Explorer 11 en Edge kan de <div> op een touchscreen worden gescrold, behalve op Windows Phone 8.1. In Firefox en Chrome op Android kan de <div> ook worden gescrold. In alle andere geteste browsers kan de <div> niet worden gescrold op een touchscreen. Dat betekent dat tekst en dergelijke die links buiten het browservenster staat, volledig onbereikbaar is.

(Op iOS kan de <div> ook worden gescrold, maar zodra je ook maar 'n heel klein beetje inzoomt, kan de <div> niet meer worden gescrold. Waardoor mensen die iets slechter zien de tekst niet kunnen bekijken.)

Er zijn 'n paar oplossingen mogelijk.

* Zet niet te veel tekst en dergelijke in de <div>. Als er niet te veel in zit, hoeft de <div> niet gescrold te worden. Als de hele pagina wordt ingezoomd, en daarmee ook de <div>, levert dat geen problemen op. Het probleem doet zich alleen voor, als binnen de <div> zelf gescrold moet worden.

* Zet de <div>, of wat er ook geroteerd wordt, niet te veel naar links.

* De enige afdoende oplossing: schakel met behulp van media query's het roteren uit in smallere browservensters. De <div> gedraagt zich dan als een normale <div> en groeit mee met de inhoud van de <div> en de lettergrootte. Deze methode is in dit voorbeeld, overigens om andere redenen, gebruikt bij het bijschrift bij de foto: in vensters smaller dan 640 px wordt dit gewoon horizontaal weergegeven.

Validatie

writing-mode valideert niet

Het is zelfs nog erger: de css-validator verslikt zich dermate heftig, dat de css helemaal niet meer nagekeken kan worden. Kennelijk is dit nog zo nieuw dat dit tot een voortijdig overlijden door acute doodsschrik van de validator leidt met de volgende tranentrekkende Laatste Woorden: 'org.w3c.css.properties.css3.Css3Style cannot be cast to org.w3c.css.properties.svg.SVGBasicStyle'. Laat ik het zo zeggen: de gemiddelde techneut is geen bloemrijk dichter.

(Om de rest van de css te kunnen valideren, is writing-mode even uitgecommentarieerd.)

Omdat de oorzaak van het niet-valideren volledig bekend is, is dit verder niet van belang. Over enige tijd zal de validator dit gewoon herkennen.

Wijzigingen

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

:

Nieuw opgenomen.

Inhoud van de download en licenties

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

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

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

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

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

tekst-115-dl.html: de pagina met het voorbeeld.

tekst-115.pdf: de uitleg (aangepast aan de inhoud van de download).

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

115-css-dl:

tekst-115-dl.css: stylesheet voor tekst-115-dl.html.

115-js:

picturefill.min.js versie 3.0.2.

Een JavaScript om oudere browsers het in <figure> gebruikte srcset-attribuut te laten herkennen. Voordat dit script wordt gebruikt, is het belangrijk op scottjehl.github.io/picturefill te kijken, of er misschien inmiddels een nieuwere versie van dit script is.

115-pics:

twee dezelfde afbeeldingen, een van 320 px breed en een van 640 px breed.

Als je jezelf toevallig herkent op de foto en graag het origineel wilt hebben, stuur dan even een mail aan info@css-voorbeelden.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. In dit voorbeeld bijvoorbeeld wordt de breedte van <main> (en de daarin zittende <div>'s) aangepast aan de breedte van het venster, net als de plaatsing van het bijschrift bij de foto. Maar die stomme mobiele browser weet dat niet, dus die gaat ervan uit dat ook de al aangepaste pagina 980 px breed is, en verkleint die dan. Dat is ongeveer even behulpzaam als de gedienstige kelner die behulpzaam de stoel naar achteren trekt, net als jij wilt gaan zitten.

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

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

En dat klopt, want de breedte van <main> (en de daarin zittende <div>'s) past zich automatisch aan de breedte van het apparaat aan. Er is op deze pagina niets, wat problemen kan opleveren in een smaller browservenster.

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

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

<div lang="la">

Als opvultekst is Latijnse tekst gebruikt. De taal is van belang voor schermlezers, automatisch afbreken, automatisch genereren van aanhalingstekens, juist gebruik van decimale punt of komma, en dergelijke. Daarom wordt met lang="la" aangegeven dat de tekst binnen deze <div> Latijn is. (En tot mijn niet geringe verbazing blijkt een schermlezer als NVDA dat dan, voor zover ik dat kan beoordelen, op de juiste manier voor te lezen.)

<figure>

<img src="115-pics/koninginnedag-2012-amsterdam-640.jpg" srcset="115-pics/koninginnedag-2012-amsterdam-320.jpg 320w, 115-pics/koninginnedag-2012-amsterdam-640.jpg 640w" sizes="(max-width: 320px) 320px, 640px" alt="Vier meiden verdienen op de Vrijmarkt wat bij als levende standbeelden"> <figcaption>Vondelpark Amsterdam Koninginnedag 2012</figcaption> </figure>

Binnen <figure> staan de foto en het bijbehorende bijschrift. Dit ziet er mogelijk wat ingewikkeld uit, maar in stukken gehakt is het hopelijk wat duidelijker.

<figure> is gewoon een van de nieuwe html5-elementen. Binnen een <figure> kun je iets als een <img> zetten, met in de <figcaption> het bijbehorende bijschrift. Nu is voor zoekmachines, schermlezers, en dergelijke duidelijk dat de tekst in de <figcaption> bij de <img> hoort.

Voor mensen die de afbeelding kunnen zien, is duidelijk wat erop staat. Voor die mensen is het in <figcaption> staande 'Vondelpark Amsterdam Koninginnedag 2012' voldoende. Voor zoekmachines en schermlezers is een alt-tekst toegevoegd: 'Vier meiden verdienen op de Vrijmarkt wat bij als levende standbeelden'. Deze alt-tekst wordt opgepikt door zoekmachines en voorgelezen door schermlezers. Samen met het in <figcaption> staande bijschrift, is de afbeelding nu (enigszins) beschreven. De alt-tekst werkt precies hetzelfde als bij elke 'gewone' <img>. Dat deze <img> binnen een <figure> staat en een srcset-attribuut heeft, maakt niets uit.

<img> is opgeleukt met een nieuw attribuut: srcset. Over dit element is jaren nagedacht, het lost één van de grootste problemen voor responsieve sites op: hoe voorkom je dat een smartphone wordt opgezadeld met een afbeelding voor een breedbeeldscherm. Dat kost enorm veel bandbreedte en het is ook nog 'ns heel traag.

Hier wordt maar heel beperkt gebruikt gemaakt van srcset, omdat er maar twee afbeeldingen zijn. Eentje voor browservensters van 320 px en smaller, en eentje voor vensters breder dan 320 px. Je kunt bijvoorbeeld ook een betere kwaliteit afbeelding opgeven voor hogeresolutieschermen, maar dat gebeurt hier allemaal niet, omdat het om de verticale tekst gaat en niet om de afbeelding.

Het eerste deel van <img> is hetzelfde, zoals het altijd al was:

img src="115-pics/koninginnedag-2012-amsterdam-640.jpg"

Gewoon een afbeelding. Als een browser het attribuut srcset niet kent, wordt srcset genegeerd en wordt deze src gebruikt. De naam van de afbeelding is 'koninginnedag-2012-amsterdam-640.jpg'. Dat is gewoon een naam, met daarachter het getal '640'. Die '640' geeft de breedte van de afbeelding aan. Dat hoeft niet, maar het is een simpele manier om verschillende maten van dezelfde afbeelding te kunnen onderscheiden. Bovendien hoef je nu de breedte niet te onthouden, wat voor mensen met mijn kwaliteit geheugen een niet te versmaden voordeel is.

srcset="115-pics/koninginnedag-2012-amsterdam-320.jpg 320w, 115-pics/koninginnedag-2012-amsterdam-640.jpg 640w" sizes="(max-width: 320px) 320px, 640px"

Hier wordt het mogelijk wat griezelig, want dit is relatief nieuw en ziet er, als je het niet kent, nogal chaotisch uit. Maar ook hier helpt het weer, als je het attribuut in stukjes hakt.

Als een browser dit nieuwe attribuut nog niet kent, wordt het genegeerd en wordt de afbeelding uit de gelijk achter <img staande src gebruikt.

Het eerste deel van srcset bestaat uit een lijstje met afbeeldingen:

"115-pics/koninginnedat-2012-amsterdam-320.jpg 320w, 115-pics/koninginnedag-2012-amsterdam-640.jpg 640w"

De namen van de afbeeldingen worden op de gebruikelijke manier weergegeven, gescheiden door een komma. De namen eindigen op '320' en '640'. De eerste afbeelding is 320 px breed, de tweede is 640 px breed (en ook hoger dan de eerste). Die '320' en '640' hoeft niet, maar is een simpele manier om de verschillende maten uit elkaar te houden. In dit geval worden er maar twee afbeeldingen gebruikt, omdat het in dit voorbeeld niet om de afbeelding gaat, maar om de verticale tekst.

Achter de naam staat de breedte van de afbeelding: 320w en 640w. De 'w' staat voor 'width' (breedte) en is gewoon het aantal px dat de afbeelding breed is. (Er zijn meer eenheden mogelijk, dat is de reden dat niet gewoon 'px' wordt gebruikt.)

De twee afbeeldingen zijn hier hetzelfde, maar als je om een of andere reden twee volkomen verschillende afbeeldingen wilt gebruiken, is daar niets op tegen. Je zou dus bijvoorbeeld naar een kleiner browservenster een kleiner deel van de afbeelding kunnen sturen, waarop alleen de belangrijkste delen van de afbeelding staan.

Achter het lijstje met namen staat een tweede deel:

sizes="(max-width: 320px) 320px, 640px"

Achter het sleutelwoord sizes staan ook hier weer twee waarden, gescheiden door een komma, maar dat mogen ook meer waarden zijn. De waarden 320px en 640px geven de breedte aan, waarop de afbeelding moet worden weergegeven.

Bij de eerste waarde 320px staat een voorwaarde: (max-width: 320px). Dat wil zeggen dat de afbeelding in browservensters met een maximale breedte van 320 px op een breedte van 320 px wordt weergegeven.

Bij de tweede waarde 640px staat geen voorwaarde. Dat betekent dat deze breedte voor alle overige browservensters wordt gebruikt, dus alle vensters die breder dan 320 px zijn.

Met srcset wordt niet precies opgegeven, welke afbeelding moet worden gebruikt. Dat beslist uiteindelijk de browser. De browser krijgt een lijstje met beschikbare afbeeldingen, met daarbij de breedte van die afbeeldingen. Daarnaast wordt de browser verteld, hoe groot die afbeeldingen bij bijvoorbeeld een bepaalde breedte van het browservensters moet worden weergegeven.

Op bijvoorbeeld een desktopscherm met gewone resolutie en een breedte van 1280 px zal dat normaal genomen de afbeelding van 640 px breed zijn. Op een tablet met een breedte van 1024 px ook. Maar bij een slechte verbinding kan de browser er bij de tablet toch voor kiezen om de kleinere afbeelding te gebruiken, omdat die sneller kan worden gedownload. Op een smal hogeresolutiescherm kan toch een grotere afbeelding worden gedownload en verkleind worden weergegeven, omdat dat scherper is.

De bedoeling van srcset is om de browser voldoende informatie over afbeelding en grootte van weergave te geven, om de beste keuze te kunnen maken.

De achter sizes opgegeven breedte kan worden overruled door een breedte in de css op te geven, maar dat zal meestal niet zo zinvol zijn.

Bij img wordt wel een maximumbreedte van 100% opgegeven om te voorkomen dat de afbeelding breder is dan het venster van de browser. Als het venster breder is dan 320 px, wordt in principe de afbeelding van 640 px breedte gedownload. Als het venster smaller is dan 640 px, zou de afbeelding niet passen. Dat wordt gecorrigeerd met die maximumbreedte.

(Voordat je denkt dat je hallucineert: bij img wordt ook een breedte opgegeven, maar dat heeft te maken met een bug in UC browser op Android en zou niet nodig moeten zijn.)

Oudere browsers kennen srcset niet. Voor veel van deze browsers kan srcset worden geïmiteerd met behulp van JavaScript, waarover meer is te vinden bij JavaScript.

CSS

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

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

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

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

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

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

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

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

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

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

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

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

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

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

css voor alle vensters

/* tekst-115-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.

background: #ff9;

Achtergrondkleurtje.

color: black;

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

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

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

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

Als Arial is geïnstalleerd op de machine van de bezoeker, wordt deze gebruikt, anders Helvetica. Als die ook niet wordt gevonden, wordt in ieder geval een schreefloze letter (zonder dwarsstreepjes) gebruikt.

margin: 0; padding: 0;

Slim om te doen vanwege verschillen tussen browsers.

main

Alle <main>'s. Dat is er maar eentje. De belangrijkste inhoud van de pagina staat hierin. In dit voorbeeld is dat de hele pagina.

display: block;

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

width: 98%;

Normaal genomen wordt een blok-element zoals <main> automatisch even breed als z'n ouder. Hier wordt die breedte beperkt tot 98%, iets minder dan z'n ouder.

Een breedte in procenten is altijd ten opzichte van de ouder van het element. Die ouder is hier <body>. <body> is ook een blok-element en wordt normaal genomen dus ook weer even breed als z'n ouder <html>. Omdat <html> het buitenste element is, wordt dit normaal genomen even breed als het venster van de browser.

Uiteindelijk krijgt <main> dus een breedte van 98% van de breedte van het venster van de browser. Dit geeft net wat ruimte links en rechts van <main>, waardoor de borders rondom de <div>'s zichtbaar zijn, wat mooier is.

max-width: 1500px;

Er staan steeds drie <div>'s naast elkaar, die elk een derde van de breedte van <main> (en dus ook van het browservenster) vullen. In brede vensters worden de <div>'s héél breed. Daarom wordt de breedte van <main> hier beperkt tot 1500 px.

margin: 0 auto;

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

Boven en onder geen marge. Rechts en links auto, wat hier hetzelfde betekent als evenveel. Ongeacht de breedte van het browservenster staat <main> nu altijd horizontaal gecentreerd.

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

main > div

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

<main> <div></div> </main>

De middelste <div> hieronder is geen direct kind van <main>, omdat er een <div> tussen <main> en de binnenste <div> zit:

<main> <div> <div></div> </div> </main>

In dit geval zijn er maar twee <div>'s die een direct kind van <main> zijn: div#een en div#twee. Binnen elk van deze twee <div>'s zitten negen andere <div>'s, maar die zijn geen directe kinderen van <main>. Deze selector geldt dus alleen voor div#een en div#twee.

display: -webkit-flex; display: flex;

Hier staat in feite twee keer hetzelfde: display: flex;. Waarom dat zo is, staat bij De voorvoegsels -moz-, -ms- en -webkit-.

Flexbox is een relatief nieuwe manier om een pagina te lay-outen. Met deze regel wordt van de <div> een 'flex container' gemaakt. Elk direct kind van een flex container is een zogenaamd 'flex item'.

In dit geval zijn de flex containers div#een en div#twee. De flex items zijn de <p> en de negen <div>'s die directe kinderen van div#een en div#twee zijn.

Met behulp van flexbox worden elementen op een bepaalde manier over de pagina verdeeld. In dit geval wordt de <p> over de volle breedte van de <div> neergezet. De negen <div>'s binnen div#een en div#twee worden in series van drie naast elkaar gezet. Datzelfde kan zonder flexbox ook met behulp van float, maar dat heeft allerlei ongewenste bijwerkingen. Als op deze pagina float zou worden gebruikt, is bijvoorbeeld extra css nodig voor wat afstand tussen div#een en div#twee, om maar iets te noemen.

Flexbox heeft de voordelen van float (en nog veel meer), zonder de bijbehorende nadelen.

In UC browser op Android, oudere versies van Android browser en oudere versies van Opera Mini op Android werkt flexbox niet. In die browsers staan de <div>'s onder elkaar. Dat is verder zo gelaten, omdat het hier niet om flexbox, maar om de verticale tekst gaat. Meer hierover is te vinden bij Bekende problemen (en oplossingen).

flex-wrap: wrap; Zoals het er met alleen flex-wrap: wrap uitziet

Ook deze eigenschap hoort bij flexbox. Standaard worden alle flex items, de directe kinderen van een flex container, naast elkaar weergegeven. In dit geval gaat het om de <p> en de negen <div>'s binnen div#een en div#twee.

Op de afbeelding is te zien, wat er gebeurt, als flex-wrap wordt weggehaald: alles staat naast elkaar. Terwijl dat eigenlijk niet kan, omdat de <p> (het meest linkse witte blok) een breedte van 100% heeft. De <div>'s hebben een breedte van 33,33%, dus daarvan zouden er maar drie naast elkaar passen.

Flexbox trekt zich hier echter weinig van aan. Als niet uitdrukkelijk met flex-wrap: wrap; wordt gezegd dat te brede elementen op een nieuwe regel moeten komen te staan, worden ze gewoon naast elkaar gezet. Wel wordt rekening gehouden met de relatieve breedte. De witte <p> links heeft een breedte van 100%. De negen <div>'s hebben een breedte van 33,33%. De <p> is daarom drie keer zo breed als de <div>'s, want 100% is (ongeveer) drie keer zoveel als 33,33%.

Werken met flexbox is even wennen, maar het is al vrij snel veel makkelijker dan dingen als float en absoluut positioneren.

margin-top: 10px;

Kleine ruimte aan de bovenkant.

border-left: black solid 1px;

Links border van 1 px breed.

Rondom div#een en div#twee, en rondom de <p> en de <div>'s binnen div#een en div#twee, staat een border. Waar twee elementen elkaar raken, komen de borders tegen elkaar te staan, waardoor daar een dubbele border van 2 px breed komt te staan.

De simpelste manier om die dubbele border te voorkomen is het weglaten van de border aan één of meer kanten van de <p> en de negen <div>'s. Onder andere bij aan de linkerkant wordt de border weggelaten bij de <p> en de negen <div>'s weggelaten. Nu is er, waar twee <div>'s elkaar raken, geen dubbele verticale border. Maar aan de uiterste kant ontbreekt de border nu helaas ook. Daarom krijgen div#een en div#twee een border links. Deze border sluit prima aan op de andere borders bij <p> en de negen <div>'s.

p

Alle paragrafen. Dat zijn er maar twee, waarin de tekstjes boven de gekleurde <div>'s zitten.

background: white;

Witte achtergrond.

color: black;

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

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

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

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

width: 100%;

Een breedte in procenten is altijd ten opzichte van de ouder. Dat is hier <main>. De <p>'s met de tekst worden dus even breed als <main>. Maar een blok-element zoals een <p> wordt normaal genomen automatisch even breed als z'n ouder, dus eigenlijk zou die 100% helemaal niet nodig moeten zijn. Maar let op de woorden 'normaal genomen'.

Drie divs staan foutief naast elkaar

Hier wordt de <p> niet automatisch even breed als z'n ouder, omdat bij main > div de ouder van

de <p> (dat is div#een of div#twee) is veranderd in een flex container. De <p> is daardoor een flex item geworden.

De <p> wordt daardoor niet breder dan nodig is om de tekst erin weer te geven. Daardoor komen in de ruimte rechts van de <p> twee <div>'s te staan, want ook die zijn veranderd in een flex item. Die <div>'s krijgen bij div div een breedte van 33,33%, dus op één regel passen de <p> en nog twee <div>'s, zoals op de afbeelding is te zien.

De <p> met 'writing-mode: vertical-rl;' hoort bóven de <div>'s te staan, maar staat links naast de eerste twee <div>'s. Door de <p> 100% breed te maken, wordt deze even breed als <main> en komt boven de <div>'s te staan.

margin: 0;

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

border: black solid 1px;

Zwart randje rondom de <p>.

border-left: none;

Het randje links is niet nodig, want div#een en div#twee hebben bij main > div al een randje links gekregen. Als de <p> ook een border links zou krijgen, zou de rand links 2 px breed worden.

padding: 10px 0 10px 20px; De paragraaf met marge en zonder padding aan boven- en onderkant

Iets hierboven is de marge aan boven- en onderkant bij de <p> weggehaald. En hier wordt weer een padding van 10 px aan boven- en onderkant neergezet. Waardoor de <p> weer even hoog wordt als wanneer die marge gewoon niet zou zijn weggehaald.

Je zou kunnen denken dat dit duidt op Samsoniaanse draaikonterij, maar dat is niet zo.

Op de afbeelding staat de <p> met marge en zonder padding aan boven- en onderkant. De hoogte van de <p> is inderdaad ongeveer hetzelfde. Dat is te zien aan het zwarte lijntje links, de linkerborder van de <div> waar de <p> in staat.

Het verschil zit hem in de achtergrondkleur. De achtergrondkleur loopt niet door onder een marge. Vandaar dat de <p> op de afbeelding zo laag lijkt. Onder een padding loopt de achtergrondkleur wel door. Door de marge te vervangen door een padding, krijgt de volle hoogte van de <p> een witte achtergrondkleur.

div div

Alle <div>'s die binnen een andere <div> zitten. Alleen de negen <div>'s die binnen div#een en div#twee zitten, voldoen aan deze selector.

Normaal genomen worden blok-elementen zoals een <div> op een nieuwe regel gezet. Bij main > div zijn ze echter veranderd in zogenaamde 'flex items', waardoor dit niet meer zo is. Ze gedragen zich nu min of meer alsof ze naar links zijn gefloat, maar zonder de nadelen die bij float horen.

background: cyan;

Achtergrondkleur blauw.

De <div>'s hebben een afwisselende achtergrondkleur. <div>'s die een andere achtergrondkleur moeten krijgen, krijgen hieronder eigen css.

color: black;

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

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

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

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

box-sizing: border-box;

Normaal genomen worden een marge, border en padding bij de breedte van een element opgeteld. Hier gelijk onder krijgen de <div>'s een breedte van 33,33%. Hierdoor passen er precies drie <div>'s naast elkaar. (De breedte van drie <div>'s is 99,99%, maar die 0,01% te weinig zie je niet.)

Iets verder hieronder krijgen de <div>'s een rechterborder van 1 px breed. En nog iets lager een padding rechts en links van 3 px. De breedte is dan geen 33,33% meer, maar 3 px + 33,33% + 3 px + 1 px. Hierdoor wordt het totaal van de breedte van de drie <div>'s veel meer dan 100% en passen er nog maar twee <div>'s naast elkaar.

Met deze regel worden marge, border en padding niet bij de breedte opgeteld, maar komen deze binnen de breedte te staan. De breedte van de <div>'s blijft nu 33,33%, waardoor er drie naast elkaar passen.

width: 33.33%;

Een breedte in procenten is altijd ten opzichte van de ouder. Dat is hier <main>. Bij een breedte van 33,33% passen er drie <div>'s naast elkaar. Je houdt dan nog 0,01% over, maar dat zie je niet.

border: black solid;

Randje rondom de <div>'s. Gelijk hieronder wordt de breedte opgegeven.

border-width: 0 1px 1px 0;

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

Kleur en stijl zijn gelijk hierboven al opgegeven. Door de breedte apart op te geven, spaar je in dit geval wat css uit, omdat dit korter is dan het opgeven van twee afzonderlijke volledige borders voor links en onder.

padding: 3px;

Kleine afstand tussen buitenkant en inhoud van de <div>.

#een div

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat.

div div {background: cyan; color: black; box-sizing: border-box; width: 33.33%; border: black solid; border-width: 0 1px 1px 0; padding: 3px;}

Alle <div>'s binnen het element met id="een". De negen <div>'s die bij de bovenste verticale tekst horen.

height: 8em;

Hoogte. Als eenheid wordt de relatieve eenheid em genomen, zodat de hoogte mee verandert met de lettergrootte. Bij een absolute eenheid als px is dat niet het geval.

Normaal genomen wordt geen hoogte aan een <div> gegeven, en daar zijn goede redenen voor. Een blok-element zoals een <div> wordt normaal genomen automatisch precies hoog genoeg, als nodig is om de inhoud ervan weer te kunnen geven. Als je een hoogte aan de <div> geeft, wordt dit proces verstoord.

Ook met een hoogte wordt normaal genomen wordt de inhoud van de <div> nog steeds volledig weergegeven, ook als die niet in de <div> past, omdat overflow standaard op visible staat. Maar bijvoorbeeld een achtergrondkleur, een border, een box-shadow, en dergelijke worden niet groter dan de hoogte van de <div> toestaat. Tekst en dergelijke komen dus buiten die achtergrondkleur, border, box-shadow, en dergelijke te staan. Waardoor de lay-out al snel een forse chaos kan worden.

Toch is dit normaal genomen wat je wilt, omdat in ieder geval alle tekst en dergelijke zichtbaar zijn. Beter een slordige lay-out dan tekst en dergelijke die gewoon volledig verdwijnen.

In dit geval ligt het iets anders. Acht van de negen <div>'s die bij het bovenste voorbeeld horen, gedragen zich als een gewone <div>. Als je geen hoogte opgeeft, worden ze precies hoog genoeg. Precies zoals het hoort.

Zonder correctie wordt de gedraaide div veel te hoog

De negende <div> met de verticale tekst gedraagt zich ook, zoals het hoort. Maar dan zoals het hoort in een taal die verticaal wordt geschreven, zoals Chinees. Bij deze <div> wordt ook de 'breedte' gedraaid, omdat dat logisch is in een verticaal geschreven taal.

Hoe dat eruit ziet, is op de afbeelding te zien. De bovenste en onderste drie <div>'s worden niet hoger dan nodig is om de tekst erin weer te geven. Bij de <div> met de verticale tekst is dat ook zo, maar dan op z'n Chinees. En omdat voor de lay-out flexbox is gebruikt, worden de <div> links en rechts van de <div> met de verticale tekst ook zo hoog.

(Bij iets andere maten van het browservenster of in andere browsers kan het er iets anders uitzien, omdat de tekst op twee of drie regels wordt gezet, maar overal wordt de <div> met de verticale tekst veel hoger dan de andere <div>'s.)

Omdat dit er net niet helemaal ideaal uitziet, is een hoogte aan de <div> gegeven. maar dat brengt weer andere problemen met zich mee.

Tekst staat over elkaar heen

In een breder browservenster gaat het goed, als een hoogte aan de <div> is gegeven, omdat er voldoende ruimte is om alle tekst weer te geven. Maar in smallere vensters gaat het mis.

Op de afbeelding is, in een venster van 320 px breed, aan de <div>'s een hoogte van 8 em gegeven. Aan alle <div>'s, om het 'n beetje symmetrisch en zo te houden. Dat houdt in dat de tekst nu niet meer in de <div>'s past, omdat die heel smal zijn geworden. Omdat overflow standaard op visible staat, is die tekst echter nog wel te zien.

Op de afbeelding wordt het teveel aan tekst van de eerste, tweede, derde, vijfde en zesde <div> niet getoond, omdat die wegvalt onder de eronder staande <div>'s. Bij de onderste drie <div>'s is een klein stukje tekst te zien, maar niet veel, omdat dat wordt afgekapt door de grens van div#een.

Bij de vijfde <div>, die met verticale tekst, gaat het echt grandioos mis. De tekst daarvan staat pontificaal over de vierde <div> heen. Je zou die vierde <div> een hogere z-index kunnen geven, maar dat schiet ook niet op, want dan komt het teveel aan tekst daarvan weer over de zevende <div> te staan. Met een z-index bij de zevende <div> verplaats je het probleem alleen maar. Het eindpunt van deze z-indexen-dans is vermoedelijk een langdurig verblijf in een rusthuis.

Delen van de tekst verdwijnen

Om te voorkomen dat teksten en dergelijke over elkaar heen komen te staan, zou je heel weinig tekst in een <div> kunnen zetten. Maar dan zit je in grotere browservensters weer met enorme leegtes.

In het voorbeeld is het 'opgelost' met het gelijk hieronder opgegeven overflow: hidden;. Op de afbeelding is te zien dat er nu geen overlappingen meer zijn. Maar helaas is nu een (groot) deel van de tekst gewoon verdwenen. Die tekst is op geen enkele manier meer te lezen (tenzij je de broncode gaat bekijken of zoiets, maar je kunt bezwaarlijk op je site zetten dat mensen de tekst even moeten opzoeken in de broncode.)

'opgelost' staat hierboven tussen aanhalingstekens, omdat dit natuurlijk geen oplossing is. Het komt er op neer, dat je grotere hoeveelheden tekst beter niet verticaal weer kunt geven in kleinere browservensters. Als de tekst gewoon horizontaal wordt weergegeven, gedraagt de <div> zich als een normale <div> en wordt de hoogte ervan aangepast aan de inhoud van de <div>.

Verticale tekst is leuk voor 'n paar woorden of zo, maar meer niet. In dit voorbeeld wordt het toch verticaal weergeven in kleinere vensters, om te laten zien tot welke problemen dit kan leiden.

Wel wordt in dit voorbeeld wordt, overigens om andere redenen, het bijschrift bij de foto in smallere vensters niet verticaal weergegeven.

overflow: hidden;

De reden hiervan wordt gelijk hierboven bij height: 8em; beschreven.

div div:nth-of-type(4n + 2)

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat.

div div {background: cyan; color: black; box-sizing: border-box; width: 33.33%; border: black solid; border-width: 0 1px 1px 0; padding: 3px;}

#een div {height: 8em; overflow: hidden;}

div div: da's simpel: gewoon alle <div>'s die binnen een andere div zitten. Dat zijn hier de twee keer negen <div>'s die binnen div#een en div#twee zitten.

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

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

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

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

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

Omdat er in div#een en div#twee negen <div>'s zitten , wordt de berekening negen keer gemaakt (eigenlijk twee keer negen keer, één keer voor div#een en één keer voor div#twee). De negende en laatste berekening is 8 x 2 = 16. Maar alleen de uitkomsten tot en met 9 hebben nut, omdat er maar negen <div>'s in div#een en div#twee zitten. In totaal zijn er wel meer dan negen <div>'s, maar alleen <div>'s met dezelfde ouder tellen mee voor deze berekening.

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

De tweede keer is het resultaat 4 x 1 = 4. Daarachter staat nog + 2. De tweede keer is de volledige berekening dus 4 x 1 + 2 = 6. Oftewel: de zesde <div>.

De derde keer is het resultaat 4 x 2 = 8. Daarachter staat nog + 2. De derde keer is de volledige berekening dus 4 x 2 + 4 = 10. Oftewel: de tiende <div>. Omdat er echter maar negen <div>'s in div#een en div#twee zitten, is een uitkomst van 10 al zinloos, omdat er geen tiende <div> is. Alle hogere uitkomsten zijn dus helemaal zinloos.

In dit geval gaat het om de tweede en de vijfde <div>. Dit zijn de <div>'s die een grijze achtergrond moeten krijgen.

background: #ddd;

Grijze achtergrond.

Normaal genomen zou hier ook een voorgrondkleur, tevens de kleur van de tekst, worden opgegeven, omdat bezoekers eigen kleuren kunnen hebben opgegeven. Bijvoorbeeld omdat ze moeite hebben met te weinig contrast. Als je dan alleen de achtergrond- of voorgrondkleur zou veranderen, bestaat het risico dat de veranderde achtergrond- of voorgrondkleur te veel gaat lijken op de door de bezoeker ingestelde achtergrond- of voorgrondkleur. Door beide kleuren te veranderen, wordt dat risico voorkomen.

Hier is echter al bij div div een zwarte voorgrondkleur opgegeven voor deze <div>'s, dus dat hoeft hier niet nogmaals.

div div:nth-of-type(4n + 3)

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat.

div div {background: cyan; color: black; box-sizing: border-box; width: 33.33%; border: black solid; border-width: 0 1px 1px 0; padding: 3px;}

#een div {height: 8em; overflow: hidden;}

Deze selector is exact hetzelfde als die iets hierboven bij div div:nth-of-type(4n + 2), alleen wordt er nu 3 en geen 2 bij de 4n opgeteld. Waardoor hiermee de derde en zevende <div> worden aangesproken.

background: yellow;

Gele achtergrond.

Normaal genomen zou hier ook een voorgrondkleur, tevens de kleur van de tekst, worden opgegeven, omdat bezoekers eigen kleuren kunnen hebben opgegeven. Bijvoorbeeld omdat ze moeite hebben met te weinig contrast. Als je dan alleen de achtergrond- of voorgrondkleur zou veranderen, bestaat het risico dat de veranderde achtergrond- of voorgrondkleur te veel gaat lijken op de door de bezoeker ingestelde achtergrond- of voorgrondkleur. Door beide kleuren te veranderen, wordt dat risico voorkomen.

Hier is echter al een zwarte voorgrondkleur opgegeven voor deze <div>'s bij div div, dus dat hoeft hier niet nogmaals.

div div:nth-of-type(4n + 4)

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat.

div div {background: cyan; color: black; box-sizing: border-box; width: 33.33%; border: black solid; border-width: 0 1px 1px 0; padding: 3px;}

#een div {height: 8em; overflow: hidden;}

Deze selector is exact hetzelfde als die iets hierboven bij div div:nth-of-type(4n + 2), alleen wordt er nu 4 en geen 2 bij de 4n opgeteld. Waardoor hiermee de vierde en achtste <div> worden aangesproken.

background: orange;

Oranje achtergrond.

Normaal genomen zou hier ook een voorgrondkleur, tevens de kleur van de tekst, worden opgegeven, omdat bezoekers eigen kleuren kunnen hebben opgegeven. Bijvoorbeeld omdat ze moeite hebben met te weinig contrast. Als je dan alleen de achtergrond- of voorgrondkleur zou veranderen, bestaat het risico dat de veranderde achtergrond- of voorgrondkleur te veel gaat lijken op de door de bezoeker ingestelde achtergrond- of voorgrondkleur. Door beide kleuren te veranderen, wordt dat risico voorkomen.

Hier is echter al een zwarte voorgrondkleur opgegeven voor deze <div>'s bij div div, dus dat hoeft hier niet nogmaals.

#een div:nth-of-type(5)

Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat.

div div {background: cyan; color: black; box-sizing: border-box; width: 33.33%; border: black solid; border-width: 0 1px 1px 0; padding: 3px;}

#een div {height: 8em; overflow: hidden;}

#een div: alle <div>'s die binnen een element met id="een" zitten. Dat zijn hier de negen <div>'s binnen div#een.

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

(5): tussen de haakjes staat aangegeven, om welke <div> of <divs>'s het gaat. In dit geval staat er een simpel getal tussen de haakjes. Hiermee wordt het volgnummer van de <div> aangegeven. Het gaat hier om de vijfde <div>.

De hele selector in normale mensentaal: de vijfde <div> binnen div#een. Dit is de <div>, waarbinnen de bovenste verticale tekst staat.

background: white;

Witte achtergrond.

Normaal genomen zou hier ook een voorgrondkleur, tevens de kleur van de tekst, worden opgegeven, omdat bezoekers eigen kleuren kunnen hebben opgegeven. Bijvoorbeeld omdat ze moeite hebben met te weinig contrast. Als je dan alleen de achtergrond- of voorgrondkleur zou veranderen, bestaat het risico dat de veranderde achtergrond- of voorgrondkleur te veel gaat lijken op de door de bezoeker ingestelde achtergrond- of voorgrondkleur. Door beide kleuren te veranderen, wordt dat risico voorkomen.

Hier is echter al een zwarte voorgrondkleur opgegeven voor deze <div>'s bij div div, dus dat hoeft hier niet nogmaals.

-ms-writing-mode: tb-rl; -webkit-writing-mode: vertical-rl; writing-mode: vertical-rl;

Hier staat in feite drie keer hetzelfde: writing-mode: vertical-rl;. Waarom dat zo is, staat bij De voorvoegsels -moz-, -ms- en -webkit-.

(De eerste waarde bij -ms- wijkt af van de twee andere, omdat de specificatie is gewijzigd.)

Hiermee wordt de tekst verticaal weergegeven. De verticaal weergegeven tekst wordt vervolgens weer van rechts naar links weergegeven. (Met vertical-lr zou de verticale tekst van links naar rechts worden weergegeven.)

De tekst in de <div> wordt verticaal weergegeven, de <div> zelf verandert op geen enkele manier van plaats. Hoogte en breedte blijven hetzelfde. Een border aan de bovenkant blijft een border aan de bovenkant. Enz.

#twee div:nth-of-type(5)

Voor deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat.

div div {background: cyan; color: black; box-sizing: border-box; width: 33.33%; border: black solid; border-width: 0 1px 1px 0; padding: 3px;}

#twee div: alle <div>'s die binnen een element met id="twee" zitten. Dat zijn hier de negen <div>'s binnen div#twee.

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

(5): tussen de haakjes staat aangegeven, om welke <div> of <divs>'s het gaat. In dit geval staat er een simpel getal tussen de haakjes. Hiermee wordt het volgnummer van de <div> aangegeven. Het gaat hier om de vijfde <div>.

De hele selector in normale mensentaal: de vijfde <div> binnen div#twee. Dit is de <div> waarbinnen de middelste verticale tekst staat.

background: white;

Witte achtergrond.

Normaal genomen zou hier ook een voorgrondkleur, tevens de kleur van de tekst, worden opgegeven, omdat bezoekers eigen kleuren kunnen hebben opgegeven. Bijvoorbeeld omdat ze moeite hebben met te weinig contrast. Als je dan alleen de achtergrond- of voorgrondkleur zou veranderen, bestaat het risico dat de veranderde achtergrond- of voorgrondkleur te veel gaat lijken op de door de bezoeker ingestelde achtergrond- of voorgrondkleur. Door beide kleuren te veranderen, wordt dat risico voorkomen.

Hier is echter al een zwarte voorgrondkleur opgegeven voor deze <div>'s bij div div, dus dat hoeft hier niet nogmaals.

max-height: 100vw; overflow: auto;

Maximum-hoogte 100 vw. vw is de eenheid voor de breedte van het venster van de browser. 100 vw is de breedte van het venster, 1 vw is 1% van de breedte, 10% is tien procent van de breedte, enz. Met een maximumhoogte van 100 vw kan de <div> dus nooit hoger worden dan de breedte van het venster. Het maakt niet uit of voorouders van de <div> eventueel een bepaalde breedte hebben gekregen: vw wordt altijd rechtstreeks gemeten ten opzichte van de breedte van het venster.

Het lijkt mogelijk vreemd om de hoogte te beperken tot de breedte van het browservenster, maar dat is omdat de <div> wordt gedraaid. En als de <div> is gedraaid, wordt de hoogte van de <div> in feite de breedte.

Dit is alleen van belang in browservensters, waarin de <div> breder is dan het venster. In de praktijk zal dit vooral bij smartphones het geval zijn en als er vrij veel tekst in de <div> staat.

Normaal genomen wordt een <div> automatisch precies hoog genoeg om de inhoud ervan weer te kunnen geven. Dat kan in smallere browservensters een probleem zijn, omdat de <div> dan bij draaien breder wordt dan het venster, waardoor links en rechts tekst en dergelijke buiten het venster komen te staan.

Links en rechts, want standaard wordt bij transform: rotate(); een element om z'n middelpunt gedraaid. Als de gedraaide <div> breder is dan het venster, komt het teveel dus evenveel links als rechts buiten het venster te staan. Je kunt dat draaipunt wel aanpassen met het hier niet gebruikte transform-origin, maar daar is dit niet goed mee op te lossen.

Als tekst rechts buiten het venster van de browser komt te staan, kan die zichtbaar worden gemaakt door scrollen. Niet ideaal, maar in ieder geval kun je het bekijken.

Tekst die links buiten het venster komt te staan, is op geen enkele manier zichtbaar te maken. Wat dat betreft lijkt transform: rotate(); op een absolute positie.

Door de hoogte van de <div> met 100 vw nooit hoger te maken dan het browservenster breed is, wordt voorkomen dat tekst links buiten het venster komt te staan. Maar daarmee wordt nog niet voorkomen dat tekst verdwijnt: de tekst staat nu inderdaad niet meer buiten het venster, maar de tekst is nu gewoon helemaal weg. Niet echt een verbetering.

Met overflow: auto; wordt gezorgd dat het teveel door scrollen van de <div> kan worden bekeken. Althans: dat is het idee. Op veel touchscreens kan de <div> niet of niet goed worden gescrold. Eigenlijk is er maar één goede oplossing, als je meer dan 'n paar woorden verticaal wilt weergeven: geef de tekst in smallere browservensters met behulp van media query's gewoon horizontaal weer. De <div> gedraagt zich dan als een normale <div>, waarbij de hoogte van de <div> mee verandert met de inhoud en de lettergrootte van de <div>.

(Een uitgebreider verhaal over problemen met het scrollen van deze <div> op touchscreens is te vinden bij Bekende problemen (en oplossingen).)

-webkit-overflow-scrolling: touch;

Het veelgeprezen besturingssysteem iOS van Appel heeft een klein, al jaren bestaand, probleempje. Of het ooit wordt opgelost, is onbekend, want Apple reageert nauwelijks of niet op het ontelbare aantal klachten en bugrapporten over dit probleem (en aanverwante problemen).

Als je op iOS scrolt binnen een <div>, gaat dat ongelooflijk houterig. Het is feitelijk onbruikbaar, zo slecht werkt het. Door deze regel wordt het scrollen net zo vloeiend als elders op iOS. Alleen heeft deze eigenschap nogal wat bijwerkingen. Voor zover ik heb kunnen nagaan, waren er geen bijwerkingen in dit voorbeeld. Maar internet staat vol met verhalen over verdwijnende tekst en wat al niet, als deze eigenschap wordt gebruikt. Ik weet niet helemaal zeker, of er echt geen bijwerkingen zijn, want je komt op internet echt de meest bizarre problemen tegen bij gebruik van deze eigenschap. En omdat Apple zwijgt als het graf, is het ook niet mogelijk echt goed op problemen te controleren. Je kunt bij het testen van iets niet álle potentiële bizarre bijwerkingen in álle mogelijke situaties verzinnen.

(Overigens is het beter om scrollen van deze <div> overbodig te maken. De reden daarvan wordt hierboven bij max-height: 100vw; overflow: auto; beschreven.)

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

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

Als je met behulp van transform: rotate(); meer dan 'n paar woorden verticaal wilt weergeven, kan dat grandioos misgaan in smallere browservensters. Je kunt dat verticaal weergeven het best met behulp van media query's beperken tot bredere vensters. Meer hierover is te vinden bij max-height: 100vw; overflow: auto; hier iets boven.

transform heeft een aantal functies die gebruikt kunnen worden om het uiterlijk van een element te veranderen. Een daarvan is rotate(), waarmee een element gedraaid kan worden. Tussen de haakjes komt het aantal graden te staan. Hier is dat aantal 90, waardoor de tekst verticaal komt te staan. Maar als je 'n ander aantal graden neemt, kun je tekst ook schuin, ondersteboven, enz. neerzetten.

Zonder z-index verdwijnt een deel van de tekst

In het voorbeeld verdwijnt een deel van de <div> onder de eronder staande afbeelding, zoals op de afbeelding links is te zien. Dat kan heel makkelijk worden opgelost door een hogere z-index aan de <div> te geven.

Een z-index werkt alleen in sommige omstandigheden. Een van die omstandigheden is het gebruik van transform. Dat is hier het geval, dus een z-index kan probleemloos worden gebruikt. Op de afbeelding rechts heeft de <div> z-index: 10; gekregen, waardoor deze nu boven de eronder staande afbeelding staat.

De middelste div is gedraaid

Met transform: rotate(); wordt de <div> gedraaid. De inhoud van de <div> draait mee met de <div>, maar verandert verder niet. Ten opzichte van de <div> blijft de inhoud op dezelfde plaats staan.

De gedraaide <div> staat op een andere plaats op het scherm, maar de originele positie blijft gewoon bezet, ook al is die nu leeg. Op de afbeelding is op de originele plaats van de <div> de achtergrondkleur van de pagina te zien. De <div> is gedraaid, dus die achtergrondkleur wordt niet meer afgedekt. Maar de lege ruimte, waarin de achtergrondkleur is te zien, is precies even groot als de ruimte die de <div> voor draaiing innam.

Bij div div is aan de rechter‑ en onderkant van de <div> een border gegeven. Deze draaien ook gewoon met de <div> mee, waardoor de borders nu onder en links staan. Hoogte en breedte zijn hetzelfde gebleven, behalve dat nu de hoogte feitelijk de breedte is, en omgekeerd. Als je de <div> breder zou willen maken, moet je dus een grotere hoogte opgeven.

figure

Alle <figure>'s. Dat is er hier maar eentje: de foto en het bijschrift bij de foto zitten erin.

width: 640px;

Breedte. De foto is 640 px breed, dus wordt de <figure> dit ook.

De breedte is hier nodig om de <figure>, en daarmee de erin zittende foto met bijschrift, te kunnen centreren. Bovendien is een breedte nodig om, in browservensters met een minimumbreedte van 640 px, het verticaal weergegeven bijschrift bij de foto de juiste maat te kunnen geven en op de juiste plaats neer te kunnen zetten.

max-width: 100%;

Maximumbreedte.

Hierboven is een breedte van 640 px opgegeven. In browservensters smaller dan 640 px zou dat betekenen dat <figure> – en de daarin zittende foto en bijschrift – breder dan het venster worden. Om dat te voorkomen wordt hier een maximumbreedte opgegeven.

Een breedte in procenten is altijd ten opzichte van de ouder van het element. Die ouder is hier het blok-element <main>. Een blok-element wordt normaal genomen automatisch even breed als z'n ouder. Die ouder is hier <body>, ook weer een blok-element. <body> wordt normaal genomen ook weer even breed als z'n ouder <html>. Omdat <html> het buitenste element is, wordt dit normaal genomen even breed als het venster van de browser.

Uiteindelijk kan <figure> dus niet breder worden dan het venster van de browser. Hierdoor is altijd zonder scrollen de volledige foto met bijschrift te zien, ook in smallere vensters.

margin: 10px auto 20px;

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

Boven een kleine afstand tot de <div> erboven. Onder een marge van 20 px omdat het niet zo mooi is als de <figure>, en daarmee de foto en bijschrift, tot helemaal onderaan het venster van de browser staan.

Links en rechts auto, wat hier hetzelfde betekent als evenveel. <figure> staat hierdoor altijd horizontaal gecentreerd, ongeacht de breedte van het venster van de browser.

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

position: relative;

In browservensters met een minimumbreedte van 640 px wordt het bijschrift bij de foto gepositioneerd ten opzichte van <figure>. Dat kan alleen als <figure> zelf een positie heeft. Omdat hier verder niets wordt opgegeven voor top en dergelijke, heeft dit verder geen enkel gevolg voor <figure> zelf.

img

Alle afbeeldingen. Dat is er hier maar eentje.

display: block; Kier tussen afbeelding en onderschrift

Een <img> is een inline-element, net zoals tekst. Weliswaar een wat bijzonder inline-element, maar dat maakt niet uit. Daardoor heeft een <img> automatisch ook een regelhoogte. De <img> staat standaard op de basislijn, waarop ook tekst wordt neergezet. Dat is iets boven de onderkant van de regelhoogte, want letters als de 'y' en de 'g' steken onder die onderkant uit. De kleine kier die op de afbeelding te zien is tussen de foto en het eronder staande blokje met tekst, is de ruimte voor die uitstekende letters.

Hier is die ruimte niet nodig, want er is helemaal geen tekst aanwezig op de regel, waar de <img> staat. De simpelste manier om dit te verwijderen het veranderen van de <img> in een blok-element.

width: 100%;

Dit is alleen nodig voor UC browser op Android. Er wordt gebruikt gemaakt van twee maten foto's: eentje voor browservensters van maximaal 320 px breed, en eentje voor bredere vensters. Dit wordt uitgebreid beschreven bij <figure>. Om een of andere reden kiest UC browser altijd de kleinere foto, ook in bredere vensters. Dit zorgt ervoor dat ook UC browser in vensters breder dan 320 px de grotere foto gebruikt.

max-width: 100%;

Maximumbreedte.

Een breedte in procenten is altijd ten opzichte van de ouder van het element. Dat is hier <figure>. Bij figure is gezorgd dat <figure> nooit breder dan het venster van de browser kan worden. Met deze regel wordt gezorgd dat <img> nooit breder kan worden dan <figure>, en daardoor dus ook nooit breder dan het venster.

Als, in smalle browservensters, de breedte van de foto wordt aangepast, wordt automatisch ook de hoogte van de foto aangepast, waarbij de juiste verhoudingen van de foto behouden blijven.

figcaption

Alle <figcaption>'s. Dat is er hier maar eentje. Het bijschrift van de foto staat erin.

In browservensters met een minimumbreedte van 640 px wordt het bijschrift verticaal op de foto geplaatst. In smallere vensters zou dit veel te veel van de foto afdekken, daarom wordt het in smallere vensters onder de foto geplaatst.

background: white;

Witte achtergrond.

color: black;

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

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

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

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

text-align: center;

Tekst horizontaal centreren.

border: black solid 1px;

Randje.

padding: 3px;

Kleine afstand tussen tekst in en buitenkant van <figcaption>.

css voor vensters minimaal 640 px breed

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

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

De css die binnen deze media query staat, geldt alleen voor vensters die minimaal 640 px breed zijn. In deze bredere vensters wordt het bijschrift bij de foto in verticale richting op de foto gezet.

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

screen: deze regel geldt alleen voor schermweergave.

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

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

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

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

figcaption

Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat.

figcaption {background: white; color: black; text-align: center; border: black solid 1px; padding: 3px;}

Alle <figcaption>'s. Dat is er hier maar eentje, waarin foto en bijschrift zitten.

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

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

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

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

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

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

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

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

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

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

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

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

In dit voorbeeld is deze achtergrondkleur enigszins doorzichtig: 0.7. Hierdoor zie je de foto nog enigszins door het bijschrift heen, maar is het bijschrift toch goed leesbaar.

box-sizing: border-box;

Bij figcaption is een border aan <figcaption> gegeven. Normaal genomen wordt die bij de breedte opgeteld. In dit geval komt dat onhandig uit, omdat <figcaption> inclusief de border een bepaalde hoogte moet krijgen. Door deze regel komt de border binnen de breedte te staan.

(Er is daar ook een padding opgegeven, waarvoor hetzelfde zou gelden, maar die padding wordt iets hieronder verwijderd.)

width: 75%; Onderschrift is even breed als de hoogte van de foto

Een breedte in procenten is altijd ten opzichte van de ouder van het element. Dat is hier <figure>, die bij figure 640 px breed is gemaakt, even breed als de erin zittende foto.

De foto is 640 px breed en 480 px hoog, een veel voorkomende verhouding bij foto's. De hoogte is daarmee 75% van de breedte van de foto. Als <figcaption> 75% breed wordt gemaakt, is <figcaption> dus even breed als de foto hoog is. Op de afbeelding is dat duidelijk te zien. Als <figcaption> wordt gedraaid, is de breedte (die dan hoogte is geworden) gelijk aan de hoogte van de foto.

line-height: 1.6em;

Regelhoogte. Omdat geen hoogte aan <figcaption> wordt gegeven, is dit tevens de hoogte van <figcaption>. Tekst wordt automatisch halverwege de regelhoogte neergezet, dus de tekst wordt netjes verticaal gecentreerd. (Dat de hele <figcaption> hieronder wordt gedraaid, heeft hier geen enkele invloed op.)

1,2 em is ongeveer de normale regelhoogte. Met 1,6 em komt er wat extra ruimte boven en onder de tekst.

Als eenheid wordt de relatieve eenheid em gebruikt, omdat bij een absolute eenheid als px de regelhoogte niet mee verandert met een andere lettergrootte (zoomen kan altijd, ongeacht de gebruikte eenheid).

padding: 0;

Bij figcaption is een padding van 3 px opgegeven voor wat afstand tussen de tekst en de buitenkant van <figcaption>. Hier wordt hetzelfde al bereikt door de hier gelijk boven opgegeven regelhoogte, dus de padding kan weg.

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

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

transform heeft een aantal functies, die gebruikt kunnen worden om het uiterlijk van een element te veranderen. Een daarvan is rotate(), waarmee een element gedraaid kan worden. Tussen de haakjes komt het aantal graden te staan. Hier is dat aantal 90, waardoor de tekst verticaal komt te staan. Maar als je 'n ander aantal graden neemt, kun je tekst ook schuin, ondersteboven, enz. neerzetten.

Bij een positief getal, zoals hier is gebruikt, draait het element met de klok mee. Bij een negatief getal draait het element tegen de klok in.

Het hele element wordt gedraaid met behulp van transform: rotate();, inclusief alles wat erin zit. Dat is hier het bijschrift bij de foto.

Het element wordt wel gedraaid, maar het blijft normaal genomen de originele ruimte bezet houden. Als je onder de afbeelding nog iets anders neer zou zetten, zou dat onder <figcaption> komen te staan, ook al staat <figcaption> zelf op de foto. Althans: dat is normaal genomen zo. Hieronder wordt <figcaption> absoluut gepositioneerd, en daardoor negeren andere elementen het.

-ms-transform-origin: left top; -webkit-transform-origin: left top; transform-origin: left top;

Hier staat in feite drie keer hetzelfde: transform-origin: left top;. Waarom dat zo is, staat bij De voorvoegsels -moz-, -ms- en -webkit-.

De middelste div rondom het middelpunt gedraaid

Als een element wordt gedraaid met behulp van transform: rotate();, wordt standaard rondom het middelpunt gedraaid. Dat levert het op de afbeelding zichtbare resultaat op: de helft van het bijschrift staat onder de foto, de andere helft staat ergens halverwege de foto. Daar worden ook levende standbeelden niet vrolijk van.

Met behulp van transform-origin kun je het draaipunt aanpassen. Dat kan met eenheden zoals px, procenten en sleutelwoorden. Hier zijn de sleutelwoorden left en top gebruikt: het draaipunt wordt de linkerbovenhoek. Op de afbeelding iets hieronder is het resultaat van deze correctie te zien.

position: absolute; Bijschrift staat niet op, maar verticaal onder de foto

Hier gelijk boven is het draaipunt van het bijschrift onder de foto aangepast. Op de afbeelding is te zien dat er inderdaad netjes rondom de linkerbovenhoek is gedraaid, maar dat het resultaat daarvan nou niet direct tot het spontaan dansen van de polonaise zal leiden: het héle bijschrift staat nu onder de foto, zoals op de afbeelding is te zien. Voor de hierboven uitgevoerde correctie met transform-origin stond slechts de helft was van het bijschrift onder de foto.

Daarom wordt het bijschrift met behulp van position op de juiste plaats gezet. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier <figure>.

top: 0; Bijschrift staat op de goede hoogte, maar te ver naar rechts

Met top: 0; wordt de bovenkant van <figcaption> gelijk gezet met de bovenkant van <figure>, en daarmee met de in <figure> zittende afbeelding.

De bovenkant, maar wat is de bovenkant? Het gaat hier om de bovenkant voordat <figcaption> is gedraaid. Op de afbeelding is transform: rotate() even weggehaald, zodat duidelijk is te zien dat het om de bovenkant van <figcaption> gaat, voordat <figcaption> is gedraaid. Maar omdat het draaipunt de linkerbovenhoek is, maakt dat in dit geval niets uit: na draaiing om de linkerbovenhoek staat ook de linkerzijkant, die nu de bovenkant is, gelijk met de bovenkant van <figure>.

right: -75%;

Ook bij right moet, net als hierboven bij top, worden uitgegaan van <figcaption> voordat dit werd gedraaid.

Een waarde in procenten bij right is ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier <figure>. Met een negatieve waarde bij right komt de rechterkant van <figcaption> rechts van de rechterkant van <figure> te staan.

<figure> heeft bij figure een breedte van 640 px gekregen. 75% hiervan is 480 px. De rechterkant van <figcaption> komt dus 480 px rechts van <figure> te staan.

<figcaption> heeft iets hierboven een breedte van 75% van de breedte van <figure> gekregen, dat is ook 480 px. Als de rechterkant van <figcaption> 480 px rechts van de rechterkant van <figure> komt te staan, staat de linkerkant van <figcaption> precies gelijk met de rechterkant van <figure>. Dat is precies de positie, waarin <figcaption> moet staan, om na draaiing rechts op de foto te komen staan.

Op de afbeelding hierboven bij top: 0; is de plaatsing van <figcaption>, voordat is gedraaid, te zien. Bij draaiing met de klok mee om de linkerbovenhoek, komt <figcaption> precies verticaal rechts op de foto te staan.

JavaScript

<script src="115-js/picturefill.min.js" async></script>

Van de afbeelding zijn twee verschillende maten beschikbaar: eentje voor browservensters maximaal 320 px breed, en eentje voor bredere vensters. Hiervoor wordt gebruikt gemaakt van het tamelijk nieuwe srcset-attribuut, dat uitgebreider wordt beschreven bij <figure>. Met behulp van dit JavaScript kunnen ook de meeste oudere browsers hiermee uit de voeten.

Dit JavaScript is een zogenaamde 'polyfill': een script om nieuwere html en css in oudere browsers te laten werken. De code van dit script wordt hier verder niet besproken, omdat het script kant-en-klaar wordt gebruikt.

'Picturefill', de naam van dit script, is in de download bijgesloten. Dit soort scripts wordt voortdurend verbeterd en uitgebreid, daarom is het belangrijk te kijken of er inmiddels misschien een nieuwe versie is. In de download is versie 3.0.2 bijgesloten. Op scottjehl.github.io/picturefill kun je kijken, of dit de laatste versie is.

Het script wordt aan de pagina gekoppeld met behulp van bovenstaande regel. Normaal genomen wordt de weergave van de pagina onderbroken, zodra de browser een script ontmoet. Eerst wordt het script dan afgewerkt. Dat kan tot de nodige vertraging leiden, en in dit geval is die vertraging niet nodig, omdat het script niet essentieel is voor de weergave. Daarom is aan <script> het sleutelwoord async toegevoegd. De browser onderbreekt het weergeven van de pagina nu niet.

Als dit script ontbreekt, of als JavaScript is uitgeschakeld, zal in browsers die srcset niet kennen de in <figure> bij <img> opgegeven src worden gebruikt, zoals uitgebreider beschreven bij <figure>.