Skip links en inhoudsopgave

Tekstkleur aanpassen aan achter­grond met gebruik van mix-blend-mode - uitleg

Laatst aangepast: .

Afbeelding 1: voorbeelden van het gebruik van blend-mode-mix

Korte omschrijving

Kleur van de tekst aanpassen aan de kleur van de achtergrond met behulp van mix-blend-mode.

BELANGRIJK

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

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

Als je dit lastig vindt, downloadt dan de hele handel (ga terug naar het voorbeeld en kies daar voor downloaden). In de download zit 'n voorbeeld dat wel naadloos aansluit op de uitleg in de download.

Alles op deze site kan vrij worden gebruikt, met drie 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.

* Het kan zijn dat materiaal is gebruikt dat van anderen afkomstig is. Dat materiaal kan onder een bepaalde licentie vallen, waardoor het mogelijk niet onbeperkt gebruikt mag worden. Als dat zo is, wordt dat vermeld onder Inhoud van de download en licenties.

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

Alle code is geschreven in een afwijkende lettersoort en -kleur. De code die te maken heeft met de basis van dit voorbeeld (essentiële code), is in de hele uitleg blauw gekleurd. Alle niet-essentiële code is bruin. (In de inhoudsopgave staat alles 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.

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

Achterliggend idee

Tot voor enige tijd was het tamelijk lastig om tekst op onregelmatig gekleurde achtergronden te zetten, zonder het risico te lopen delen van die tekst (vrijwel) onleesbaar te maken. Op effen achtergronden speelde dit probleem niet, want daar kon je gewoon een voor- en achtergrondkleur met voldoende contrast kiezen.

Maar op bijvoorbeeld een foto met een heel scala aan kleuren, was het vrijwel onmogelijk de tekst een kleur te geven die overal voldoende contrast met de foto had. De tekst kon wel leesbaar worden gemaakt door de tekst een eigen achtergrond te geven. Maar zelfs als die achtergrond doorzichtig was, verdween daardoor veel meer van de afbeelding dan alleen voor de tekst nodig zou zijn, omdat de achtergrond ook tussen en rond de tekst stond.

In grafische programma's zoals Gimp en Photoshop kon je dit oplossen door de tekst te 'blenden'. De kleur van de tekst (of andere voorgronden) kon op allerlei manieren worden aangepast aan de kleur van de afbeelding. Desgewenst kon de tekst ook verschillende kleuren krijgen: licht op donkere delen van de afbeelding, donker op lichte delen.

Dat was wel een oplossing, maar nogal tijdrovend. Bovendien moest je alles weer opnieuw doen, als de tekst of de afbeelding veranderde. Als je ook afbeeldingen in verschillende resoluties had, moest je soms 'n hele reeks afbeeldingen aanpassen. En je kunt niet zonder meer een grote afbeelding met tekst verkleinen, want vaak zal de tekst op de afbeelding dan te klein worden.

Met de eigenschap mix-blend-mode heeft css vergelijkbare mogelijkheden gekregen als grafische programma's. Tekst kan boven een afbeelding worden gepositioneerd, waarna met behulp van mix-blend-mode de kleur van de tekst automatisch wordt aangepast aan de kleur van de afbeelding. Hierdoor kunnen tekst en afbeelding worden gewijzigd, zonder dat tijdrovende grafische bewerkingen nodig zijn. Omdat de tekst geen eigen achtergrond meer nodig heeft, blijft de afbeelding veel beter zichtbaar. Omdat de tekst boven de afbeelding nu echte tekst is, is deze ook te lezen door schermlezers, zoekmachines, en dergelijke.

Als je mix-blend-mode gebruikt om bijvoorbeeld tekst boven een foto te zetten, zitten daar wel wat risico's aan.

Oudere browsers kennen mix-blend-mode niet. In die oudere browsers wordt de kleur van de tekst daardoor niet aangepast aan de kleur van de achtergrond. Dat kan betekenen dat het contrast tussen tekst en achtergrond onvoldoende is, waardoor de tekst slecht leesbaar of zelfs volledig onleesbaar kan worden. Dit geldt helemaal voor mensen die moeite met kleuren hebben hebben, of mensen die slechter zien.

Daarom wordt in het voorbeeld de tekst standaard zwart op een (doorzichtige) witte achtergrond weergegeven. Met behulp van @supports wordt gekeken, of de browser een bepaalde vorm van mix-blend-mode ondersteunt. Pas als dat het geval is, wordt de kleur van de tekst aangepast, en wordt de witte achtergrond achter de tekst weggehaald.

(Ook Internet Explorer 11 en Edge ondersteunen mix-blend-mode overigens niet. Omdat dit vrijwel bovenaan staat in het wensenlijstje voor Edge, zal Edge dit over niet al te lange tijd vermoedelijk ook ondersteunen.)

Het is ook mogelijk dat om een of andere reden de afbeelding onder de tekst niet wordt weergegeven. mix-blend-mode wordt echter wel gewoon gebruikt, want dat werkt niet alleen bij afbeeldingen, maar ook bij effen achtergronden. De kleur van de tekst wordt dus gewoon vrolijk aangepast. Daarom is het belangrijk ook een achtergrondkleur op te geven die voldoende contrast heeft met de kleur van de tekst. Als de afbeelding niet wordt geladen, is dan in ieder geval de tekst nog leesbaar.

Als je geen (verre) familie bent van Rembrandt van Rijn én Maryam Mirzakhani, is mix-blend-mode wat lastig om mee te werken. Je moet over kleurgevoel beschikken en ook nog iets van wiskunde begrijpen. Althans: als je de theorie wilt begrijpen. Maar je kunt ook heel gelukkig en tevreden leven zonder daar iets van te begrijpen.

Het is veel makkelijker (en leuker) om gewoon door uitproberen de juiste combinatie van achtergrond, tekstkleur en de soort mix-blend-mode te vinden. Dat wordt in het algemeen zelfs door de experts aangeraden: gewoon proberen.

Waarbij testen dus wel uiterst belangrijk is. Dat is het altijd al, maar met mix-blend-mode kun je tekst echt laten verdwijnen. Ook als je geen oudere browser hebt, kun je doen alsof de browser mix-blend-mode niet ondersteunt. Laat gewoon alles met mix-blend-mode weg, en je ziet de weergave zoals die in oudere browsers is. Het weergeven van tekst zonder erachter zittende afbeelding is uiteraard helemaal simpel te imiteren: gewoon de afbeelding niet weergeven.

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. (Edge gebruikt geen voorvoegsels, maar vanwege compatibiliteit met oudere sites kunnen er nog wat aanwezig zijn.)

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.

In dit voorbeeld worden column-count en column-rule gebruikt.

column-count

Op dit moment moet je nog het volgende schrijven:

{-webkit-column-count: ...; column-count: ...;}

In de toekomst kun je volstaan met:

{column-count: ...;}

column-rule

Op dit moment moet je nog het volgende schrijven:

{-webkit-column-rule: ...; column-rule: ...;}

In de toekomst kun je volstaan met:

{column-rule: ...;}

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.

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.

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

Semantische elementen en WAI-ARIA

Deze twee onderwerpen zijn samengevoegd, omdat ze veel met elkaar te maken hebben.

Semantische elementen

De meeste elementen die in html worden gebruikt, hebben een semantische betekenis. Dat wil zeggen dat je aan de gebruikte tag al (enigszins) kunt zien, wat voor soort inhoud er in het element staat. In een <h1> staat een belangrijke kop. In een <h2> staat een iets minder belangrijke kop. In een <p> staat een alinea. In een <table> staat een tabel (en geen lay-out, als het goed is!). Enzovoort.

Door het op de goede manier gebruiken van semantische elementen, kunnen zoekmachines, schermlezers, enzovoort de structuur van een pagina begrijpen. De spider van een zoekmachine is redelijk te vergelijken met een blinde. Het is dus ook in je eigen belang om semantische elementen zo goed mogelijk te gebruiken. Een site die toegankelijk is voor mensen met een handicap, is in de regel ook goed te verwerken door een zoekmachine en maakt dus een grotere kans gevonden en bezocht te worden.

Als het goed is, wordt het uiterlijk van de pagina bepaald met behulp van css. Het uiterlijk staat hierdoor (vrijwel) los van de semantische inhoud van de pagina. Met behulp van css kun je een <h1> heel klein weergeven en een <h6> heel groot, terwijl schermlezers, zoekmachines, en dergelijke nog steeds weten dat de <h1> een belangrijke kop is.

Slechts enkele elementen, zoals <div> en <span>, hebben geen semantische betekenis. Daardoor zijn deze elementen uitstekend geschikt om met behulp van css het uiterlijk van de pagina aan te passen: de semantische betekenis verandert niet, maar het uiterlijk wel. Voor een schermlezer of zoekmachine verandert er (vrijwel) niets, voor de gemiddelde bezoeker krijgt het door de css een heel ander uiterlijk.

(De derde laag, naast html voor de inhoud en css voor het uiterlijk, is JavaScript. Die zorgt voor de interactie tussen site en bezoeker. De min of meer strikte scheiding tussen css en html aan de ene kant en JavaScript aan de andere kant is met de komst van css3 en html5 veel vager geworden. Je kunt nu bijvoorbeeld ook met css dingen langzaam verplaatsen en met html deels de invoer in formulieren controleren.)

Html5 heeft een aantal nieuwe elementen, die speciaal zijn bedoeld om de opbouw van een pagina aan te geven. In dit voorbeeld wordt hiervan alleen <main> gebruikt. <main> gedraagt zich als een gewone <div>, maar dan een <div> met een semantische betekenis. Hierdoor kunnen schermlezers, zoekmachines, en dergelijke beter zien, hoe de pagina is samengesteld.

<main>

Hierbinnen staat de belangrijkste inhoud van de pagina (in dit voorbeeld zijn dat alleen de voorbeelden met bijbehorende tekst en dergelijke).

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

<main role="main">

Inmiddels is dit behoorlijk veranderd. Het advies is nu om deze speciale toevoeging niet meer te gebruiken, omdat de meeste schermlezers en dergelijke dit soort nieuwe elementen inmiddels herkennen.

WAI-ARIA-codes

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

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

aria-hidden

Met behulp van aria-hidden="true" kan de inhoud van 'n element worden verborgen voor schermlezers, zonder dat dit verder enige invloed heeft op de weergave op het scherm. In dit voorbeeld wordt een deel van de tekst verborgen voor schermlezers. Hierdoor wordt deze tekst niet voorgelezen, maar is wel gewoon zichtbaar op het scherm.

In het eerste voorbeeld staan twee foto's. Beide foto's hebben alt-tekst, die wordt voorgelezen door schermlezers: 'Sponsgooien op Koninginnedag 2008 Vondelpark Amsterdam'.

Boven de foto's wordt met behulp van een <span> de tekst 'Koninginnedag 2008 Vondelpark' neergezet. Deze tekst wordt ook nog eens herhaald in de toelichting onder de foto.

Schermlezers zouden dus drie keer ongeveer dezelfde tekst melden. Daarom wordt de tekst op de foto voor schermlezers verborgen met behulp van aria-hidden:

<span aria-hidden="true">Koninginnedag 2008 Vondelpark</span>

In het tweede voorbeeld staat vier keer het woord 'Raster' boven een achtergrond-afbeelding. Schermlezers lezen dus trouwhartig vier keer het woord 'Raster' voor, zonder dat verder in enige context te plaatsen. De tekst 'raster raster raster raster' leidt vermoedelijk niet tot diepe inzichten, in wat hier gebeurt. In de toelichting onder het voorbeeld wordt 'Raster' ook genoemd, maar dan in enige context. Daarom wordt het woord 'Raster' met behulp van aria-hidden="true" voor schermlezers verborgen:

<p aria-hidden="true">

<span>Raster</span>

</p>

Door de <p> te verbergen voor schermlezers, wordt ook de daarin zittende <span> met het woord 'Raster' verborgen. Je zou ook alleen de <span> kunnen verbergen, maar schermlezers kunnen van element naar element springen. Dat zou bij het voorbeeld met 'Raster' betekenen, dat mogelijk vier keer een volledig lege <p> wordt bezocht, wat tamelijk zinloos is.

Het derde voorbeeld bestaat uit zeven cirkels, maar dit is feitelijk zeven keer de letter 'o'. Een schermlezer leest dus zeven keer de letter 'o'. Afhankelijk van het leestempo kan dat indrukwekkend snel. Er zijn vier reeksen van zeven letters, met daartussendoor de woorden 'mix-blend-mode' en 'opacity'. Wat de gebruiker van een schermlezer dus hoort is 'o o o o o o o mix-blend-mode o o o o o o o opacity o o o o o o o mix-blend-mode o o o o o o o opacity'. Deze tekst slaat natuurlijk nergens op. Bovendien wordt het voorbeeld in de eronder staande toelichting uitgelegd.

Daarom wordt ook deze tekst voor schermlezers verborgen met aria-hidden:

<p aria-hidden="true">

<span>o</span>

<span>o</span>

<span>o</span>

<span>o</span>

<span>o</span>

<span>o</span>

<span>o</span>

<span>mix-blend-mode</span>

</p>

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

JavaScript

Er wordt geen JavaScript gebruikt, dus het aan- of uitstaan van JavaScript heeft geen invloed.

CSS

Zonder css zijn de twee foto's bovenin gewoon te zien. Ook alle tekst is aanwezig, hoewel bijvoorbeeld opschriften niet meer op, maar onder de foto's staan. Omdat de zeven cirkels eigenlijk zeven opgeblazen letters 'o' zijn, staat onderaan de pagina 28 keer de letter 'o', verdeeld over vier groepjes. Kortom: zonder css is alles te lezen, maar het ziet er niet uit.

Afbeeldingen

Zonder afbeeldingen missen bovenin de twee foto's en in het midden de achtergrond-afbeelding met het raster. Verder werkt alles gewoon.

Tekstbrowsers

Lynx toont netjes alle tekst, maar inclusief vier keer 'Raster' en vier groepjes met in elk zeven keer de letter 'o'. WebbIE doet hetzelfde, maar laat het opschrift boven de foto's, de woorden 'Raster' en de letters 'o' weg, omdat deze met de WAI-ARIA-code aria-hidden="true" zijn verborgen.

Schermlezers

In het eerste voorbeeld wordt het opschrift op de foto's verborgen, omdat anders twee keer min of meer hetzelfde wordt voorgelezen.

In het tweede voorbeeld worden de vier woorden 'Raster' verborgen, omdat anders vier keer 'Raster' wordt voorgelezen. Bovendien wordt het voorbeeld in het onderschrift omschreven.

In het derde voorbeeld worden de letters 'o' (de cirkels) met het eronder staande woord verborgen, omdat anders 28 keer de letter 'o' wordt voorgelezen. Bovendien wordt het voorbeeld in het onderschrift omschreven.

Alles wordt verborgen met behulp van de WAI-ARIA-code aria-hidden="true".

Overig

  • Voor kleurenblinden of mensen die slechter zien, is het contrast tussen tekst en achtergrond niet in alle gevallen groot genoeg. Dit contrast is ook heel moeilijk helemaal goed te krijgen, omdat je rekening moet houden met het blenden, met browsers die juist niet kunnen blenden en met het eventueel ontbreken van de achtergrond-afbeelding.

    Daarom is het belangrijk dat in de geblende tekst geen belangrijke informatie staat, want deze kan mogelijk niet door iedereen (makkelijk) worden gelezen.

  • Het gebruik van gekleurde cirkels is hoe dan ook ongeschikt om echt informatie over te dragen, omdat veel mensen de kleuren niet goed zullen kunnen onderscheiden. Als je kleuren gebruikt om informatie te geven, verander dan niet alleen de kleur, maar bijvoorbeeld ook de vorm. Hier speelt dat niet, want dit is alleen maar een voorbeeld.
  • Als niet heel zorgvuldig de juiste combinaties van blenden, voor- en achtergrondkleuren (of achtergrond-afbeelding) worden uitgekozen, kunnen elementen in bepaalde omstandigheden volledig onzichtbaar worden. Dat geldt ook voor tekst. Meer hierover is te vinden bij Blenden kan dingen, ook tekst, volledig onzichtbaar maken!

Getest in

Laatst gecontroleerd op 5 oktober 2017.

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:

Desktopcomputers

Windows 7 (1280 x 1024 px, resolution: 96 dpi):
Firefox, UC Browser, Google Chrome en Internet Explorer 11, in grotere en kleinere browservensters.

OS X 10.11.6 ('El Capitan') (1680 x 1050 px, resolution: 96: dpi, device-pixel-ratio: 1):
Firefox, Safari en Google Chrome, in grotere en kleinere browservensters.

Linux (Kubuntu 14.04 LTS, 'Trusty Tahr') (1280 x 1024 px, resolution: 96 dpi):
Firefox en Google Chrome, in grotere en kleinere browservensters.

Laptops

Windows 8.1 (1366 x 768 px, resolution: 96 dpi):
Bureaublad-versie: Firefox, UC Browser, Google Chrome en Internet Explorer 11, in grotere en kleinere browservensters.
Startscherm-versie: Internet Explorer 11.

Windows 10 (1600 x 900 px, resolution: 96 dpi):
Firefox, UC Browser, Google Chrome, Internet Explorer 11, Edge, in grotere en kleinere browservensters.

Tabletten

iPad met iOS 9.3.5 (1024 x768 px, device-pixel-ratio: 1):
Safari, Chrome for iOS, UC Browser, Firefox (alle portret en landschap).
Opera Mini (Opera Turbo) portret en landschap.

iPad met iOS 11.0.2 (2048 x 1536 px, device-pixel-ratio: 2 ('retina'):
Safari, Chrome for iOS, Firefox (alle portret en landschap).
Opera Mini (Opera Turbo) portret en landschap.

Android 4.4.2 ('Kitkat') (1280 x 800 px, resolution: 96 dpi):
Android browser, UC Browser, Firefox en Chrome (alle portret en landschap).
Opera Mini (besparingen uitgeschakeld) portret en landschap.

Android 4.4.2 ('Kitkat') (2560 x 1600 px, resolution: 192 dpi):
Android browser, UC Browser, Firefox en Chrome (alle portret en landschap).
Opera Mini (besparingen uitgeschakeld) portret en landschap.

Android 6.0 ('Marshmallow') (1920 x 1200 px, resolution: 144 dpi):
Dolphin, UC Browser, Firefox en Chrome (alle portret en landschap).
Opera Mini (besparingen uitgeschakeld) portret en landschap.

Android 7.0 ('Nougat') (1920 x 1200 px, resolution: 144 dpi):
Dolphin, Samsung Internet, UC Browser, Firefox en Chrome (alle portret en landschap).
Opera Mini (besparingen uitgeschakeld) portret en landschap.

Smartphones

Windows 10 Mobile (1280 x 720 px, resolution: 192 dpi):
Edge en UC browser (portret en landschap).

Android 4.1.2 ('Jelly Bean') (800 x 480 px, resolution: 144 dpi):
Chrome, Android browser, UC Browser en Firefox (alle portret en landschap).
Opera Mini (besparingen uitgeschakeld) portret en landschap.

Android 7.0 ('Nougat') (1280 x 720 px, resolution: 192 dpi):
Dolphin, Samsung Internet, UC Browser, Firefox en Chrome (alle portret en landschap).
Opera Mini (besparingen uitgeschakeld) portret en landschap.

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- en uitzoomen en – voor zover de browser dat kan – een kleinere en grotere letter zijn ook 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.)

Schermlezers en dergelijke

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

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

TalkBack is een in Android ingebouwde schermlezer. Er is getest in combinatie met Chrome op Android 4.4,2, 6.0 en 7.0.

VoiceOver is een in iOS en OS X ingebouwde schermlezer. Er is getest in combinatie met Safari op iOS (9.3.5 en 11.0.2) en OS X 10.11.6.

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

Verteller (Narrator) is een in Windows 10 ingebouwde schermlezer. Er is getest in combinatie met Edge.

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 worden pas getest, als ze uit het bèta-stadium zijn, omdat er anders 'n redelijke kans is dat je tegen 'n bug zit te vechten, 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 kunnen niet worden beantwoord, en het melden van fouten in niet-geteste browsers heeft ook geen enkel nut. (Melden van fouten, problemen, enzovoort 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.

mix-blend-mode werkt niet

Het werkt in geen enkele browser

Een aantal browsers ondersteunt mix-blend-mode niet, dat wordt iets hieronder verder beschreven. Maar als het ook in Firefox en Google Chrome niet (goed) werkt, is er iets anders aan de hand. Los van typefouten in de syntax en dergelijke, is het meest waarschijnlijke dat je 'n eigenschap hebt gebruikt die een nieuwe 'stacking context' veroorzaakt, zoals opacity met een waarde minder dan 1, of position: absolute;. Hierover is meer te vinden bij Elementen niet laten meedoen met blenden.

Het werkt niet in Internet Explorer (alle systemen), Edge (alle systemen), UC Browser (Android, Windows Phone 8.1, Windows Mobile 10), Android browser (alle versies), Opera Mini (Android 4.1.2 en 4.4.2)

De genoemde browsers ondersteunen mix-blend-mode niet, daarom wordt de kleur van de tekst (of andere voorgrond) niet veranderd.

Vaak bestaat voor een niet-werkende eigenschap een zogenaamde 'polyfill', een stukje JavaScript dat iets laat werken in browsers die een eigenschap anders niet ondersteunen. Voor mix-blend-mode bestaat dit niet.

Android 4.4.2 wordt nog volop gebruikt. In Firefox en Chrome op Android wordt mix-blend-mode wel ondersteund, maar niet iedereen zal dit gebruiken. In Android 4.4.2 is dit dus echt een probleem.

Internet Explorer 11 wordt ook nog volop gebruikt, en Microsoft voegt aan Internet Explorer geen nieuwe dingen toe.

Edge wordt ook volop gebruikt, maar ondersteuning voor mix-blend-mode staat hoog op het verlanglijstje, dus het zal geen tien jaar duren, voordat dit wordt ondersteund.

Maar alles bij elkaar kun je er niet vanuit gaan dat mix-blend-mode werkt. Daarom is het uiterst belangrijk te zorgen dat de tekst altijd leesbaar is, ook zonder mix-blend-mode. Geef de tekst een eigen achtergrondkleur, en verander of verwijder die pas, als met @supports is getest, of mix-blend-mode wordt ondersteund. Het is dan misschien wel minder mooi, maar de tekst is in ieder geval te lezen.

Meer over testen met @supports is te vinden bij @supports (mix-blend-mode: normal).

Android browser (alle versies), UC browser op Android (alle versies), Opera Mini (Android 4.1.2)

Foto's en ringen staan niet altijd netjes verdeeld over het venster

Om de foto's bovenaan en de gekleurde ringen onderaan netjes over het browservenster te verdelen, wordt gebruik gemaakt van flexbox. In de genoemde browsers werkt flexbox niet, of er werkt alleen een verouderde versie. Die verouderde versie is ook nog 'ns zo slecht en onvolledig geïmplementeerd, dat alleen mensen die cum laude zijn geslaagd voor de Hogere Opleiding Zelfhaat dat legaal mogen gebruiken.

Omdat dit verder niet van belang is, is hier geen tijd in gestopt.

(Overigens zie je dit misschien niet eens, als je het niet weet. Door gebruik van display: inline-block; staat het nog steeds redelijk netjes. Browsers die flexbox kennen, hebben hier verder geen last van, die gebruiken gewoon flexbox.)

Firefox op Android

In sommige versies staan de gekleurde cirkels iets te laag

Om precies te zijn: in Android 4.1.2 en 7 op de smartphone, en in Android 6 en 7 op de tablet. Maar in beide tabletten met Android 4.4.2 staan ze goed. Omdat Firefox de enige browser op Android is die dit doet, en nog niet eens consequent in alle versies van Android, is dat kennelijk 'n soort bug. Omdat dit verder van geen enkel belang is voor het voorbeeld, is hier alleen vluchtig naar gekeken en verder zo gelaten.

Safari (alle versies)

De modes 'hue', 'saturation', 'color' en 'luminosity' werken niet

Safari ondersteunt de modes 'hue', 'saturation', 'color' en 'luminosity' van mix-blend-mode niet. Bij gebruik van deze modes wordt de kleur niet gewijzigd. (Deze modes worden overigens niet gebruikt in het voorbeeld.)

Als je één van deze modes wilt gebruiken, moet je daarom met behulp van @supports expliciet op deze modes testen.

In het voorbeeld wordt bij @supports (mix-blend-mode: normal) alleen getest op de mode 'normal'. Dat kan ook, omdat in het voorbeeld alleen de modes 'normal', 'difference' en 'color-dodge' worden gebruikt. En alle browsers die de mode 'normal' ondersteunen, ondersteunen ook de modes 'difference' en 'color-dodge'. Maar bij gebruik van één van bovenstaande vier modes is het testen op alleen 'normal' niet voldoende, want Safari ondersteunt wel 'normal', maar niet de vier genoemde modes.

Validatie

@supports valideert niet

De css-validator geeft een foutmelding, als je @supports gebruikt. Kennelijk is dit nog niet geïmplementeerd in de validator. Omdat de reden van deze foutmelding bekend is, is dit verder geen probleem. @supports werkt gewoon in alle nieuwere browsers.

Alle browsers die mix-blend-mode (gedeeltelijk) ondersteunen, ondersteunen @supports. Als een browser @supports niet ondersteunt, ondersteunt die browser dus zeker mix-blend-mode niet. Maar ook in dat geval heeft @supports de gewenste werking: als @supports niet wordt ondersteund, wordt de code tussen de {} van @supports genegeerd. En dat is precies de code die te maken heeft met mix-blend-mode.

(Om de css binnen @supports te kunnen valideren, is @supports even weggehaald. Zolang @supports aanwezig was, had de validator alleen 'n soort cryptische doodsreutel te melden.)

mode 'color-dodge' valideert niet

Dit is gewoon een vuige leugen van de css-validator. Deze waarde bestaat volgens de validator niet, en daarom krijg je 'n foutmelding. Maar deze waarde bestaat toch echt.

(De jokkebrok beweert trouwens hetzelfde over het in het voorbeeld niet gebruikte 'color-burn', maar ook dat bestaat.)

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-121-dl.html: de pagina met het voorbeeld.

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

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

121-css-dl:

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

121-pics:

raster.jpg: de in het tweede voorbeeld gebruikte achtergrond-afbeelding is afkomstig van bgrepeat.com en kan vrij worden gebruikt.

sponsgooien.jpg: de in het eerste voorbeeld gebruikte foto van de jongen, die met sponsen nat wordt gegooid, is gemaakt in het Vondelpark in Amsterdam op Koninginnedag 2008. Als je jezelf herkent en de originele foto wilt hebben, stuur dan even 'n mailtje naar 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 blauw gekleurd. Alle niet-essentiële code is bruin. (In de inhoudsopgave staat alles in een gewone letter vanwege de leesbaarheid.)

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

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

<!DOCTYPE html>

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

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

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

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

<html lang="nl">

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

<meta charset="utf-8">

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

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

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

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

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

Mobiele apparaten variëren enorm in breedte. En dat is een probleem. Sites waren, in ieder geval tot voor kort, gemaakt voor desktopbrowsers. En die hebben, in vergelijking met bijvoorbeeld een smartphone, heel brede browservensters. Hoe moet je op 'n smartphone een pagina weergeven, die is gemaakt voor de breedte van een desktop? Je kunt natuurlijk wachten tot álle sites zijn omgebouwd voor smartphones, tablets, enzovoort, 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 wordt de pagina nooit breder dan het venster. Maar die stomme mobiele browser weet dat niet, dus die gaat ervan uit dat ook deze pagina 980 px breed is, en verkleint die dan. Dat is ongeveer even behulpzaam als de gedienstige kelner die behulpzaam de stoel naar achteren trekt, net als jij wilt gaan zitten.

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

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

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

<span aria-hidden="true">Koninginnedag 2008 Vondelpark</span>

Dit is de tekst die op de foto's staat. Bij de foto's staat ook een alt-omschrijving, die wordt voorgelezen door schermlezers. Die alt-omschrijving is vrijwel hetzelfde als de tekst in de <span>. Om dubbel voorlezen te voorkomen, wordt de <span> met de tekst met behulp van de WAI-ARIA-code aria-hidden verborgen voor schermlezers.

<p aria-hidden="true">

In het tweede voorbeeld staat vier keer het woord 'Raster'. In het derde voorbeeld staan onder andere vier series van zeven keer de letter 'o'. Het voorlezen van deze woorden en letters is volstrekt zinloos en alleen maar verwarrend. Bovendien staan woorden en letters ook in de uitleg onder de voorbeelden, maar dan op 'n begrijpelijke manier. Woorden en letters worden daarom met behulp van de WAI-ARIA-code aria-hidden="true" verborgen voor schermlezers.

CSS

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

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

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

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

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

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

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

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

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

Je hebt dan eigenlijk twee stylesheets. De uitgebreide versie waarin je dingen uitprobeert, verandert, enzovoort, 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.)

Uitgebreide beschrijving van mix-blend-mode

Als je deze uitleg online leest, werken de in deze uitleg gebruikte voorbeelden in ieder geval allemaal goed in Firefox, Google Chrome en Samsung Internet (in Safari werken de meeste). De voorbeelden online zijn geen afbeeldingen, maar echt werkende voorbeelden van mix-blend-mode. Als een voorbeeld niet werkt in 'n browser, wordt dat bij dat voorbeeld vermeld.

Je kunt de uitleg ook in pdf-vorm downloaden. In de pdf zijn alle voorbeelden te zien, omdat daarin gebruik wordt gemaakt van afbeeldingen.

Algemeen

Dit deel gaat over de meer theoretische achtergrond van mix-blend-mode. Als je daarin niet bent geïnteresseerd, kun je dit in principe gewoon overslaan. Meestal is het simpeler om het gewoon spelenderwijs uit te proberen dan om het theoretisch te beredeneren. Dat is ook wat in (vrijwel) elke uitleg hierover wordt gezegd.

Maar als je dezelfde afwijking hebt als ondergetekende en wilt weten, hoe iets ongeveer werkt, dan kun je dat hier vinden.

Als wij een kleur zien, ziet de computer 'n aantal getallen. En met getallen kun je rekenen. Als je twee kleuren hebt, heb je twee sets met getallen. Als je daar dingen mee doet, waar alleen wiskundigen de humor van begrijpen, krijg je 'n nieuwe kleur. Dat is de kern van blenden. (En van het zusje van blenden: compositing. Maar dat wordt hier verder niet beschreven.)

Css kent twee eigenschappen voor blenden: mix-blend-mode en background-blend-mode. Beide werken, wat betreft het blenden, grotendeels hetzelfde. Het verschil zit in wát ze blenden.

background-blend-mode is bedoeld om binnen hetzelfde element één of meerdere achtergronden en eventueel een achtergrondkleur te blenden. Het kan bijvoorbeeld worden gebruikt om twee afbeeldingen te combineren. Het werkt alleen voor achtergronden: de kleur van tekst en dergelijke wordt niet gewijzigd. Deze eigenschap wordt hier verder niet beschreven.

mix-blend-mode is bedoeld om inhoud en achtergrond van een element te blenden met het element erachter. Omdat je dat element ook weer met het element erachter kunt blenden, en dat ook weer met dat erachter, enzovoort, kun je 'n – in theorie – eindeloze hoeveelheid elementen elkaar laten beïnvloeden.

Dat is te zien in het onderste voorbeeld met de gekleurde cirkels. Bij het eerste en derde groepje cirkels wordt mix-blend-mode gebruikt. De html en css is bij beide groepjes vrijwel hetzelfde. Elke cirkel zit in een eigen <span>. De <span>'s van elk groepje cirkels zitten weer in een <p>. Bij beide groepjes beïnvloeden de kleuren van de cirkels elkaar op de plaatsen, waar de cirkels elkaar overlappen. Maar de <p> van het derde groepje heeft een rode achtergrondkleur. Daardoor zijn de uiteindelijke kleuren van de cirkels van het derde groepje volkomen anders dan die van het eerste groepje.

Aan dit blenden van verschillende elementen zitten wel grenzen: de elementen moeten in dezelfde 'stacking context' zitten. (Er bestaat geen goede Nederlandse vertaling voor dit begrip.) Je zou een stacking context, heel erg versimpeld, 'n groep bij elkaar horende elementen kunnen noemen.

Verschillende eigenschappen zorgen voor een nieuwe stacking context, bijvoorbeeld opacity met een lagere waarde dan 1. Door bijvoorbeeld een <div> opacity: 0.99; te geven (dat is zo weinig dat je het niet ziet), kun je het blenden beperken tot die <div>. Maar je kunt ook een speciaal daarvoor bedoelde eigenschap gebruiken: isolation. Die stacking context kan heel handig zijn, maar je kunt er ook hartstikke knettergestoord van worden. Meer over stacking context en isolation is te vinden bij Elementen niet laten meedoen met blenden.

Blenden heeft ook invloed op de kinderen van een element. Ook daar is meer over te vinden bij Elementen niet laten meedoen met blenden.

Emgelse termen

Op internet worden voor blenden vrijwel alleen de Engelse termen gebruikt. Nederlandstalige artikelen over de css-eigenschap mix-blend-mode heb ik niet kunnen vinden, althans geen artikelen die iets langer waren dan enkele regels met een truc of zo. (Ook geen artikelen over background-blend-mode trouwens.) Ook in Nederlandstalige artikelen over Photoshop worden vaak de Engelse termen gebruikt.

Om deze redenen worden in deze uitleg ook voornamelijk de Engelse termen gebruikt. Als je elders op internet iets op wilt zoeken, zul je ook die Engelse termen moeten gebruiken. Hieronder volgt een kort lijstje van de belangrijkste begrippen. (De namen van de modes – de mogelijke soorten blenden – zitten daar niet bij, want die worden nooit vertaald.)

Backdrop

Het deel waar de twee elementen ('destination' en 'source') elkaar overlappen. De twee elementen kunnen elkaar volledig overlappen, maar dat hoeft niet. Bij tekst is de backdrop niet hoger of breder dan de tekst, de ruimte tussen de letters hoort niet bij de backdrop.

Blending

Het mengen van de kleuren. In deze uitleg wordt het werkwoord 'blenden' gebruikt, want dat blijkt gewoon Nederlands te zijn.

Destination

'Bestemming'. Het onderste element.

Mode

De manier waarop wordt geblend. Er zijn zestien verschillende modes, zestien verschillende manieren. De modes worden aangegeven met de Engelse naam, bijvoorbeeld 'multiply'. Bij Modes worden de verschillende modes beschreven.

Source

'Bron'. Het bovenste element.

Stacking context

Hier bestaat geen Nederlandse vertaling voor. Het is 'n groep elementen die min of meer bij elkaar hoort. Blenden beperkt zich tot de stacking context, waarbij het te blenden element hoort. Het wordt uitgebreider besproken bij Onderliggende elementen niet laten blenden: de stacking context.

Rekenen met kleuren

Als wij naar een scherm kijken, zien we 'n kleur. Die kleur wordt samengesteld door de computer. Mijn favoriete stripfiguur Guust Flater werkt in een van zijn vele dromen met gloeiwormpjes die gekleurd licht geven. Dat is ook geprobeerd met computers, maar helaas bleken de gloeiwormpjes de bedrading aan te vreten. Daarom moet een computer een andere techniek gebruiken om een kleur te 'maken'.

Als gevolg hiervan moet de computer zelf een kleur samenstellen, waarna het scherm die kleur dan kan weergeven. Dat is in werkelijkheid een waanzinnig gecompliceerd proces, waar hier verder niet op wordt ingegaan. (Dat klinkt ook 'n stuk slimmer, dan dat ik er gewoon te weinig van weet...)

Schermen zijn opgebouwd uit pixels. Op hogeresolutieschermen zitten die heel dicht bij elkaar, zodat je een mooiere weergave hebt. Op desktopmonitors zitten ze meestal verder uit elkaar. Dat maakt voor de rest van het verhaal verder niets uit.

Elke pixel is opgebouwd uit drie subpixels: een rode, een groene en een blauwe. Door deze subpixels meer of minder op te laten lichten, kun je elke kleur maken. Omdat elke subpixel 256 verschillende sterktes kan krijgen (van helemaal uit tot helemaal aan), kun je 256 x 256 x 256 =16.777.216 verschillende kleuren samenstellen.

In feite wordt je dus voortdurend voor de gek gehouden, als je denkt 'n bepaalde kleur te zien. In werkelijkheid zie je 'n rood, 'n groen en 'n blauw puntje. Alle andere kleuren ontstaan door de sterkte van die drie kleuren te variëren. Omdat menselijke ogen eigenlijk helemaal niet zo goed zijn, dénken wij 'n gewone kleur te zien op een monitor. In werkelijkheid zijn het drie stukjes rood, groen en blauw die voor 'n mens niet zijn te onderscheiden.

Eigenlijk is het verhaal nog veel ingewikkelder, omdat je inmiddels ook 'n soort subsubpixels hebt. Verder kun je subpixels van twee verschillende pixels combineren. Er zijn allerlei trucs mogelijk, waarmee het menselijk oog gefopt kan worden. Daardoor zijn zelfs goedkope monitors tegenwoordig niet meer echt blokkerig.

(Op papier is het trouwens een heel ander verhaal, daar zijn ogen veel moeilijker voor de gek te houden. Vandaar dat het printen van een foto vanaf internet vaak een slecht resultaat oplevert. De kwaliteit die op een monitor nog voldoende was, ziet er op papier niet uit.)

Voor een computer is elke kleur een getal. Of feitelijk: een combinatie van drie getallen. Een getal voor rood, een voor groen en een voor blauw. Daar komt de afkorting RGB vandaan, die veel wordt gebruikt in de grafische wereld. Toevallig beginnen de Nederlandse kleuren ook met deze letters, maar ze staan eigenlijk voor red, green en blue.

rgb is ook de naam van een css-eigenschap, waarmee je kleuren kunt aangeven.

rgb(0, 0, 0) wil zeggen: helemaal geen rood, geen groen en geen blauw. Dit levert zwart op.

rgb(255, 255, 255) wil zeggen: volledig rood, groen en blauw, wat wit oplevert.

rgb(0, 0, 255) is geen rood, geen groen en volledig blauw. Dit levert blauw op. rgb(255, 255, 0) is volledig rood, volledig groen en geen blauw, wat geel oplevert. (Het mengen van kleuren op een monitor werkt anders dan bij kleuren op papier.)

Op deze manier kun je, door de drie getallen te variëren, elk van de 16.777.216 mogelijke kleuren definiëren.

Er zijn 256 waarden mogelijk, maar het hoogst mogelijke getal is 255. Dat heeft een simpele reden: computers beginnen meestal met 0 te tellen, in tegenstelling tot mensen. En als je bij 0 begint en bij 255 eindigt, heb je 256 getallen. Er bestaan in css nog andere manieren om kleuren weer te geven, zoals de hexadecimale. Daarin geef je bijvoorbeeld geel op als #ffff00. Voor dit verhaal maakt dit niets uit, want de verschillende notaties werken allemaal hetzelfde. Voor een computer is ff hetzelfde als 255.

Een van de modes bij blenden is 'multiply': vermenigvuldigen. Twee kleuren worden vermenigvuldigd en dat levert een nieuwe kleur op. Alleen: konijnen kunnen zich vermenigvuldigen, maar hoe vermenigvuldig je twee kleuren?

Voor een computer bestaat een kleur uit een getal. Feitelijk drie getallen: een waarde voor rood, een voor groen en een voor blauw. En met getallen kun je, net als met konijnen, vermenigvuldigen.

Als er twee kleuren geblend moeten worden, heb je twee series van drie getallen.

De kleur rood is rgb(255, 0, 0). 255 voor rood, 0 voor groen en 0 voor blauw.

De kleur blauw is rgb(0, 0, 255). 0 voor rood, 0 voor groen en 0 255 voor blauw.

Bij de mode multiply worden van beide kleuren de waarden voor rood, voor groen en voor blauw met elkaar vermenigvuldigd.

De beide waarden voor rood: 255 x 0 = 0.

De beide waarden voor groen: 0 x 0 = 0.

De beide waarden voor blauw: 0 x 255 = 0.

Voor de nieuwe kleur worden de drie uitkomsten weer achter elkaar gezet: rgb(0, 0, 0). Dit levert de kleur zwart op. Als je rood met blauw blendt met de mode multiply, levert dat de kleur zwart op:

Hierboven staan twee geneste <div>'s. De buitenste <div> heeft als css onder andere background: rgb(255, 0, 0);, een rode achtergrond. De binnenste <div> heeft als css onder andere background: rgb(0, 0, 255);, een blauwe achtergrond, en mix-blend-mode: multiply;. Dit levert uiteindelijk een zwarte achtergrondkleur op voor de binnenste <div>.

Uiteraard is dit een vrij zinloze exercitie die alleen afkomstig kan zijn van de Afdeling Werkverschaffing. Je kunt de binnenste <div> ook gewoon 'n zwarte achtergrond geven. Maar wat hier is gebeurd, is wezenlijk anders dan 'n simpele zwarte achtergrond.

De binnenste <div> is 260 px breed en 100 px hoog. Dat zijn 260 x 100 = 26.000 pixels (waarbij even niet wordt gelet op hogeresolutieschermen en zo). Van de buitenste <div> worden dus 26.000 pixels overlapt door de binnenste <div>. Elk van die pixels wordt apart bekeken. Omdat de achtergrondkleur van beide <div>'s egaal is, is de uitkomst van elke berekening hetzelfde: zwart. Dus krijgt de binnenste <div> een egaal zwarte achtergrond.

Als de binnenste <div> echter boven bijvoorbeeld een foto zou staan, wordt het een heel ander verhaal. De pixels van de foto hebben allemaal een andere kleur, dus de uitkomst van de berekening is voor elke pixel anders. En nu varieert de kleur van de binnenste <div>:

Het enige verschil met de twee <div>'s iets hierboven is, wat er achter de binnenste <div> zit. In de buitenste <div> is nu een foto gezet. Achter de binnenste <div> zit daardoor nu geen egaal rode kleur meer, maar een foto met allerlei kleuren. De achtergrondkleur van de binnenste <div> blijkt nu opeens te variëren, terwijl die achtergrondkleur nog steeds gewoon blauw is.

Op het voorbeeld hierboven lijkt het mogelijk, alsof je de binnenste <div> ook gewoon doorzichtig zou kunnen maken. Maar als je mix-blend-mode vervangt door opacity, blijkt dat er echt heel anders uit te zien. De blauwe achtergrondkleur wordt dan overal even doorzichtig, ongeacht of de achtergrond donker of licht of wat dan ook is. Bij mix-blend-mode is de uiteindelijke kleur mede afhankelijk van de kleur van de achtergrond.

Overigens wordt hierboven gelijk iets anders duidelijk: je moet de juiste kleuren combineren, met de juiste mode. Hierboven is van de foto vrijwel niets meer te zien. Bij de combinatie multiply met blauw verdwijnen de lichte delen van de foto vrijwel helemaal. Aan de andere verdwijnt de achtergrondkleur van de binnenste <div> vrijwel helemaal boven de donkere delen van de foto.

Een bruikbaarder voorbeeld is tekst boven een zwart-witte achtergrond. Hieronder staat een witte tekst binnen een zwart-wit gestreepte <div>. De zwart-witte achtergrond is verkregen, door de achtergrond van de <div> met behulp van repeating-linear-gradient elke 10% van zwart naar wit en omgekeerd te veranderen:

In een <span> binnen de <div> staat de meesterlijke tekst 'ZWART OP WIT OP ZWART', maar dan tig keer herhaald en aan elkaar vast geschreven. De tekst heeft een witte kleur. De <span> heeft mix-blend-mode: difference;, verschil, gekregen.

Zwart is rgb(0, 0, 0). Wit is rgb(255, 255, 255). Het verschil tussen die twee is 255 – 0 = 255. De geblende kleur boven een zwarte achtergrond wordt dus rgb(255, 255, 255), oftewel: wit. Op een zwarte achtergrond blijft de tekst dus gewoon wit.

Op een witte achtergrond is het een ander verhaal. Wit is rgb(0, 0, 0). De waarde van de witte achtergrond is dus hetzelfde als die van de witte tekst. Het verschil tussen beide is nu 0 – 0 = 0. De geblende kleur boven een witte achtergrond wordt dus rgb (0, 0, 0), oftewel: zwart.

Als de lettergrootte wordt veranderd, maakt dat niets uit. Er wordt minder of meer tekst zichtbaar, maar de kleuren veranderen mee. In hele smalle browservensters wordt de tekst eerder afgebroken. Ook dat maakt niet uit: de kleuren passen zich aan. De tekst is automatisch zwart-op-wit, of wit-op-zwart.

In browsers die mix-blend-mode niet ondersteunen, verandert de tekst niet van kleur. In deze browsers valt de witte tekst weg tegen de witte strepen van de achtergrond. Daarom moet voor browsers die mix-blend-mode niet ondersteunen vaak andere css worden opgegeven, dan voor browsers die het wel ondersteunen. Bij @supports (mix-blend-mode: normal) is te zien, hoe dat in het voorbeeld is gedaan.

Je kunt ook bijvoorbeeld twee foto's over elkaar heen zetten. Hieronder staan twee foto's, één van 'n gewone, vlakke zee, en één van iemand die in de zonsondergang op het strand wandelt.

Afbeelding 2: foto van een rustige zee Afbeelding 3: foto van een zonsondergang aan zee

Als je de tweede foto mix-blend-mode: overlay; geeft en over de eerste foto zet, krijg je onderstaand resultaat:

De gewone, vlakke zee is plotsklaps voorzien van wandelaar en zonsondergang.

Het resultaat van dit samenvoegen zal vermoedelijk geen prijs voor de mooiste compositie gaan krijgen op de eerstvolgende World Press Photo. Maar daar gaat het niet om: het laat zien wat de mogelijkheden zijn. Op internet zijn tal van trucs met foto's te vinden, die je op betere ideeën kunnen brengen dan het bovenstaande gefröbel.

En ook hier geldt weer: je moet met @supports controleren, of de browser mix-blend-mode ondersteunt. Een browser die dit niet ondersteunt, toont alleen de tweede foto. Daar moet je dus eventueel de css aanpassen. Bij @supports (mix-blend-mode: normal) is te zien, hoe dat in het voorbeeld is gedaan.

(Er gelden nog wat meer regels bij de hierboven gebruikte modes, maar dit is in grote lijnen, hoe het werkt. Bij de verschillende Modes van mix-blend-mode wordt dit vollediger beschreven.)

Als je nou denkt: hier klopt iets niet bij de berekeningen, dan heb je helemaal gelijk. De waarde voor rood, groen of blauw kan hoogstens 255 zijn. Maar als je bijvoorbeeld rgb(3, 0, 0) vermenigvuldigt met rgb(100, 0, 0), dan wordt rood 3 x 100 = 300. Oeps. En bij 255 x 255 is het nog erger, want dan beginnen sommige mobieltjes erbarmelijk te huilen.

Voordat de browser aan het rekenen slaat, worden de drie waarden voor rood, groen en blauw eerst teruggebracht tot een waarde tussen 0 en 1. Hierdoor kun je nooit een te lage of een te hoge uitkomst krijgen. Na de berekening wordt de uitkomst dan weer terugvertaald naar een voor de kleur bruikbare waarde. Daarnaast zitten er nog wat grenzen bij verschillende modes, zoals dat het resultaat altijd zwart of wit is, of iets daar tussenin.

(In werkelijkheid is het nog veel ingewikkelder. Mensen geven een decimale of hexadecimale waarde op. Die wordt omgerekend naar een getal tussen 0 en 1. Maar een computer werkt met een tweetallig getallenstelsel. Ik krijg al last van ernstige zenuwtics als ik hier langer dan drie seconden over nadenk. En hoe dit kan werken, is me echt 'n compleet raadsel. Alsof je 'n Chinees gedicht naar het Russisch vertaalt, vervolgens naar het Grieks en de Griekse versie laat bewerken door 'n stel Egyptische scholieren. Het resultaat daarvan wordt weer terug vertaald naar het Grieks, dan naar het Russisch en uiteindelijk weer naar het Chinees. En dan blijk je dus als eindresultaat een mooi Chinees gedicht over te houden.)

Er wordt dus eigenlijk gerekend met getallen tussen 0 en 1. Omdat dit het verhaal nog ingewikkelder maakt, dan het al is, wordt dat hier meestal genegeerd. rgb(3, 3, 3) + rgb(4, 4, 4) levert rgb(7, 7, 7) op. De tussenstap van het omrekenen naar en weer terugrekenen van een getal tussen 0 en 1 wordt overgeslagen.

Voor de echte liefhebber zijn de precieze formules van de diverse modes te vinden in de specificatie Compositing and Blending Level 1.

Modes

Als je deze uitleg online leest, werken de in deze uitleg gebruikte voorbeelden in ieder geval allemaal goed in Firefox, Google Chrome en Samsung Internet (in Safari werken de meeste). De voorbeelden online zijn geen afbeeldingen, maar echt werkende voorbeelden van mix-blend-mode. Als een voorbeeld niet werkt in 'n browser, wordt dat bij dat voorbeeld vermeld.

Je kunt de uitleg ook in pdf-vorm downloaden. In de pdf zijn alle voorbeelden te zien, omdat daarin gebruik wordt gemaakt van afbeeldingen.

Blenden kan op zestien verschillende manieren gebeuren, met zestien verschillende 'modes'.

In het bijgesloten voorbeeld wordt met behulp van @supports getest, of een browser mix-blend-mode ondersteunt. Met behulp van @supports kunnen voor browsers die mix-blend-mode niet ondersteunen, andere kleuren worden gebruikt.

Dit testen op ondersteuning is uitermate belangrijk. Als je bij mix-blend-mode kleuren gebruikt die een goed leesbare tekst opleveren, kan die tekst prima volledig onzichtbaar worden, als de browser mix-blend-mode niet ondersteunt. En omgekeerd.

Hieronder wordt elke mode drie keer gebruikt. In totaal zijn er zestien groepjes met in elk groepje drie verschillende voorbeelden. De css en html voor alle zestien modes is precies hetzelfde, alleen de mode bij mix-blend-mode is steeds anders. Alle kleuren en dergelijke zijn precies hetzelfde.

Elk voorbeeld bestaat uit een <div> met een achtergrondkleur.

In elk eerste voorbeeld van elk groepje van drie heeft die <div> de achtergrondkleur rgb(51, 51, 51), donkergrijs.

In het middelste voorbeeld van elk groepje van drie heeft de <div> de achtergrondkleur rgb(204, 204, 204), lichtgrijs.

In het derde voorbeeld van elk groepje van drie heeft de <div> een gradiënt (verlopende kleur): linear-gradient(black, black 10%, red, yellow, green, white, blue 90%, blue). Hier zijn geen rgb-waarden gebruikt, maar gewoon de kleurennamen, omdat het anders tamelijk onleesbaar wordt.

Maar als je dit in rgb-notatie zou willen weergeven, ziet het er zo uit: linear-gradient(rgb(0, 0, 0), rgb(0, 0, 0) 10%, rgb(255, 0, 0), rgb(255, 255, 0), rgb(0, 128, 0), rgb(255, 255, 255), rgb(0, 0, 255) 90%, rgb(0, 0, 255)). Beide gradiënts hebben precies dezelfde kleuren, omdat kleurennamen in css door de browsers naar getallen worden omgezet.

Omdat deze achtergrond een gradiënt is, verlopende kleuren, kun je goed zien hoe de kleur van de tekst zich aan de achtergrond aanpast.

Omdat de tekst vaak niet helemaal tot de boven- en/of onderkant van de gradiënt doorloopt, hebben boven- en onderkant van de gradiënt over een hoogte van 10% dezelfde kleur.

Binnen elke <div> staan twee <span>'s boven elkaar. Dat geeft de mogelijkheid om voor het bovenste woord een andere kleur te gebruiken dan voor het onderste woord. (Als het woord wat lang is, staat de eerste helft boven en de tweede helft onder.)

In elk eerste en tweede voorbeeld van elk groepje van drie is de kleur van het woord bovenin rgb(51, 51, 51), donkergrijs. De kleur van het woord onderin is rgb(204, 204, 204), lichtgrijs.

In elk derde groepje van drie is de kleur zowel boven- als onderin rgb(204, 204, 204), lichtgrijs.

(Boven elke mode worden deze kleuren kort herhaald, voor het geval je geen geheugenwonder bent.)

Dit levert voor elke mode 5 voorbeelden op: het eerste voorbeeld van elk groepje van drie heeft een donkergrijze achtergrond met bovenin donkergrijze en onderin lichtgrijze tekst. Het tweede voorbeeld heeft een lichtgrijze achtergrond met bovenin donkergrijze en onderin lichtgrijze tekst. Het derde groepje heeft een gradiënt als achtergrond en lichtgrijze tekst.

Zwart en wit zijn niet gebruikt, omdat deze twee uiterste kleuren in veel modes geen enkel effect hebben. (Dat wordt bij de verschillende modes vermeld). Grijs is wat dat betreft ook niet ideaal, maar je ziet in ieder geval meestal iets. Er zijn geen kleuren die bij elke mode een duidelijk zichtbaar resultaat geven.

normal

Achtergrond eerste blokje, tekst bovenin eerste en tweede blokje: rgb(51, 51, 51) (donkergrijs).

Achtergrond tweede blokje, tekst onderin eerste en tweede blokje, tekst derde blokje: rgb(204, 204, 204) (lichtgrijs).

Tekst: mix-blend-mode: normal;

Uitgebreider verhaal over kleuren en dergelijke zie Hieronder wordt elke mode...

Niet echt wereldschokkend: 'normal', de standaard waarde van mix-blend-mode, geeft de hele zaak gewoon weer, alsof mix-blend-mode niet wordt gebruikt.

Hierboven staat in de bovenste helft 'nor-', in de onderste helft 'mal'. De tekst wordt gewoon zonder enige aanpassing weergegeven. Dit kan handig zijn, als je bijvoorbeeld een hele serie <li>'s wilt blenden, maar eentje niet.

multiply

Achtergrond eerste blokje, tekst bovenin eerste en tweede blokje: rgb(51, 51, 51) (donkergrijs).

Achtergrond tweede blokje, tekst onderin eerste en tweede blokje, tekst derde blokje: rgb(204, 204, 204) (lichtgrijs).

Tekst: mix-blend-mode: multiply;

Uitgebreider verhaal over kleuren en dergelijke zie Hieronder wordt elke mode...

'Multiply' betekent letterlijk vermenigvuldigen. De voorgrondkleur wordt vermenigvuldigd met de kleur van de achtergrond. De uiteindelijke kleur is altijd minstens even donker als voor- of achtergrondkleur. Als een van beide kleuren zwart is, is de uiteindelijke kleur altijd zwart. Als een van beide kleuren wit is, blijft de originele kleur bewaard. 'Multiply' is het tegenovergestelde van screen.

Hierboven staat in de bovenste helft 'mul-', in de onderste helft 'tiply'. De uiteindelijke kleur is nooit lichter dan voor- of achtergrondkleur.

Als je de tekst onderin het eerste blokje met z'n achtergrond vermenigvuldigt, gebruik je dezelfde kleuren als bij de tekst bovenin het tweede blokje met z'n achtergrond. Tekst- en achtergrondkleur zijn omgewisseld, maar de kleuren zijn hetzelfde. De uitkomst van beide vermenigvuldigingen is dan ook hetzelfde, en de uiteindelijke kleur ook. De tekst onderin het eerste blokje is echter nauwelijks te lezen. Hieruit blijkt weer, hoe belangrijk het is de juiste combinatie van kleuren en mode te kiezen.

De uiteindelijke voorgrondkleur in het derde blokje varieert, omdat de kleur van de achtergrond varieert.

screen

Achtergrond eerste blokje, tekst bovenin eerste en tweede blokje: rgb(51, 51, 51) (donkergrijs).

Achtergrond tweede blokje, tekst onderin eerste en tweede blokje, tekst derde blokje: rgb(204, 204, 204) (lichtgrijs).

Tekst: mix-blend-mode: screen;

Uitgebreider verhaal over kleuren en dergelijke zie Hieronder wordt elke mode...

Dit is het tegenovergestelde van multiply. (Het heet geen 'divide' of zo, omdat er niet gedeeld wordt, maar onder andere vermenigvuldigd. Dat het volgens wiskundigen het tegenovergestelde van 'multiply' is, is toch wel 'n aanduiding dat wiskundigen een geheel opmerkelijk eigen kijk op de wereld hebben.)

De tekst- en achtergrondkleur worden eerst gecomplementeerd: ze worden veranderd in hun complementaire kleur. Dat is de 'tegenovergestelde' kleur. Twee complementaire kleuren vormen samen altijd wit. De complementaire kleur van bijvoorbeeld het donkergrijze rgb(51, 51, 51) is rgb(214, 214, 214). Als je deze twee kleuren bij elkaar optelt, krijg je rgb(255, 255, 255): wit.

Goed, de kleuren worden dus gecomplementeerd. Vervolgens worden ze met elkaar vermenigvuldigd. En het resultaat daarvan wordt nogmaals gecomplementeerd.

De uiteindelijke kleur is nooit donkerder dan voor- of achtergrondkleur. Als een van beide kleuren wit is, is de uiteindelijke kleur altijd wit. Als een van beide kleuren zwart is, blijft de originele kleur bewaard.

Hierboven staat in elk blokje twee keer het woord 'screen'. Van de uiteindelijke kleuren heeft alleen 'screen' onderin het eerste blokje voldoende contrast met de achtergrond om duidelijk leesbaar te zijn. Waaruit weer het belang van de juiste combinatie van kleuren en mode blijkt.

De uiteindelijke voorgrondkleur in het derde blokje varieert, omdat de kleur van de achtergrond varieert.

overlay

Achtergrond eerste blokje, tekst bovenin eerste en tweede blokje: rgb(51, 51, 51) (donkergrijs).

Achtergrond tweede blokje, tekst onderin eerste en tweede blokje, tekst derde blokje: rgb(204, 204, 204) (lichtgrijs).

Tekst: mix-blend-mode: overlay;

Uitgebreider verhaal over kleuren en dergelijke zie Hieronder wordt elke mode...

Als de achtergrondkleur donkerder is dan de voorgrondkleur, wordt multiply gebruikt. Als de achtergrondkleur lichter is dan de voorgrondkleur, wordt screen gebruikt. De achtergrondkleur wordt niet helemaal vervangen, maar gemengd met de voorgrondkleur. Deze mode is het omgekeerde van hard-light.

Hierboven staat in de bovenste helft 'over-', in de onderste helft 'lay'. Omdat de achtergrondkleur wordt gemengd met de voorgrondkleur, is het verschil anders dan bij de modes 'multiply' en 'screen'.

darken

Achtergrond eerste blokje, tekst bovenin eerste en tweede blokje: rgb(51, 51, 51) (donkergrijs).

Achtergrond tweede blokje, tekst onderin eerste en tweede blokje, tekst derde blokje: rgb(204, 204, 204) (lichtgrijs).

Tekst: mix-blend-mode: darken;

Uitgebreider verhaal over kleuren en dergelijke zie Hieronder wordt elke mode...

'Darken' betekent letterlijk 'donkerder maken'. Voor de uiteindelijke kleur wordt de donkerste van voor- en achtergrondkleur gebruikt. Hierbij worden rood, groen en blauw apart bekeken. Dit is het tegenovergestelde van lighten.

Hierboven staat in de bovenste helft 'dar-', in de onderste helft 'ken'.

In het eerste blokje is de kleur van de achtergrond rgb(51, 51, 51). De kleur van de tekst is bovenin rgb(51, 51, 51) en onderin rgb(204, 204, 204). In beide combinaties is 51 donkerder dan 204. De uiteindelijke kleur wordt dus rgb(51, 51, 51). Omdat dit hetzelfde is als de achtergrondkleur, zie je de tekst niet.

In het tweede blokje is de kleur van de achtergrond rgb(204, 204, 204). De kleur van de tekst is bovenin rgb(51, 51, 51) en onderin rgb(204, 204, 204). 51 is donkerder dan 204, dus de uiteindelijke voorgrondkleur wordt rgb(51, 51, 51), waardoor de tekst bovenin is te zien.

Onderin het tweede blokje zijn voorgrond- en achterkleur hetzelfde. De uiteindelijke kleur blijft hierdoor hetzelfde als de voorgrondkleur, want er is geen donkerder kleur. De tekst heeft hier dezelfde kleur als de achtergrond en valt weg tegen de achtergrond.

De uiteindelijke voorgrondkleur in het derde blokje varieert weer, omdat de kleur van de achtergrond varieert.

lighten

Achtergrond eerste blokje, tekst bovenin eerste en tweede blokje: rgb(51, 51, 51) (donkergrijs).

Achtergrond tweede blokje, tekst onderin eerste en tweede blokje, tekst derde blokje: rgb(204, 204, 204) (lichtgrijs).

Tekst: mix-blend-mode: lighten;

Uitgebreider verhaal over kleuren en dergelijke zie Hieronder wordt elke mode...

'Lighten' betekent letterlijk 'lichter maken'. Voor de uiteindelijke kleur wordt de lichtste van voor- en achtergrondkleur gebruikt. Hierbij worden rood, groen en blauw apart bekeken. Dit is het tegenovergestelde van darken.

Hierboven staat in de bovenste helft 'ligh-', in de onderste helft 'ten'.

In het eerste blokje is de kleur van de achtergrond rgb(51, 51, 51). De kleur van de tekst is bovenin rgb(51, 51, 51), hetzelfde als de achtergrondkleur. De uiteindelijke kleur blijft hierdoor hetzelfde als de achtergrondkleur, want er is geen lichtere kleur. De tekst valt hierdoor weg tegen de achtergrond.

Onderin het eerste blokje is de tekstkleur rgb(204, 204, 204). 204 is lichter dan 51, hierdoor wordt de uiteindelijke kleur onderin rgb(204, 204, 204). Onderin het eerste blokje is de tekst daardoor wel te zien.

In het tweede blokje is de kleur van de achtergrond rgb(204, 204, 204). De kleur van de tekst is bovenin rgb(51, 51, 51). 204 is lichter dan 51, dus de voorgrondkleur wordt bovenin rgb(204, 204, 204), hetzelfde als de achtergrondkleur.

Onder het tweede blokje is de kleur van de tekst rgb(204, 204, 204), hetzelfde als de achtergrondkleur. Er is geen lichtere kleur, dus de kleur van de tekst verandert niet. Ook onderin het tweede blokje is de tekst daardoor niet te zien.

De uiteindelijke voorgrondkleur in het derde blokje varieert weer, omdat de kleur van de achtergrond varieert.

color-dodge

Achtergrond eerste blokje, tekst bovenin eerste en tweede blokje: rgb(51, 51, 51) (donkergrijs).

Achtergrond tweede blokje, tekst onderin eerste en tweede blokje, tekst derde blokje: rgb(204, 204, 204) (lichtgrijs).

Tekst: mix-blend-mode: color-dodge;

Uitgebreider verhaal over kleuren en dergelijke zie Hieronder wordt elke mode...

Dit is het tegenovergestelde van color-burn.

Eerst wordt de voorgrondkleur gecomplementeerd: hij wordt veranderd in z'n complementaire kleur. Dat is de 'tegenovergestelde' kleur. Twee complementaire kleuren vormen samen altijd wit. De complementaire kleur van bijvoorbeeld het donkergrijze rgb(51, 51, 51) is rgb(214, 214, 214). Als je deze twee kleuren bij elkaar optelt, krijg je rgb(255, 255, 255): wit.

De uiteindelijke kleur wordt gevormd door de achtergrondkleur te delen door de gecomplementeerde voorgrondkleur. Dit laat de achtergrondkleur oplichten (op de plaatsen waar voorgrond- en achterkleur elkaar overlappen, wat hier de plaats is, waar de tekst staat).

Als de voorgrondkleur zwart is, zie je alleen de ongewijzigde achtergrondkleur. De voorgrondkleur verdwijnt dan helemaal.

Hierboven staat bovenin 'color-' en onderin 'dodge'. Wat hier nou eigenlijk precies gebeurt, is mij niet helemaal duidelijk. Ik vrees dat alleen experts dit soort dingen kunnen voorspellen. Gewoon uitproberen werkt voor gewone stervelingen het beste.

color-burn

Achtergrond eerste blokje, tekst bovenin eerste en tweede blokje: rgb(51, 51, 51) (donkergrijs).

Achtergrond tweede blokje, tekst onderin eerste en tweede blokje, tekst derde blokje: rgb(204, 204, 204) (lichtgrijs).

Tekst: mix-blend-mode: color-burn;

Uitgebreider verhaal over kleuren en dergelijke zie Hieronder wordt elke mode...

Dit is het tegenovergestelde van color-dodge.

Eerst wordt de achtergrondkleur gecomplementeerd: hij wordt veranderd in z'n complementaire kleur. Dat is de 'tegenovergestelde' kleur. Twee complementaire kleuren vormen samen altijd wit. De complementaire kleur van bijvoorbeeld het donkergrijze rgb(51, 51, 51) is rgb(214, 214, 214). Als je deze twee kleuren bij elkaar optelt, krijg je rgb(255, 255, 255): wit.

De gecomplementeerde achtergrondkleur wordt gedeeld door de voorgrondkleur, en het resultaat daarvan wordt weer gecomplementeerd. Dat levert de uiteindelijke kleur op. Dit maakt de achtergrondkleur donkerder (op de plaatsen waar voorgrond- en achterkleur elkaar overlappen, wat hier de plaats is, waar de tekst staat).

Als de voorgrondkleur wit is, zie je alleen de ongewijzigde achtergrondkleur. De voorgrondkleur verdwijnt dan helemaal.

Hierboven staat bovenin 'color-' en onderin 'burn'. Wat hier nou eigenlijk precies gebeurt, is mij niet helemaal duidelijk. Ik vrees dat alleen experts dit soort dingen kunnen voorspellen. Gewoon uitproberen werkt voor gewone stervelingen het beste.

hard-light

Achtergrond eerste blokje, tekst bovenin eerste en tweede blokje: rgb(51, 51, 51) (donkergrijs).

Achtergrond tweede blokje, tekst onderin eerste en tweede blokje, tekst derde blokje: rgb(204, 204, 204) (lichtgrijs).

Tekst: mix-blend-mode: hard-light;

Uitgebreider verhaal over kleuren en dergelijke zie Hieronder wordt elke mode...

Als de achtergrondkleur lichter is dan de voorgrondkleur, wordt multiply gebruikt. Als de achtergrondkleur donkerder is dan de voorgrondkleur, wordt screen gebruikt. De achtergrondkleur wordt niet helemaal vervangen, maar gemengd met de voorgrondkleur. Deze mode is het omgekeerde van overlay.

Hierboven staat in de bovenste helft 'hard-', in de onderste helft 'light'. Omdat de achtergrondkleur wordt gemengd met de voorgrondkleur, is het verschil anders dan bij de modes 'multiply' en 'screen'.

soft-light

Achtergrond eerste blokje, tekst bovenin eerste en tweede blokje: rgb(51, 51, 51) (donkergrijs).

Achtergrond tweede blokje, tekst onderin eerste en tweede blokje, tekst derde blokje: rgb(204, 204, 204) (lichtgrijs).

Tekst: mix-blend-mode: soft-light;

Uitgebreider verhaal over kleuren en dergelijke zie Hieronder wordt elke mode...

Als de achtergrondkleur lichter is dan de voorgrondkleur, wordt multiply gebruikt. Als de achtergrondkleur donkerder is dan de voorgrondkleur, wordt screen gebruikt. De achtergrondkleur wordt niet helemaal vervangen, maar gemengd met de voorgrondkleur. Deze mode is een zachtere versie van hard-light.

Hierboven staat in de bovenste helft 'soft-', in de onderste helft 'light'. Omdat de achtergrondkleur wordt gemengd met de voorgrondkleur, is het verschil anders dan bij de modes 'multiply' en 'screen'.

difference

Achtergrond eerste blokje, tekst bovenin eerste en tweede blokje: rgb(51, 51, 51) (donkergrijs).

Achtergrond tweede blokje, tekst onderin eerste en tweede blokje, tekst derde blokje: rgb(204, 204, 204) (lichtgrijs).

Tekst: mix-blend-mode: difference;

Uitgebreider verhaal over kleuren en dergelijke zie Hieronder wordt elke mode...

De donkerste kleur wordt van de lichtste kleur afgetrokken (de waarden voor rood, groen en blauw ieder weer apart). Het verschil levert de uiteindelijke kleur op.

Als een van de kleuren zwart is, gebeurt er niets. Wat logisch is, want zwart is rgb(0, 0, 0), en als je 0 ergens vanaf trekt, maakt dat geen verschil.

Als een van de kleuren wit is, is het resultaat de complementaire kleur: de 'tegenovergestelde' kleur. Twee complementaire kleuren vormen samen altijd wit, rgb(255, 255, 255). Als je van wit 'n kleur aftrekt, krijg je daarom per definitie de complementaire kleur.

Hierboven staat bovenin 'diffe-', onderin staat 'rence'.

Bovenin het eerste blokje en onderin het tweede blokje zijn de kleuren van voor- en achtergrond hetzelfde. Als je die van elkaar aftrekt, is het resultaat rgb(0, 0, 0). Bij beide is de tekst dan ook zwart.

Onderin het eerste blokje en bovenin het tweede blokje zijn de kleuren van voor- en achtergrond rgb(204, 204, 204) en rgb(51, 51, 51), alleen zijn voor- en achtergrondkleur verwisseld. Als je het donkerder 51 van het lichtere 204 aftrekt, is de resulterende kleur rgb(153, 153, 153). Beide hebben dan ook dezelfde tekstkleur.

In het derde blokje is de uiteindelijk kleur nogal wild. Dit levert een heel speciaal effect op, waarbij de tekst toch nog redelijk leesbaar is.

exclusion

Achtergrond eerste blokje, tekst bovenin eerste en tweede blokje: rgb(51, 51, 51) (donkergrijs).

Achtergrond tweede blokje, tekst onderin eerste en tweede blokje, tekst derde blokje: rgb(204, 204, 204) (lichtgrijs).

Tekst: mix-blend-mode: exclusion;

Uitgebreider verhaal over kleuren en dergelijke zie Hieronder wordt elke mode...

Bovenin staat 'exclu-', onderin 'sion'. Deze mode is hetzelfde als difference, maar levert een iets zachter resultaat op.

hue

Achtergrond eerste blokje, tekst bovenin eerste en tweede blokje: rgb(51, 51, 51) (donkergrijs).

Achtergrond tweede blokje, tekst onderin eerste en tweede blokje, tekst derde blokje: rgb(204, 204, 204) (lichtgrijs).

Tekst: mix-blend-mode: hue;

Uitgebreider verhaal over kleuren en dergelijke zie Hieronder wordt elke mode...

saturation
color
luminosity

De modes 'hue', 'saturation', 'color' en 'luminosity' werken anders dan de eerdere modes. De eerdere modes rekenden met de afzonderlijke waarden voor rood, groen en blauw, terwijl deze modes op een of andere manier gelijktijdig met deze drie waarden werken.

Deze modes gebruiken 'hue', 'saturation' en 'luminosity', een alternatieve manier om kleuren te definiëren. In css kan dat met de hsl()-notatie. Dit schijnt vooral handig te zijn, als de kleur veranderd moet worden. Persoonlijk heeft het me nooit aangetrokken.

Wat deze modes precies doen, is me dan ook niet helemaal duidelijk. Mensen die ervaring hebben met hsl(), zullen dat waarschijnlijk wel weten. Maar die hebben deze hele uitleg vermoedelijk niet nodig. In ieder geval: voor de volledigheid staan ze er hier bij.

Bij 'hue' worden de 'hue' van de voorgrondkleur en de 'saturation' en 'luminosity' van de achtergrondkleur gebruikt.

Bij 'saturation' worden de 'saturation' van de voorgrondkleur en de 'hue' en 'luminosity' van de achtergrondkleur gebruikt.

Bij 'color" worden de 'hue' en 'saturation' van de voorgrondkleur en de 'luminosity' gebuikt.

Bij 'luminosity' worden de 'luminosity' van de voorgrondkleur en de 'hue' en 'saturation' gebruikt.

Elementen niet laten meedoen met blenden

Opbouw van het gebruikte voorbeeld

Het is natuurlijk hartstikke mooi, als je allerlei elementen zich met elkaar kunt laten vermengen. Maar soms kan het nodig zijn één of meer elementen te verbieden deel te nemen aan deze groepsorgie. Daarvoor bestaan een aantal mogelijkheden, de een iets lastiger dan de ander.

Op de afbeelding hieronder staat zo'n groepsorgie van elementen: 12 effen achtergrondkleuren en één achtergrond-afbeelding staan (gedeeltelijk) over elkaar heen. Met behulp van mix-blend-mode: difference; worden de overlappende delen met elkaar geblend:

Dit voorbeeld is redelijk gestoord. In de praktijk zul je niet zo snel zoveel elementen met elkaar willen blenden. Maar dit oorbeeld geeft de mogelijkheid 'n aantal dingen te laten zien.

Als je de html bekijkt, wordt dit hopelijk wat overzichtelijker. Het chaotische uiterlijk ontstaat, omdat alles met alles wordt geblend. Hieronder volgen de vier belangrijkste onderdelen.

De hele handel staat in een gewone <div> met een achtergrond-afbeelding, die hieronder is te zien:

Binnen deze <div> staat weer een <div>, waarbinnen de twaalf <div>'s met de effen achtergrond zitten. Dit geeft de mogelijkheid om deze twaalf <div>'s als één groep te behandelen, waarvan later gebruik gemaakt gaat worden. Deze <div> is normaal genomen niet zichtbaar, maar wordt op de afbeelding hieronder even zichtbaar gemaakt met behulp van een dikke zwarte border:

Deze <div> is relatief gepositioneerd, waardoor de twaalf <div>'s met de achtergrondkleuren ten opzichte van deze <div> gepositioneerd kunnen worden. De twaalf <div>'s zijn in drie groepjes onderverdeeld, die elk ook weer in een <div> staan. Vijf bovenin, twee in het midden en vijf onderaan. Dit geeft de mogelijkheid de vijf bovenste, twee middelste en vijf onderste elk als één groep te behandelen, waarvan later gebruikt gemaakt gaat worden.

Op de afbeelding hieronder staan de vijf bovenste <div>'s, maar nu zonder dat ze geblend worden met het blauwe raster, de twee middelste en de vijf onderste <div>'s. Ze worden nog wel met elkaar geblend. De smallere kleuren geven aan, waar ze elkaar overlappen en met elkaar geblend worden:

Hieronder staan op de afbeelding de twee middelste <div>'s, maar nu zonder dat ze gemengd worden met het blauwe raster, de vijf bovenste en de vijf onderste <div>'s. Deze <div>'s staan gedeeltelijk buiten en gedeeltelijk over de bovenste en onderste <div>'s:

Ten slotte op de afbeelding hieronder de vijf onderste <div>'s, maar nu zonder dat ze gemengd worden met het blauwe raster, de vijf bovenste en de twee middelste <div>'s. Ze worden nog wel met elkaar geblend. De smallere kleuren geven aan, waar ze elkaar overlappen en met elkaar geblend worden:

De relevante html:

<div>(<div> met raster) <div>(wrapper-<div>) <div>(voor bovenste vijf <div>'s) <div></div>(blauw) <div></div>(groen) <div></div>(geel) <div></div>(oranje) <div></div>(cyaan) </div> <div>(voor middelste twee <div>'s) <div></div>(chocolade) <div></div>(lichtgroen) </div> <div>(voor onderste vijf <div>'s) <div></div>(bruin) <div></div>(goud) <div></div>(wit) <div></div>(rood) <div></div>(zilver) </div> </div> </div>

De css die voor het blenden zorgt, is heel simpel. De twaalf <div>'s waarachter tussen haakjes kleuren staan (vijf bovenin, twee in het midden en vijf onderin) hebben allemaal een class die begint met 'a-niet-blend'. De class van de bovenste <div> (blauw) is 'a-niet-blend-blauw', die van de alleronderste <div> (zilver) is 'a-niet-blend-silver', enzovoort.

Omdat de class van alle twaalf <div>'s die moeten blenden hetzelfde begin heeft, kan dat blenden worden geregeld met

div[class ^= "a-niet-blend"] {mix-blend-mode: difference;}

De selector [class ^= "a-niet-blend"] geeft aan, dat de naam van de class moet beginnen met 'a-niet-blend'. (Omdat daarachter voor elk van de twaalf <div>'s nog een unieke kleur volgt, kan elke <div> ook apart worden geselecteerd. Dat is hier verder niet van belang, maar wel op de site. Daar kunnen de voorbeelden worden aangepast, omdat de <div>'s ook apart kunnen worden aangesproken.)

Eén of meer afzonderlijke elementen niet blenden: mix-blend-mode: normal;

Als je nu één of meer van deze <div>'s niet wilt laten meedoen met het blenden, geef je die in de css gewoon mix-blend-mode: normal;. Hiermee wordt voor de betreffende <div> het blenden uitgeschakeld. Op de afbeelding hieronder is dit gedaan bij de groene <div> bovenin, de lichtgroene <div> midden rechts en de gouden <div> onderin:

Deze drie <div>'s worden nu niet meer geblend met wat eronder zit.

De <div>'s die in de html op deze drie <div>'s volgen, blenden nog gewoon met deze drie <div>'s. Want bij die <div>'s is mix-blend-mode: difference; nog gewoon werkzaam.

Dat is vooral bij de lichtgroene <div> rechts in het midden goed te zien. De <div> helemaal rechtsonder staat over een deel van de linkerhelft van de lichtgroene <div> heen. De <div> helemaal rechtsonder blendt daar nog gewoon met de lichtgroene <div>. Maar het raster zie je niet meer, want de lichtgroene <div> zelf blendt niet meer en is gewoon egaal lichtgroen.

(Uiteraard kun je dit in dit geval ook oplossen door bij de negen <div>'s die moeten blenden mix-blend-mode: difference; op te geven. Bij de drie <div>'s die niet moeten blenden, geef je gewoon niets op. De standaardwaarde van mix-blend-mode is 'normal', dus deze <div>'s blenden dan ook niet.)

Onderliggende elementen niet laten blenden: de stacking context

Het kan gebeuren dat je onderliggende elementen niet wilt laten blenden met wat erboven zit. Als je in het gebruikte voorbeeld 'n foto zou blenden, moet die vermoedelijk niet blenden met het raster op de achtergrond, om maar iets te noemen.

In het voorbeeld worden de twaalf <div>'s niet alleen met elkaar, maar ook met de achtergrond-afbeelding van de buitenste <div>, het raster, geblend. Dat blenden met het raster kun je echter voorkomen, terwijl de <div>'s nog wel met elkaar blenden.

Blenden beperkt zich tot de 'stacking context', waar het te blenden element bij hoort. (Een Nederlandse vertaling voor 'stacking context' bestaat niet.) Om blenden te kunnen beperken, moet je dus eerst weten wat een stacking context is, en hoe je een nieuwe stacking context kunt maken.

Het is ook in het algemeen handig om te weten, wat een stacking context is. Je kunt vrij makkelijk onbedoeld een nieuwe stacking context maken, bijvoorbeeld als je opacity gebruikt. Dat kan onbedoelde bijwerkingen hebben die lastig zijn op te lossen, als je niet weet, wat een stacking context is.

Blenden gebeurt alleen met elementen die in dezelfde stacking context zitten. Als je dus op een of andere manier ergens 'n nieuwe stacking context kunt laten beginnen, wordt met de daaronder zittende elementen niet meer geblend.

De bovenste vijf <div>'s die worden geblend, zitten in een gemeenschappelijke ouder-<div>. Als je zou kunnen zorgen dat die ouder-<div> een nieuwe stacking context gaat vormen, wordt met het daaronder zittende element – de <div> met het raster-achtergrond – niet meer geblend.

Om de ouder-<div> een nieuwe stacking context te laten vormen, hoef je alleen maar één van de volgende eigenschappen te gebruiken bij de ouder-<div>:

  • position: absolute; of position: relative; én z-index met een andere waarde dan 'auto';
  • position: fixed; of position: sticky;
  • Een flex item met een z-index met een andere waarde dan 'auto', ook als geen position is opgegeven. (Een flex item is een direct kind van een element met display: flex;.)
  • opacity met een waarde minder dan 1;
  • mix-blend-mode met een waarde anders dan 'normal';
  • Eén van de volgende eigenschappen met een waarde anders dan 'none': transform, filter, perspective, clip-path, mask, mask-image, mask-border;
  • isolation: isolate;
  • will-change met als waarde een eigenschap die een nieuwe stacking context maakt, als bij die eigenschap een andere waarde dan de initiële wordt gebruikt. (Dat klinkt ingewikkeld. Je kunt er meer over lezen op dev.opera.com. Je kunt ook gewoon onthouden dat je bij gebruik van will-change de kans loopt een nieuwe stacking context te maken.)
  • -webkit-overflow-scrolling: touch; (Dit wordt gebruikt op iOS om soepel te kunnen scrollen binnen bijvoorbeeld een <div>.)

(Een uitstekende uitleg over wat een stacking context is, is te vinden op 'The stacking context' op developer.mozilla.org. De lijst hierboven met eigenschappen die een nieuwe stacking context vormen, is ook daarvan overgenomen.)

De html voor de bovenste vijf <div>'s die worden geblend is als volgt:

<div>(voor bovenste vijf <div>'s) <div></div>(blauw) <div></div>(groen) <div></div>(geel) <div></div>(oranje) <div></div>(cyaan) </div>

Als bij de buitenste <div> één van de hierboven genoemde eigenschappen wordt gebruikt, worden de onder die <div> zittende elementen niet meer geblend, zoals op de afbeelding hieronder is te zien:

De buitenste <div> heeft nu als het ware 'n soort bodem onder de vijf bovenste <div>'s gelegd, waardoor die niet meer blenden met wat er onder de buitenste <div> zit. Het achtergrond-raster, dat de achtergrond van de grootouder van de buitenste <div> is, is niet meer te zien binnen de vijf geblende <div>'s.

Maar de <div>'s blenden nog wel gewoon met de middelste en onderste <div>'s, waar ze deze overlappen. Niet alleen het raster is verdwenen in de bovenste vijf <div>'s, maar ook de kleur is veranderd. Dat komt omdat niet alleen niet meer met het patroon van het raster, maar ook niet meer met de blauwe kleur daarvan wordt geblend.

Op dezelfde manier kun je ook de twee middelste <div>'s van het raster (en eventuele andere eronder zittende achtergronden) isoleren. Op de afbeelding hieronder worden de twee middelste <div>'s niet met de achtergrond geblend:

Ook de twee middelste <div>'s zitten in een gezamenlijke <div>. Als je die gezamenlijke <div> één van de genoemde eigenschappen geeft, blenden de middelste <div>'s niet meer met het raster, maar nog wel met de andere <div>'s, waar ze die overlappen.

De onderste vijf <div>'s kunnen op dezelfde manier worden geïsoleerd van het raster: geef aan hun gezamenlijke ouder-<div> één van de genoemde eigenschappen.

De bovenste vijf, middelste twee en onderste vijf <div>'s staan in drie ouder-<div>'s. Die drie <div>'s staan ook weer in één gezamenlijke <div>. Als je aan die gezamenlijke <div> één van de genoemde eigenschappen geeft, mengen de twaalf <div>'s zich geen van alle meer met de achterliggende elementen. Op de afbeelding hieronder is de achtergrond-afbeelding met het raster helemaal verdwenen uit de binnenste <div>'s:

Onderling worden de vijftien <div>'s nog steeds geblend, maar het raster is uit de vijftien <div>'s verdwenen.

Een fout die makkelijk wordt gemaakt: er wordt geprobeerd een nieuwe stacking context te maken bij het element, waarbij mix-blend-mode is opgegeven. Dat werkt dus niet. Het element waarbij mix-blend-mode is opgegeven, blendt zich altijd met het onderliggende element. Want dat is nou juist de functie van mix-blend-mode.

Je moet ónder het te blenden element (of onder de te blenden elementen) één van de genoemde eigenschappen opgeven. Hier kan dat vrij makkelijk, omdat de vijftien <div>'s al in drie gezamenlijke ouders staan, met daarboven weer 'n gemeenschappelijke grootouder. Maar als dat niet zo is, moet je het te isoleren elementen, of de te isoleren elementen, in een ouder zetten. Die ouder geef je dan één van de genoemde eigenschappen.

Op de afbeelding hieronder zijn alleen de witte en rode <div> aan de onderkant van de onderliggende elementen geïsoleerd:

De vijftien <div>'s blenden nog steeds met elkaar, waar ze elkaar overlappen. Ook is het raster overal te zien, behalve in de witte en rode <div> aan de onderkant. De html voor de onderste vijf <div>'s is wat aangepast:

<div>(voor onderste vijf <div>'s) <div></div>(bruin) <div></div>(goud) <div>(extra toegevoegde <div>) <div></div>(wit) <div></div>(rood) </div> <div></div>(zilver) </div>

De extra toegevoegde <div> heeft isolation: isolate; gekregen en schermt daardoor de erin zittende witte en rode <div> af van de eronder zittende elementen.

Met welke eigenschap maak je het best een nieuwe stacking context?

Dat is niet simpel te zeggen.

Als je bijvoorbeeld toch al de eigenschap opacity gebruikt, wordt die nieuwe stacking context daardoor ook automatisch aangemaakt. Dat geldt voor meer eigenschappen.

Sommige eigenschappen hebben bijwerkingen. Die kunnen soms handig zijn, maar soms juist niet.

Op de eerste afbeelding hierboven (in bredere browservensters de afbeelding links) is aan de gemeenschappelijke <div> voor de bovenste vijf <div>'s position: relative; z-index: 10; gegeven. Dit maakt een nieuwe stacking context aan voor de bovenste vijf <div>'s, waardoor het onderliggende raster niet meer is te zien. Maar omdat z-index is gebruikt, komen de bovenste <div>'s nu boven de onderste <div>'s te staan, terwijl ze daar normaal genomen onder zouden komen te staan.

Op de tweede afbeelding hierboven (rechts in bredere browservensters) is aan de gemeenschappelijke <div> voor de onderste vijf <div>'s position: relative; z-index: 10; gegeven. Ook hier ontstaat weer een nieuwe stacking context, maar nu staan de onderste vijf <div>'s gewoon boven de vijf bovenste <div>'s.

Welke eigenschap je het best kunt gebruiken, is een kwestie van nadenken en uitproberen. Bijkomend probleem is dat mix-blend-mode tamelijk nieuw is en dat er soms nog wat verschillen tussen browsers zijn:

Afbeelding 6: verschil in weergave tussen Firefox en Google Chrome

Hierboven is voor de onderste vijf <div>'s weer een nieuwe stacking context gemaakt, maar nu met behulp van isolation: isolate; bij de ouder van de vijf <div>'s. Links staat de weergave in Google Chrome, rechts in Firefox. Html en css zijn bij beide precies hetzelfde. Chrome zet de onderste vijf <div>'s boven de middelste en bovenste <div>', Firefox zet ze eronder.

Bij gebruik van opacity: 0.99; zien ze er weer hetzelfde uit in beide browsers.

Kortom: uitgebreid testen.

Overigens is dit voorbeeld wel heel erg ingewikkeld. In de praktijk zal blenden zich vaak beperken tot tekst boven een afbeelding, twee foto's over elkaar heen, en dat soort dingen. Daarbij zul je tegen minder problemen aanlopen dan bij dit ingewikkelde voorbeeld.

Kinderen (bijvoorbeeld tekst) niet laten blenden

Het niet laten blenden van onderliggende elementen is relatief makkelijk. Je maakt 'n nieuwe stacking context, zoals iets hierboven wordt beschreven bij Onderliggende elementen niet laten blenden: de stacking context. Dat is zogezegd stoppen met blenden richting ouders van het geblende element.

Kinderen van een geblend element niet laten blenden is een heel stuk ingewikkelder. Als een element wordt geblend, wordt de héle inhoud van dat element geblend. Er wordt als het ware 'n foto van dat element gemaakt, en die foto wordt geblend. Inclusief borders, kinderen, tekst, noem maar op. Alles wat in dat geblende element zit. Naar de ouders toe kun je dat blenden stoppen door bijvoorbeeld met isolation: isolate; een nieuwe stacking context te maken, maar voor kinderen van een geblend element bestaat zoiets niet.

Waarom er geen simpele methode hiervoor bestaat, weet ik niet. Mogelijk zijn er goede technische redenen voor die mijn pet (ver) te boven gaan.

Hieronder staan twee voorbeelden, waarvan html en css vrijwel hetzelfde zijn:

NN
NN

Beide bestaan uit vijf geneste <div>'s met een verschillende achtergrondkleur, die elk geblend worden met mix-blend-mode: difference;. De vijf <div>'s staan in een buitenste <div> met zwarte achtergrondkleur, die niet wordt geblend.

In beide voorbeelden staan in het midden in een <span> de letters 'NN'. Links staat die <span> in de binnenste geneste <div>. Rechts staat de <span> buiten de geneste <div>'s, het is een direct kind van de buitenste <div>.

De html:

Links:Rechts:

<div>(buitenste, zwart)<div> <div>(blauw)<div> <div>(groen)<div> <div>(geel)<div> <div>(oranje)<div> <div>(cyaan)<div> <span>NN</span></div> </div></div> </div></div> </div></div> </div></div> </div><span>NN</span> </div></div>

De html is vrijwel hetzelfde, alleen staat de <span> met de letters 'NN' rechts buiten de vijf geneste <div>'s die worden geblend.

De css is links en rechts ook vrijwel hetzelfde. De vijf binnenste <div>'s worden geblend, achtergrondkleuren, breedte, enzovoort zijn allemaal hetzelfde.

Links en rechts wordt de <span> met behulp van een absolute positie op de juiste plaats gezet. Dat is het enige verschil in de css: top en left verschillen, omdat de uitgangspositie van de <span> links en rechts verschilt.

Links wordt de binnenste cyaankleurige <div> met alles erin geblend met de oranje <div>, voor zover ze elkaar overlappen. Die oranje <div> wordt vervolgens met alles erin geblend met de gele <div>, voor zover ze elkaar overlappen. Enzovoort. 'Met alles erin': dat geldt dus ook voor de <span> met de letters.

Rechts gebeurt precies hetzelfde. De binnenste cyaankleurige <div> met alles erin wordt geblend met de oranje <div>, voor zover ze elkaar overlappen. Enzovoort. Maar rechts zit de <span> met de letters niet binnen de oranje <div>, dus het blenden van de oranje <div> heeft geen invloed op de letters. Dat geldt ook voor de andere vijf <div>'s die worden geblend: de <span> met de letters staat er niet in, dus het blenden heeft er geen invloed op.

Rechts houden de letters dan ook hun eigen witte kleur, terwijl de letters links alle kleuren van de regenboog hebben gekregen.

Als je de <span> rechts ook nog mix-blend-mode: difference; zou geven, zou het resultaat totaal anders zijn dan op de afbeelding hierboven links. Op die afbeelding worden de <div>'s (met alles erin, dus ook de letters) van boven naar beneden afgewerkt. De letters blenden dus elke keer als het ware mee. Als je rechts de letters ook zou blenden, worden die geblend met het eindresultaat van de vijf al geblende <div>'s. Het uiteindelijke resultaat daarvan is op de afbeelding hieronder te zien:

NN
Blenden kan dingen, ook tekst, volledig onzichtbaar maken!

Nieuwe dingen zoals blenden worden vaak wild enthousiast ontvangen op allerlei sites die met het maken van websites te maken hebben. Daardoor ontstaat soms de indruk dat zo'n beetje iedereen deze eigenschappen en tags al gebruikt. Volgens een onderzoek van Microsoft wordt in juli 2017 op 0,051% van de pagina's mix-blend-mode gebruikt. Dat percentage zal waarschijnlijk gaan stijgen, als Edge het gaat ook gaat ondersteunen.

Wat ik hiermee maar bedoel: er is geen enkele reden om dit overhaast te gaan gebruiken, 'omdat iedereen het doet'. Lang niet alle browsers ondersteunen mix-blend-mode, en als je niet heel goed oplet kunnen dingen hierdoor volledig onzichtbaar worden. Datzelfde kan gebeuren in browsers die het wel ondersteunen, als bijvoorbeeld om een of andere reden een (achtergrond-)afbeelding niet wordt weergegeven. Om het nog maar niet te hebben over bugs en afwijkingen, die bij nieuw geïmplementeerde eigenschappen bepaald geen uitzondering zijn.

Blenden verandert de kleur van bijvoorbeeld tekst. Als de achtergrond-afbeelding niet wordt weergegeven, kan hierdoor de kleur van de tekst volledig veranderen. Als tekst goed leesbaar is, als deze wordt geblend, kan het prima dat de tekst volstrekt onleesbaar is in browsers die blenden niet ondersteunen. Hetzelfde geldt uiteraard voor bijvoorbeeld twee foto's die met elkaar worden geblend.

In het voorbeeld zijn voor tekst en achtergronden kleuren gekozen, die ook nog leesbaar zijn, als niet wordt geblend. In het voorbeeld wordt de tekst eerst gewoon leesbaar weergegeven voor browsers die blenden niet ondersteunen. Daarna wordt met @supports (mix-blend-mode: normal) gekeken, of een browser blenden ondersteunt. En pas als dat zo blijkt te zijn, wordt de kleur van tekst en/of achtergrond aangepast. Hierdoor wordt de tekst leesbaar weergegeven in browsers die blenden niet en in browsers die blenden wel ondersteunen.

Daarnaast is het voorbeeld ook getest, als de afbeeldingen niet werden weergegeven, zowel in browsers die blenden wel en die blenden niet ondersteunen.

In totaal is dus vier keer op leesbaarheid getest: met afbeelding en met blenden; zonder afbeelding en met blenden; met afbeelding en zonder blenden; zonder afbeelding en zonder blenden. In alle gevallen is de tekst nog leesbaar, hoewel soms niet echt optimaal.

Afbeelding 7: bij blenden is tekskt leesbaar, bij niet-blenden niet

Hierboven staat de foto met tekst uit het voorbeeld. Links de weergave in een browser die blenden ondersteunt, rechts nogmaals dezelfde weergave in een browser die blenden niet ondersteunt. De tekst op de rechterfoto is grotendeels vrijwel onleesbaar.

In het voorbeeld wordt daarom boven de foto zwarte tekst op een doorzichtige achtergrond gebruikt. Pas als met @supports (mix-blend-mode: normal) is vastgesteld dat een browser blenden ondersteunt, wordt de achtergrond onder de tekst weggehaald en wordt de tekstkleur verandert naar 'n soort beige.

css voor alle vensters

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

#geen-mix

Het element met id="geen-mix'. Binnen deze <div> staat een melding deze browser mix-blend-mode niet wordt ondersteund. Deze melding wordt alleen weggehaald, als verderop bij @supports (mix-blend-mode: normal) blijkt dat de browser mix-blend-mode ondersteunt.

Als een oudere browser @supports niet ondersteunt, wordt de code bij @supports niet uitgevoerd en blijft deze melding dus staan. Dat is geen probleem, want als een browser @supports niet ondersteunt, ondersteunt die browser zeker mix-blend-mode niet.

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: 500px;

Breedte.

max-width: 90%;

Een breedte in procenten is normaal genomen ten opzichte van de ouder van het element. Die ouder is hier <main>, een blok-element. Een blok-element wordt normaal genomen automatisch even breed als z'n ouder. De ouder van <main> is <body>, ook weer een blok-element. Ook <body> wordt hierdoor normaal genomen automatisch 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 wordt <div> dus nooit breder dan maximaal 90% van de breedte van het venster, ongeacht hoe breed dit is.

Hier gelijk boven is een breedte van 500 px opgegeven. In browservensters smaller dan 500 px zou hierdoor horizontaal gescrold moeten worden om de volledige tekst in deze <div> te kunnen lezen. Door de breedte te beperken tot maximaal 90% van de breedte van het venster, wordt dit voorkomen.

margin: 10px auto 0;

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

Boven een kleine marge voor wat afstand tot de bovenkant van het browservenster. Onderaan geen marge.

Links en rechts auto, wat hier hetzelfde betekent als evenveel. De <div> staat hierdoor altijd horizontaal gecentreerd binnen z'n ouder <main>, ongeacht de breedte van <main>.

Omdat <main> even breed is als het venster van de browser, zoals iets hierboven bij max-width: 90%; beschreven, staat de <div> horizontaal gecentreerd binnen het venster, ongeacht hoe breed dit is.

border: red solid 10px;

Dikke rode rand, zodat de melding (hopelijk) opvalt.

padding: 1%;

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

#geen-mix p

Alle <p>'s binnen het element met id="geen-mix". Binnen deze <p>'s staat de tekst voor browsers die mix-blend-mode niet ondersteunen.

margin: 0;

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

#een, #drie

De elementen met id="een" en id="drie". Binnen div#een staat het voorbeeld met de twee foto's bovenaan de pagina, binnen div#drie staan de vier groepjes met gekleurde cirkels onderaan de pagina.

background: white;

Witte achtergrond.

display: flex;

Hiermee worden deze twee <div>'s in een zogenaamde 'flex container' veranderd. Dit maakt het veel makkelijker om de directe kinderen van die elementen, de 'flex items', netjes verdeeld binnen het venster van de browser neer te zetten.

Oudere browsers ondersteunen flexbox niet en negeren daarom deze regel. De kinderen van div#een en div#drie zijn <p>'s en komen daarom, als blok-element, op een nieuwe regel te staan. Om dit te voorkomen wordt verderop bij #een p en #drie p:not(:last-child) display: inline-block; aan deze <p>'s opgegeven (behalve bij de laatste <p> in div#drie). Hierdoor staan ze ook in oudere browsers niet onder, maar naast elkaar.

(In sommige van die oudere browsers is een verouderde versie van flexbox geïmplementeerd. Die bevat echter zoveel bugs, dat alleen gediplomeerde masochisten die gebruiken.)

flex-wrap: wrap;

Standaard worden kinderen van een flex container naast elkaar gezet. Als die kinderen te breed zijn, worden ze verkleind, of moet je horizontaal scrollen. Met deze regel worden de kinderen, als er te weinig ruimte is, niet naast maar onder elkaar gezet.

justify-content: space-around;

Hiermee wordt de horizontale verdeling van de flex items – de directe kinderen van div#een en div#drie – geregeld. Tussen alle <p>'s zit evenveel ruimte. Links van de eerste <p> en rechts van de laatste <p>, dat is helemaal aan de buitenkant, zit half zoveel ruimte als tussen de <p>'s.

Verder hoef je hier niets voor te doen: flexbox verdeelt de overblijvende ruimte automatisch. Als het browservenster smaller of breder wordt, worden de tussenruimtes automatisch aangepast.

Afbeelding 8
Afbeelding 8: het onderste voorbeeld. Met een simpel justify-content: space-around; wordt de overblijvende ruimte automatisch gelijk verdeeld over de vier <p>'s. (De vijfde <p> met het onderschrift past er niet meer naast, die staat onder de cirkels. Deze <p> is hier weggelaten.)
text-align: center;

Tekst horizontaal centreren.

Deze regel is bedoeld voor browsers die flexbox niet kennen. De <p>'s in div#een en div#drie worden verderop bij #een p en #drie p:not(:last-child) met display: inline-block; in 'n soort combinatie van inline- en blok-element veranderd (behalve de laatste <p> in div#drie). Hierdoor kunnen ze, net als tekst, worden gecentreerd binnen hun ouder.

Het resultaat is iets minder mooi dan bij flexbox, maar de hele handel staat in ieder geval horizontaal gecentreerd.

max-width: 95%;

Normaal genomen wordt een <div> automatisch even breed als z'n ouder. Die ouder is hier <main>. Een breedte in procenten is normaal genomen ten opzichte van de ouder van het element. Met deze regel wordt de breedte van #een en #drie beperkt tot maximaal 95% van de breedte van <main>.

<main> is een blok-element. Een blok-element wordt normaal genomen automatisch even breed als z'n ouder. De ouder van <main> is <body>, ook weer een blok-element. Ook <body> wordt hierdoor normaal genomen automatisch 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 worden div#een en div#drie dus nooit breder dan maximaal 95% van de breedte van het venster, ongeacht hoe breed dit is.

margin: 10px auto 0;

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

Aan de bovenkant een kleine marge voor wat afstand tot het erboven zittende element (of bij div#een eventueel tot de bovenkant van het browservenster). Onderaan geen marge.

Links en rechts auto, wat hier hetzelfde betekent als evenveel. De <div> staat hierdoor altijd horizontaal gecentreerd binnen z'n ouder <main>, ongeacht de breedte van <main>.

Omdat <main> even breed is als het venster van de browser, zoals iets hierboven bij max-width: 95%; beschreven, staan div#een en div#drie horizontaal gecentreerd binnen het venster, ongeacht hoe breed dit is.

border: black solid 1px;

Zwart randje.

#een p

Alle <p>'s in het element met id="een". Dat zijn er hier drie. In de eerste twee staan de twee foto's met opschrift van het eerste voorbeeld, in de derde staat het onderschrift onder de foto's.

display: inline-block;

Een <p> is een blok-element en wordt daarom normaal genomen op een nieuwe regel gezet. Maar iets hierboven bij #een, #drie worden de <p>'s met display: flex; veranderd in flex items. Hierdoor staan de eerste twee <p>'s met de foto's niet onder, maar naast elkaar. De derde <p> met het onderschrift past er niet meer naast, die wordt onder de foto's gezet.

Oudere browsers kennen flexbox niet en negeren de bijbehorende eigenschappen. Voor deze browsers is deze regel bedoeld. De <p>'s worden nu een soort kruising tussen een inline- en een blok-element: ze worden naast elkaar gezet, terwijl toch eigenschappen als breedte gebruikt kunnen worden.

margin: 5px;

Aan alle kanten een marge van 5 px.

Een <p> heeft van zichzelf een marge aan boven- en onderkant. Die wordt hier iets kleiner gemaakt.

In smallere browservensters kunnen de eerste twee <p>'s, en daardoor de erin zittende foto's, tegen elkaar aan komen te staan. De marge links en rechts zorgt dat er altijd wat afstand tussen beide <p>'s is.

position: relative;

In elk van de twee eerste <p>'s zit een <span>, waarin de tekst staat die boven de foto komt te staan. Die <span> wordt gelijk hieronder bij #een span met een absolute positie op de juiste plaats gezet. Om te kunnen positioneren ten opzichte van de <p>, moet de <p> zelf ook een positie hebben. Omdat voor top en dergelijke verder niets wordt opgegeven, heeft dit geen invloed op de <p>'s zelf.

#een span

Alle <span>'s binnen het element met id="een". Binnen div#een zitten twee <span>'s, één met tekst voor boven de eerste foto, en één met tekst voor boven de tweede foto.

Hier wordt gezorgd dat de tekst boven de foto's leesbaar is, door de <span> een doorzichtig witte achtergrond met zwarte tekst te geven. Hierdoor is de tekst ook leesbaar in browsers die mix-blend-mode niet ondersteunen.

Pas als bij @supports (mix-blend-mode: normal) wordt vastgesteld dat een browser mix-blend-mode ondersteunt, worden bij de <span> boven de eerste foto bij #een p:first-of-type span de achtergrond- en voorgrondkleur veranderd.

(Meer over de risico's van onleesbare tekst is te vinden bij Blenden kan dingen, ook tekst, volledig onzichtbaar maken!)

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

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, enzovoort. Daarbij is A gelijk aan het tientallige 10, B aan 11, enzovoort. 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 behoorlijk doorzichtig: 0.4. Hierdoor zie je de foto nog enigszins door de achtergrond heen, maar is de tekst toch nog leesbaar.

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%;

De <span> wordt niet breder dan nodig is om de erin zittende tekst weer te geven. Door de lengte van de tekst in de <span> wordt min of meer toevallig de volle breedte van de <p>'s met de foto gevuld, waardoor de tekst netjes horizontaal gecentreerd boven de foto staat. Maar bij een andere tekst, of als de bezoeker de letters heeft verkleind, kan de <span> smaller dan de <p> met de foto worden, en staat de tekst niet meer gecentreerd.

Een breedte in procenten is normaal genomen ten opzichte van de ouder van het element. Door deze regel wordt de <span> altijd even breed als de <p>, en dus ook als de daarin zittende foto.

max-width: 100%;

Dit is min of meer het omgekeerde van gelijk hierboven. Als de bezoeker de lettergrootte heeft verhoogd, kan de tekst – en daarmee de <span> – breder worden dan de <p> met de foto. Maar door deze regel kan de <span> nooit breder worden dan de <p>.

Althans: een woord als 'Koninginnedag' wordt niet afgebroken en zou daardoor nog steeds breder worden dan de <p>, en daardoor buiten de foto komen te staan. Door de overflow-wrap iets hieronder kan 'Koninginnedag' op elke willekeurige plaats worden afgebroken.

max-height: 160px;

Als de bezoeker de lettergrootte heeft verhoogd, past de tekst mogelijk niet meer binnen de <p>. Hiermee wordt de hoogte van de <span> beperkt tot maximaal 160 px.

De foto, en daarmee de <p> waar de foto in zit, is 193 px hoog. Maar in hele smalle browservensters is de foto lager. Daarom is een maximumhoogte genomen, die iets minder is dan 193 px.

Als de tekst niet binnen deze hoogte past, kan de tekst door de overflow: auto; gelijk hieronder worden gescrold. Op deze manier wordt voorkomen dat er tekst verdwijnt.

overflow: auto;

Als de tekst in de <span> niet binnen de hierboven opgegeven maximumhoogte van 160 px past, kan de tekst worden gescrold. Afhankelijk van browser en besturingssysteem kan rechts van de <span> een scrollbalk worden getoond.

Afbeelding 9: bij grote lettergrootte kan tekst wegvallen

Op de afbeelding hierboven staat links het opschrift zonder maximumbreedte en -hoogte bij de <span>, waardoor de tekst gewoon volledig wordt weergegeven. Het woord 'Vondelpark' verdwijnt volledig onder het eronder zittende element. En als gelijk rechts van de foto een element zou zitten, zou een deel van 'Koninginnedag' daaronder verdwijnen.

Op de afbeelding rechts hierboven is aan de <span> wel een maximumbreedte en -hoogte gegeven, waardoor overflow: auto; werkt. Firefox op Linux toont rechts een scrollbalk. Het woord 'Koninginnedag' is afgebroken achter de tweede 'n', en het woord 'Vondelpark' achter de 'r'. Je moet nu wel scrollen, maar het hele opschrift is te lezen.

font-size: 2em;

Tamelijk grote letter.

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

word-wrap: break-word; overflow-wrap: break-word;

Deze twee eigenschappen betekenen hetzelfde. word-wrap bestaat al langer en werd door alle browsers ondersteund. Waarop w3c het kennelijk geestig vond om de naam te veranderen naar overflow-wrap. Wat dus precies hetzelfde doet. Wat het nut is van deze verandering? Geen flauw idee. Gelukkig vieren ze bij w3c niet al te vaak feestjes, waarbij kennelijk wat te diep in het glaasje wordt gekeken.

Maar goed. Nog niet alle browsers ondersteunen overflow-wrap;, daarom wordt ook de oudere vorm word-wrap gebruikt.

Normaal genomen zou een lang woord als 'Koninginnedag' niet worden afgebroken. Door deze regel kan het woord op elke willekeurige plaats worden afgebroken, ook midden in een lettergreep.

(Je kunt ook automatisch afbreken aanzetten, maar lang niet alle browsers ondersteunen dit, en zeker niet in het Nederlands. Je zou ook in de html &shy; kunnen gebruiken op plaatsen, waar mag worden afgebroken. Maar in beide gevallen levert dit extra afbreekstreepjes op. Dit is 'n simpele oplossing die hier acceptabel is, want de kans op te grote letters is niet zo heel groot.)

text-align: center;

Tekst horizontaal centreren.

position: absolute;

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

Normaal genomen zou de <span> met de tekst gewoon onder het vorige element komen te staan, onder de foto. Hier moet de tekst echter juist boven de foto komen te staan.

Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier de <p>, waar de <span> in zit. Deze heeft bij #een p een relatieve positie gekregen.

Een <span> is van zichzelf een inline-element. Daardoor kunnen eigenschappen als breedte en hoogte niet worden gebruikt. Door de <span> absoluut te positioneren verandert deze in 'n soort blok-element en kunnen deze eigenschappen wel worden gebruikt.

top: 30px; left: 0;

Normaal genomen zou de <span> gewoon achter het vorige element, de foto, worden neergezet. Nu wordt de <span> met de tekst boven de foto gezet, 30 px vanaf de bovenkant en helemaal links.

#een p:last-child, #twee p:last-child, #drie p:last-child

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.

#een p {display: inline-block; margin: 5px; position: relative;}

In div#een, div#twee en div#drie zit respectievelijk het bovenste, het middelste en het onderste voorbeeld. Elk van deze drie <div>'s heeft een aantal kinderen, kleinkinderen, enzovoort.

Kinderen van dezelfde ouder kunnen worden geteld, net zoals dat bij kinderen uit een gezin het geval is: eerste kind, tweede kind, derde kind, enzovoort. Je kunt elementen selecteren op basis van het volgnummer binnen zo'n reeks kinderen. In dit geval wordt geen echt volgnummer gebruikt, maar :last-child: het laatste kind. Toevallig komt het hier zo uit, dat het drie keer om het laatste kind gaat.

#een: het element met id="een".

p: alle <p>'s binnen #een.

:last-child: nou, toch niet alle <p>'s. Alleen de <p> die het laatste kind is. Binnen deze <p> zit het onderschrift onder het voorbeeld.

In normale mensentaal: de <p> binnen div#een die het laatste kind is. Dit is de <p> met het onderschrift.

Voor #twee p:last-child en #drie p:last-child geldt precies hetzelfde verhaal, alleen dan binnen div#twee en div#drie.

De selector :last-child kan onverwachte bijwerkingen hebben. De <p>'s met het onderschrift zijn toevallig alle drie het laatste kind van div#een, div#twee en div#drie. Maar er zitten meer laatste kinderen in die <div>'s.

Het eigenlijke voorbeeld in div#een bijvoorbeeld zit in een <p>, en in die <p> zit ook een laatste kind: de <span> met het opschrift voor de foto. Daarom staat er een p voor :last-child: het laatste kind móét een <p> zijn. Hierdoor wordt de <span> met het opschrift niet aangesproken. Zou je de p voor :last-child weglaten, dan blijken er opeens veel meer laatste kinderen te zijn en verandert de lay-out in een ouderwets gezellige familie-reünie met alle laatste kinderen: een puinhoop.

Ook moet je zeker weten dat het te selecteren element inderdaad het laatste kind is. Dat is hier echt het geval: de <p> met het onderschrift is altijd het laatste kind van div#een, div#twee of div#drie. Maar als later aan de html een element toegevoegd zou worden dat na de <p> met het onderschrift komt te staan, is die <p> ineens geen laatste kind meer.

Verder mogen andere elementen binnen div#een, div#twee of div#drie niet ook een <p> als laatste kind hebben. Als bijvoorbeeld binnen div#een een geneste <div> staat met daarin als laatste kind een <p>, zou deze selector ook voor die <p> gelden. Want die is ook 'n laatste kind. (Dit laatste zou je kunnen oplossen door het toevoegen van >: #een > p:last-child. Nu geldt de selector alleen voor directe kinderen van div#een.)

Maar in dit geval is deze selector zonder problemen te gebruiken.

Niet alle hieronder opgegeven eigenschappen zijn voor elk van de drie <p>'s met onderschrift nodig, maar ze veroorzaken geen problemen, als ze niet nodig zijn. Door alles hier te combineren voor de drie <p>'s, spaar je wat css uit.

background: white;

Witte achtergrond.

color: black;

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%;

Iets verderop bij #twee p wordt de breedte van de <p>'s in div#twee beperkt tot 50% van de breedte van div#twee. De <p> met het onderschrift moet echter even breed zijn als div#twee.

Een breedte in procenten is normaal genomen ten opzichte van de ouder. Hiermee wordt de <p> met het onderschrift in div#twee dus even breed als div#twee.

font-size: 1em;

Iets verderop bij #twee p wordt de lettergrootte van de <p>'s in div#twee vergroot tot 2 em. De <p> met het onderschrift moet echter een gewone lettergrootte krijgen.

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

font-weight: normal;

Iets verderop bij #twee p wordt de tekst vet gemaakt. De <p> met het onderschrift moet echter gewone tekst krijgen.

text-align: left;

Iets eerder bij #een, #drie wordt de tekst in div#een en div#drieM gecentreerd, en iets verderop bij #twee p gebeurt dat met de <p>'s in div#twee. De onderschriften moeten niet worden gecentreerd.

margin: 0;

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

border-width: 1px;

Iets verderop bij #twee p wordt de border 2 px breed gemaakt. De border rondom de <p> met het onderschrift moet echter slechts 1 px breed zijn.

border-top: black solid 1px;

Lijntje tussen voorbeeld en onderschrift.

padding: 5px;

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

#twee

Het element met id="twee". In div#twee zit het voorbeeld met het woord 'Raster'.

background: url(../121-pics/raster.jpg) #399;

Achtergrond-afbeelding.

Naast de afbeelding is ook een donkergroene (#399) achtergrondkleur opgegeven. In browsers die mix-blend-mode ondersteunen, wordt de kleur van de tekst aangepast aan de kleur van het eronder zittende element. Oftewel: aan de achtergrond-afbeelding.

Als die afbeelding om een of andere reden niet wordt weergegeven, zou je normaal genomen de beige achtergrondkleur van de pagina zien. De tekst wordt dan geblend met de achtergrondkleur van de pagina. Daarbij blijkt het derde woord 'Raster' volledig weg te vallen tegen de achtergrondkleur van de pagina.

Nu wordt de achtergrondkleur van div#twee, als de achtergrond-afbeelding niet wordt weergegeven, donkergroen. Als de tekst daarmee wordt geblend, is ook het derde woord 'Raster' leesbaar.

max-width: 95%;

Maximumbreedte.

Normaal genomen wordt een blok-element zoals een <div> automatisch even breed als z'n ouder. Hier wordt de breedte beperkt tot 95% van de breedte van de ouder, dat is hier <main>.

<main> is ook een blok-element en wordt daarom normaal genomen ook weer automatisch even breed als z'n ouder. De ouder van <main> is <body>, ook weer een blok-element. Ook <body> wordt hierdoor normaal genomen automatisch 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 wordt div#twee dus nooit breder dan maximaal 95% van de breedte van het venster, ongeacht hoe breed dit is.

box-sizing: border-box;

Hier gelijk boven heeft de <div> een breedte van 95% gekregen, even breed als de erboven staande div#een en de eronder staande div#drie bij #een, #drie hebben gekregen. Hierdoor zijn de drie <div>'s met de voorbeelden alle drie even breed, wat er netter uitziet.

div#twee krijgt hieronder echter links en rechts een padding van 5px en een border van 1 px. Normaal genomen worden padding en border bij de breedte opgeteld, waardoor de breedte van div#twee 1px + 5px + 95% + 5px + 1px wordt, 12 px breder dan div#een en div#drie.

Door deze regel worden padding en border niet bij de breedte opgeteld, maar er binnen gezet. Hierdoor blijft de uiteindelijke breedte van div#twee ook beperkt tot 95% van de breedte van <main>.

overflow: hidden;

Normaal genomen wordt een blok-element zoals een <div> automatisch precies hoog genoeg om de inhoud ervan weer te kunnen geven. Hier echter worden iets verderop bij #twee p de <p>'s met het woord 'Raster' in div#twee naar links gefloat. Daardoor worden deze <p>'s genegeerd voor de hoogte van div#twee. En andere kinderen heeft div#twee niet. Dat betekent dat div#twee niet hoger wordt dan de 10 px padding aan boven- en onderkant, die iets hieronder aan de <div> worden gegeven.

Hier iets boven is aan div#twee een achtergrond-afbeelding gegeven. Een achtergrond-afbeelding heeft zelf geen hoogte en breedte, maar vult alleen het element waar hij in zit. Om de achtergrond van div#twee ook achter de <p>'s met 'Raster' te krijgen, moet div#twee daarom hoger worden gemaakt dan de 10 px van de padding.

Het simpelste kan dat door overflow: hidden; aan div#twee te geven. Dit zorgt voor een nieuwe zogenaamde 'block formatting context', wat in dit geval betekent dat de hoogte van de <p>'s wel meetelt voor de hoogte van div#twee.

(Ook een ander probleem wordt hiermee gelijk opgelost. De onder div#twee zittende div#drie heeft geen minimumbreedte. Daardoor wordt div#drie in de kleine overblijvende ruimte rechts van de gefloate <p>'s uit div#twee geperst. De inhoud van div#drie staat daar vervolgens keurig netjes gecentreerd en zo, maar wel volledig op de verkeerde plaats. Op onderstaande afbeelding is het weliswaar artistieke, maar toch niet tevreden stemmende resultaat te zien, als overflow: hidden; niet wordt gebruikt:

Afbeelding 10: zonder overflow: hidden wordt de lay-out een puinhoop

(Overigens zijn er ook andere oplossingen mogelijk. Maar overflow: hidden; is in dit geval een heel eenvoudige oplossing.)

margin: 10px auto 0;

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

Boven een kleine marge voor wat ruimte tussen het bovenste en het middelste voorbeeld. Onderaan geen marge.

Links en rechts auto, wat in dit geval betekent: evenveel. Hierdoor staat div#twee altijd horizontaal gecentreerd binnen z'n ouder <main>, ongeacht de breedte van <main>.

Omdat <main> even breed is als het venster van de browser, zoals wordt iets hierboven wordt beschreven bij max-width: 95%; staat div#twee hierdoor altijd horizontaal gecentreerd binnen het venster, ongeacht hoe breed dit is.

padding: 5px;

Aan alle kanten kleine ruimte tussen inhoud en buitenkant van de <div>.

border: black solid 1px;

Zwart randje.

#twee p

Voor een deel van 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.

#een p:last-child, #twee p:last-child, #drie p:last-child {background: white; color: black; width: 100%; height: auto; float: none; font-size: 1em; font-weight: normal; text-align: left; border-top: black solid 1px; padding: 10px;}

Alle <p>'s in het element met id="twee". Dit zijn de vier <p>'s met 'Raster' en de <p> met het onderschrift daaronder.

Deze css is voor alle vijf de <p>'s, maar de vijfde <p> met het onderschrift ziet er heel anders uit dan de eerste vier <p>'s met 'Raster'. Eerder is bij #een p:last-child, #twee p:last-child, #drie p:last-child een groot deel van onderstaande css voor de <p> met het onderschrift aangepast.

Normaal genomen zou deze css de eerdere css voor de vijfde <p> overrulen, omdat hij deze css later in de stylesheet staat. Maar in dit geval is dat niet zo, omdat de eerdere selector #twee p:last-child meer specificiteit, meer 'gewicht' heeft dan de hier gebruikte selector #twee p. De selector hier heeft één id #twee en één element p. De eerdere selector heeft dat ook, maar heeft ook de pseudo-class :last-child. Daardoor heeft de eerdere selector meer specificiteit en heeft de css bij die selector toch voorrang boven de hier opgegeven css.

box-sizing: border-box;

Hier gelijk onder worden de <p>'s 50% breed gemaakt, zodat er altijd twee naast elkaar passen. Iets verderop wordt echter aan de <p>'s een border van 2 px gegeven, waardoor de <p>'s niet meer 50%, maar 50% + 4 px breed zijn, want die border wordt bij de breedte opgeteld. (4 px, want ze krijgen links én rechts een border.)

Door deze regel wordt de border niet bij de breedte opgeteld, maar binnen die 50% gezet. Nu passen er toch twee <p>'s naast elkaar.

width: 50%;

Breedte 50%.

Een breedte in procenten is normaal genomen ten opzichte van de ouder van het element. Hier is dat div#twee, die bij #twee een breedte van maximaal 95% van de breedte van het browservenster heeft gekregen. In smallere vensters is div#twee daardoor ook smaller, met als gevolg dat ook de <p>'s smaller zijn. Hierdoor past het woord 'Raster' mogelijk niet meer volledig in de <p>. Dat wordt gelijk hieronder bij overflow opgelost.

overflow: hidden;

Zoals gelijk hierboven beschreven past in smalle browservensters het woord 'Raster' mogelijk niet meer volledig in de <p>. Door deze regel wordt het deel dat niet past gewoon afgekapt. Normaal genomen is dat niet zo'n goed idee: als een sprookje te lang is voor een element, is het ietwat kindonvriendelijk om het sprookje dan maar af te kappen en het einde stomweg te verbergen.

Afbeelding 11: zonder overflow: hidden komt in smallere vensters alles over elkaar heen te staan

Hier is dat echter geen probleem, want dit voorbeeld gaat alleen maar over het aanpassen van de kleur van de tekst aan de achtergrond. Het is geen ramp als een deel van het woord 'Raster' wegvalt. Het is wel een ramp, als dat niet gebeurt. Zoals op de afbeelding is te zien, wordt het dan 'n grote chaos van over elkaar heen staande woorden in de meest woeste kleuren.

float: left;

Normaal worden blok-elementen zoals een <p> op een nieuwe regel gezet. Door ze naar links te floaten, worden ze naast elkaar gezet. Pas als de regel vol is, wordt een nieuwe regel begonnen.

Omdat de <p>'s iets hierboven 50% breed zijn gemaakt, komen er twee naast elkaar te staan. Met uitzondering van de vijfde <p> met het onderschrift, want die is bij #een p:last-child, #twee p:last-child, #drie p:last-child 100% breed gemaakt en komt dus op een eigen regel te staan.

font-size: 5em;

Lekker grote letter, zodat het effect van het blenden goed zichtbaar is.

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

Als de bezoeker de lettergrootte verhoogd, past het woord 'Raster' mogelijk niet meer in de <p>. In de hoogte is dat geen probleem, want omdat geen hoogte is opgegeven, groeit de hoogte van de <p> gewoon mee met de lettergrootte.

Maar in de breedte kan 'Raster' wel te breed worden. Dat maakt niets uit, want door het iets hierboven opgegeven overflow: hidden; wordt het te veel gewoon afgekapt. Normaal genomen is dat geen goed idee, maar voor dit voorbeeld maakt het niets uit als een deel van het woord 'Raster' verdwijnt.

font-weight: bold;

Vette letter, zodat het effect van het blenden beter is te zien.

Een vette letter is een apart ontworpen font, waarbij lang niet alle delen van een letter even veel vetter worden. Vaak wordt zelfs de vorm van een letter volledig veranderd. Als een font geen vette letter heeft, imiteert de browser een vette letter door een normale letter vet te maken. Er wordt met 'n soort verfroller over de letter gegaan, waarbij gewoon alles dikker wordt gemaakt. Elke grafisch ontwerper krijgt van het resultaat een acute depressie.

Op deze site worden overwegend de fonts Arial en Helvetica gebruikt, omdat deze in (vrijwel) elke computer zijn geïnstalleerd. Deze fonts hebben ook vette fonts, dus hier gaat het goed. Maar als je bij een font zonder aparte vette variant font-weight: bold; gebruikt, kun je prima 'n heel lelijk resultaat krijgen.

text-align: center;

De tekst staat in een <span>, een inline-element. Door deze regel wordt die <span> horizontaal gecentreerd binnen de <p>, en daarmee de daarin zittende tekst ook.

margin: 0 0 5px;

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

Van zichzelf heeft een <p> een marge aan boven- en onderkant. Hier blijft alleen de marge aan de onderkant staan. Deze zorgt voor 'n kleine afstand tussen twee boven elkaar staande <p>'s met 'Raster', en voor 'n kleine afstand tussen de onderste <p> met 'Raster' en de <p> met het onderschrift.

border: black solid 2px;

Randje van 2 px breed.

#twee p:nth-of-type(even)

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.

#twee p {box-sizing: border-box; width: 50%; overflow: hidden; float: left; font-size: 5em; font-weight: bold; text-align: center; margin: 0 0 5px; border: black solid 2px;}

In div#twee zit het middelste voorbeeld met het woord 'raster'. Deze <div> heeft een aantal kinderen, kleinkinderen, enzovoort, waaronder een aantal <p>'s. Om precies te zijn: vijf <p>'s. Vier met het woord 'Raster', en één met het onderschrift daaronder.

Bij de tweede en vierde <p>, dat zijn de twee <p>'s met Raster aan de rechterkant, moet de border links worden verwijderd. Je kunt die twee <p>'s 'n class geven, maar er is een simpeler selector mogelijk.

Kinderen van dezelfde ouder kunnen worden geteld, net zoals dat bij kinderen uit een gezin het geval is: eerste kind, tweede kind, derde kind, enzovoort. Je kunt ook alleen 'n bepaald soort element tellen, net zoals je alleen kinderen van jonger of ouder dan zes jaar kunt tellen. Met de selector :nth-of-type() worden alleen elementen van een bepaald soort geteld.

#twee: het element met id="twee".

p: alle <p>'s binnen #twee.

:nth-of-type(): het element met een bepaald volgnummer. Het volgnummer staat tussen haakjes, dat komt gelijk hieronder aan de beurt. Omdat voor :nth-of-type() een p staat, worden alleen <p>'s geteld. Als div#twee 327 <span>'s als direct kind heeft, tellen die niet mee. Hadden ze maar 'n <p>moeten zijn.

:nth-of-type(even): in dit geval moeten toevallig alleen de even <p>'s worden geselecteerd. Dan kun je het woord 'even' gebruiken in plaats van een getal of berekening. De tweede en vierde <p> worden geselecteerd, de eerste, derde en vijfde niet. In dit geval vervangt deze selector :nth-of-type(2) en :nth-of-type(4).

In normale mensentaal: de tweede en vierde <p> binnen div#twee. Dit zijn de twee <p>'s met 'Raster' aan de rechterkant.

De selector :nth-of-type() kan onverwachte bijwerkingen hebben. In dit geval zitten er maar vijf <p>'s in div#twee, die allemaal een direct kind van div#twee zijn. Maar als binnen div#twee bijvoorbeeld nog 'n geneste <div> zou zitten, waarin ook twee of meer <p>'s zouden zitten, zouden ook de even <p>'s uit die <div> onder deze selector vallen. (Dit zou je in dit geval kunnen oplossen door het toevoegen van >: #twee > p:nth-of-type(even). Nu geldt de selector alleen voor directe kinderen van div#twee.)

Als er later aan de html een <p> wordt toegevoegd, kunnen de even <p>'s plotsklaps oneven zijn, en omgekeerd.

Kortom: een handige selector, mits voorzichtig gebruikt.

border-left: none;

De vier <p>'s met 'Raster' hebben bij #twee p een border van 2 px breed gekregen. Er staan echter twee <p>'s naast elkaar. Hierdoor komen de verticale borders van de naast elkaar staande <p>'s tegen elkaar aan te staan, waardoor deze border geen 2 maar 4 px breed wordt. Door bij de <p>'s rechts de border links weg te halen, wordt dat voorkomen.

#twee span

Alle <span>'s binnen het element met id="twee". Het woord 'Raster' zit binnen een <span>. In totaal zijn er vier <span>'s, één voor elk woord.

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

Enigszins doorzichtig witte achtergrond. Hoe rgba() precies werkt, is te vinden bij background: rgba(255, 255, 255, 0.4);. Het enige verschil is dat de doorzichtigheid hier iets minder is.

Afbeelding 12: tekst op doorzichtige achtergrond zonder blenden

Op de afbeelding is te zien hoe de doorzichtige achtergrond, in combinatie met de gelijk hieronder opgegeven zwarte voorgrondkleur voor de tekst, eruit ziet. Het is niet het effect dat je met blenden krijgt, maar de tekst is in ieder geval leesbaar. En de achtergrond-afbeelding is vaag te zien, omdat de achtergrondkleur enigszins doorzichtig is.

color: black;

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.

padding: 0 10px;

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

Boven en onder geen padding, links en rechts 10 px. In dit geval zorgt dit er alleen maar voor, dat de <span> iets breder wordt dan de erin zittende tekst. Hierdoor wordt ook de achtergrondkleur iets breder dan de tekst. Als dat niet zo zou zijn, zou de achtergrondkleur precies op de rand van de tekst worden afgekapt, wat 'n beetje Hitchkock-achtig overkomt.

(Hitchkock? Is dat een haperende kok of zoiets? Nou nee. Maar zoek even op internet en er gaat een hele prehistorische culturele wereld voor je open...)

#drie p:not(:last-child)

In div#drie zit het onderste voorbeeld. Deze <div> heeft een aantal kinderen, kleinkinderen, enzovoort.

Kinderen van dezelfde ouder kunnen worden geteld, net zoals dat bij kinderen uit een gezin het geval is: eerste kind, tweede kind, derde kind, enzovoort. Je kunt elementen selecteren op basis van het volgnummer binnen zo'n reeks kinderen. In dit geval wordt geen echt volgnummer gebruikt, maar :not(:last-child) : alle kinderen, behalve het laatste kind. Toevallig komt dat hier zo uit.

#drie: het element met id="een".

p: alle <p>'s binnen #drie.

:last-child: alleen de <p>'s die laatste kind zijn. Binnen deze <p> zit het onderschrift onder de voorbeelden.

:not(:last-child): maar dan omgekeerd. Omdat :last-child binnen :not() staat, worden juist alle <p>'s geselecteerd, behalve de <p>'s die laatste kind zijn. De selector :not() geeft aan, dat wat tussen de haakjes staat, juist níét geselecteerd moet worden.

In normale mensentaal: alle <p>'s binnen div#drie, behalve de <p>'s die laatste kind. Dit zijn de vier <p>'s met in elk een groep cirkels.

De selector :last-child, en daarmee ook de omgekeerde selector :not(:last-child) kan onverwachte bijwerkingen hebben. De <p> met het onderschrift is het laatste kind van div#drie. Deze <p> moet anders worden behandeld dan de eerste vier <p>'s.

Maar er zitten meer laatste kinderen in div#drie. Elke cirkel zit bijvoorbeeld in een <span> binnen een <p>. Al deze <span>'s, behalve de laatste, zouden ook worden geselecteerd door :not(:last-child).

Daarom staat er een p voor :not(:last-child): het mogen alleen <p>'s zijn. Hierdoor worden de <span>'s met de cirkels niet aangesproken. Zou je de p voor :not(:last-child) weglaten, dan blijken in div#drie opeens heel veel eerste, tweede, derde, enzovoort kinderen te zijn.

Ook moet je zeker weten dat het element dat niet geselecteerd moet worden, inderdaad het laatste kind is. Dat is hier echt het geval: de <p> met het onderschrift is altijd het laatste kind van div#drie. Maar als later aan de html een element toegevoegd zou worden dat na de <p> met het onderschrift komt te staan, is die <p> ineens geen laatste kind meer.

Verder mogen andere elementen binnen div#drie geen <p>'s als kind hebben. Als binnen div#drie een geneste <div> staat met daarin 'n aantal <p>'s, zou deze selector ook voor die <p>'s gelden, met uitzondering van de laatste <p>. (Dit laatste zou je in dit geval kunnen oplossen door het toevoegen van >: #drie > p:not(:last-child). Nu geldt de selector alleen voor directe kinderen van div#drie.)

Maar hier is deze selector zonder problemen te gebruiken, want het onderschrift zit per definitie in de laatste <p>.

display: inline-block;

Een <p> is een blok-element en wordt daarom normaal genomen op een nieuwe regel gezet. Maar eerder bij #een, #drie zijn de <p>'s met display: flex; veranderd in flex items. Hierdoor staan de eerste vier <p>'s met de groepen cirkels niet onder, maar naast elkaar. De vijfde <p> met het onderschrift is bij #een p:last-child, #twee p:last-child, #drie p:last-child 100% breed gemaakt en komt daarom op een nieuwe regelt e staan.

Oudere browsers kennen flexbox niet en negeren de bijbehorende eigenschappen. Voor deze browsers is deze regel bedoeld. De <p>'s worden in een soort kruising tussen een inline- en een blok-element veranderd. Ze worden, net als een inline-element, naast elkaar gezet. Maar eigenschappen als breedte, die normaal genomen alleen bij een blok-element gebruikt kunnen worden, zijn toch te gebruiken.

width: 1.5em;

Normaal genomen wordt een blok-element zoals een <p> automatisch even breed als z'n ouder. Hier is dat echter niet het geval, omdat de <p>'s eerder bij #een, #drie met display: flex; zijn veranderd in flex items. Als de browser flexbox niet ondersteunt, gedragen de <p>'s zich, wat de breedte betreft, als een inline-element. In beide gevallen worden de <p>'s niet breder dan nodig is.

Normaal genomen zou de breedte dan worden bepaald door de inhoud van de <p>'s, maar ook dat is hier niet het geval. In elke <p> zitten acht <span>'s. In de eerste zeven <span>'s zit 'n cirkel, in de achtste <span> zit het onder de cirkels staande woord. Al deze <span>'s zijn absoluut gepositioneerd. Dat betekent dat ze geen invloed hebben op de breedte van de <p>'s.

Omdat er buiten de acht <span>'s niets in de <p>'s zit, zijn deze in feite leeg, wat betreft de breedte. De hele <p> bestaat in de breedte in feite uit niet meer dan de iets hieronder opgegeven borders van 2 px breed links en rechts, samen 4 px breed.

Er zijn nu twee mogelijkheden, wat betreft de weergave.

Als de browser flexbox kent, worden de vier <p>'s met cirkels netjes horizontaal verdeeld. Als het venster van de browser te smal wordt, worden één of meer <p>'s op de volgende regel gezet. Dat is precies wat er nu ook gebeurt, alleen zijn de <p>'s dus slechts de 4 px van de border breed, zoals op de afbeelding hieronder is te zien:

Afbeelding 13: met flexbox zonder breedte staan border en tekst verkeerd

De cirkels staan min of meer op de juiste plaats, maar de woorden onder de cirkels zijn zo kort mogelijk afgebroken, omdat ze in een absoluut gepositioneerde <span> zonder breedte zitten. De dikkere zwarte verticale lijnen zijn de borders van de vier <p>'s, waarbinnen de cirkels staan. Slechts een armzalige verticale border is overgebleven van de eens zo fiere <p>, die de cirkels ooit volledig omsloot met een fraaie border. De <p>'s staan nog steeds netjes horizontaal verdeeld, dat wel.

Bij de paar browsers die flexbox nog niet ondersteunen, is het resultaat nog, tja, aparter, getuige onderstaande afbeelding:

Afbeelding 14: zonder flexbox en zonder breedte staan cirkels, border en tekst verkeerd

Ook hier hebben de vier <p>'s geen breedte en zijn alleen de borders te zien. Maar nu worden ze niet netjes horizontaal verdeeld neergezet. Omdat ze als inline-block worden weergegeven, worden ze gewoon naast elkaar gezet, net als tekst. De kleine ruimte die je nog ziet tussen de borders ontstaat door de marge van 5 px die iets hieronder aan de <p>'s wordt gegeven. Bovendien staat elke <p> in de html op een nieuwe regel, en in dat geval wordt er automatisch een spatie tussen de inline-block elementen gezet. Zou je de <p>'s in de html op dezelfde regel zetten en de marge weghalen, dan zou je één verticale lijn van 4 x 4 = 16 px overhouden: alle borders tegen elkaar aan.

Omdat de in de <p>'s zittende <span>'s worden gepositioneerd ten opzichte van de <p>'s, komen deze nu grotendeels over elkaar heen te staan.

Al deze ellende is simpel op te lossen door de <p>'s een breedte te geven. Omdat de cirkels eigenlijk gewone letters 'o' zijn, die sterk vergroot worden weergegeven, wordt als eenheid em genomen en niet een absolute eenheid als px. Hierdoor verandert de breedte mee met de lettergrootte.

height: 1.6em;

Hiervoor geldt hetzelfde verhaal als hierboven bij width: 1.5em; staat, maar nu voor de hoogte. Zonder deze hoogte is alleen een border van 4 px breed aan de bovenkant te zien. De horizontale verdeling blijft wel bestaan, want dit gaat alleen over de hoogte.

De hoogte is met 1,6 em iets groter dan de breedte van 1,5 em, omdat onder de cirkels nog een woord komt te staan.

font-size: 7em;

Hele grote letter.

De cirkels zijn doodgewone letters 'o', maar dan heel groot. Het is niet echt nodig de lettergrootte in de relatieve maat em op te geven, want leesbaar zijn ze echt wel in deze maat. Maar sommige browsers veranderen een lettergrootte in de absolute eenheid px wel en andere niet. Daarom is toch voor de eenheid em gekozen, want die verandert in alle browsers, waarin je de lettergrootte kun aanpassen.

Hierboven zijn ook breedte en hoogte in em opgegeven, waardoor bij een andere lettergrootte alles met de lettergrootte mee verandert en alle verhoudingen bewaard blijven. Bij gebruik van een absolute eenheid als px zou dat niet het geval zijn.

font-weight: bold;

Vette letter. Hierdoor worden de cirkels nog wat breder.

Een vette letter is een apart ontworpen font, waarbij lang niet alle delen van een letter even veel vetter worden. Vaak wordt zelfs de vorm van een letter volledig veranderd. Als een font geen vette letter heeft, imiteert de browser een vette letter door een normale letter vet te maken. Er wordt met 'n soort verfroller over de letter gegaan, waarbij gewoon alles dikker wordt gemaakt. Elke grafisch ontwerper krijgt van het resultaat een acute depressie.

Op deze site worden overwegend de fonts Arial en Helvetica gebruikt, omdat deze in (vrijwel) elke computer zijn geïnstalleerd. Deze fonts hebben ook vette fonts, dus hier gaat het goed. Maar als je bij een font zonder vette variant font-weight: bold; gebruikt, kun je prima 'n heel lelijk resultaat krijgen.

margin: 5px;

Kleine marge aan alle kanten.

De marge links en rechts is niet van belang voor bredere browservensters in browsers die flexbox ondersteunen. Maar voor browsers die flexbox niet ondersteunen en de <p>'s met behulp van het iets hierboven opgegeven display: inline-block; naast elkaar zetten, zorgt de marge voor wat afstand tussen de <p>'s.

In smallere browservensters is de marge ook nodig voor browsers die flexbox wel ondersteunen, want anders worden de <p>'s bij bepaalde breedtes van het venster te dicht bij elkaar, of zelfs tegen elkaar aan, neergezet.

border: black solid 2px;

Randje rondom.

position: relative;

De <span>'s met de de cirkels zitten in deze <p>'s en worden gepositioneerd ten opzichte van deze <p>'s. Om dat te kunnen doen, moeten de <p>'s zelf een positie hebben. Omdat voor top en dergelijke verder niets wordt ingevuld, heeft dit geen invloed op de <p>'s zelf.

#drie span

Alle <span>'s in het element met id="drie". In div#drie zitten vier <p>'s, één voor elk groepje cirkels. Binnen elke <p> zitten zeven <span>'s met een cirkel (eigenlijk 'n grote letter 'o'), en als laatste één <span> met het woord 'mix-blend-mode' of 'opacity'.

opacity: 0.7;

De <span>'s, en daarmee de erin zittende cirkels, enigszins doorzichtig maken. Waar de cirkels elkaar overlappen, verandert de kleur hierdoor enigszins. Dit is bedoeld voor browsers die mix-blend-mode niet ondersteunen in een armzalige poging het blenden enigszins te imiteren.

position: absolute;

Om de <span>'s, en daarmee de erin zittende cirkel of woord, op de juiste plaats neer te kunnen zetten.

Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier de <p>, waar de betreffende <span> in zit. Deze hebben bij #drie p:not(:last-child) een relatieve positie gekregen.

#drie span:first-of-type

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.

#drie span {opacity: 0.7; position: absolute;}

Afbeelding 15: de meest linkse groep cirkels in een browser die blenden niet ondersteunt
Afbeelding 15: De eerste groep cirkels in een browser die mix-blend-mode niet ondersteunt.

In div#drie zit het onderste voorbeeld: de vier groepen cirkels. Elke groep zit in een eigen <p>, er zijn dus vier <p>'. Elke <p> heeft een aantal kinderen: zeven <span>'s met 'n cirkel, en één <span> met het woord onder die cirkels.

Kinderen van dezelfde ouder kunnen worden geteld, net zoals dat bij kinderen uit een gezin het geval is: eerste kind, tweede kind, derde kind, enzovoort. Je kunt ook alleen 'n bepaald soort element tellen, net zoals je alleen kinderen van jonger of ouder dan zes jaar kunt tellen. Met de selector :nth-of-type() worden alleen elementen van een bepaald soort geteld. Omdat het vaak voorkomt dat je het eerste element van 'n bepaald type wilt hebben, heeft dat een aparte selector: :first-of-type.

#drie: het element met id="twee".

span: alle <span>'s binnen #drie.

:first-of-type: het element met een bepaald volgnummer. In dit geval wordt geen volgnummer gebruikt, maar een speciaal voor het eerste element bedoelde selector: :first-of-type. Voor alle latere elementen gebruik je 'n soortgelijke selector, maar dan met een volgnummer: :nth-of-type(). Tussen de haakjes komt het volgnummer. :nth-of-type(1) is precies hetzelfde als :first-of-type, maar de laatste is wat mensvriendelijker.

Omdat voor :first-of-type (of voor latere elementen :nth-of-type()) een span staat, worden alleen <span>'s geteld. Als binnen div#twee 327 <p>'s zitten, tellen die niet mee. Hadden ze maar 'n <span>moeten zijn.

In normale mensentaal: elke eerste <span> binnen div#drie.

In dit geval zijn de <span>'s geen directe kinderen van div#drie, maar van één van de vier daarin zittende <p>'s. Dat maakt echter niets uit, het gaat om elke <span> die een eerste kind is binnen div#drie. En de <span>'s binnen de <p>'s vallen hier ook onder. Dit zijn de vier <span>'s, waarin de eerste cirkel zit.

De selector :first-of-type (of :nth-of-type()) kan onverwachte bijwerkingen hebben. In dit geval zitten er maar vier series <span>'s in div#drie, één in elke <p>. Maar als binnen div#drie bijvoorbeeld nog 'n geneste <div> zou zitten, waarin ook <span>'s zouden zitten, zou deze selector ook voor die <span>'s gelden. (Dit zou je in dit geval kunnen oplossen door het toevoegen van p: #drie p span:first-of-type. Nu geldt de selector alleen voor directe kinderen van een <p> binnen div#drie.)

color: red;

Rode voorgrondkleur. Dit is ook de kleur van de tekst. Omdat de cirkel een gewone letter 'o' is, die alleen wat uit z'n krachten is gegroeid, krijgt hiermee de eerste cirkel binnen elk van de vier <p>'s een rode kleur.

top: -0.03em; left: 0.06em;

De <span>, en daarmee de erin zittende cirkel, op de juiste plaats zetten.

Als eenheid is de relatieve eenheid em genomen, omdat deze mee verandert met de lettergrootte. Bij #drie p:not(:last-child) is aan de de <p>'s (met uitzondering van de laatste <p> met het onderschrift) ook een breedte, hoogte en lettergrootte in em gegeven. Omdat al deze maten mee veranderen met een eventuele andere lettergrootte, blijven de cirkels ook bij een andere lettergrootte netjes op hun plaats staan ten opzichte van elkaar.

#drie span:nth-of-type(2)

{color: orange; top: -0.28em; left: 0.278em;} #drie span:nth-of-type(3) {color: indigo; top: -0.27em; left: 0.58em;} #drie span:nth-of-type(4) {color: green; top: -0.02em; left: 0.78em;} #drie span:nth-of-type(5) {color: blue; top: 0.32em; left: 0.71em;} #drie span:nth-of-type(6) {color: yellow; top: 0.45em; left: 0.4em;} #drie span:nth-of-type(7) {color: violet; top: 0.3em; left: 0.12em;}

Voor de zes <span>'hierboven 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.

#drie span {opacity: 0.7; position: absolute;}

In deze zes <span>'s staan de tweede tot en met zevende cirkel. Het verhaal is precies hetzelfde als voor de eerste <span> bij #drie span:first-of-type, alleen is de selector :first-of-type vervangen door :nth-of-type(), met tussen de haakjes het volgnummer van de <span>. Verder hebben color, top en left andere waarden, omdat de <span>'s een andere kleur en positie moeten krijgen.

#drie span:last-of-type

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.

#drie span {opacity: 0.7; position: absolute;}

Deze selector is het tweelingzusje van #drie span:first-of-type. Maar dan wel 'n twee-eiige tweeling, want ze zien er totaal anders uit. Hoe deze selector werkt is beschreven bij #drie span:first-of-type, alleen gaat het hier niet om de eerste, maar om de laatste <span>: de <span> met het woord onder de cirkels. Deze <span> ziet er anders uit dan de zeven <span>'s met de cirkels, en dat wordt hier geregeld.

:last-of-type is een handige selector, want ook al wordt er een <span> voor gezet, deze <span> blijft altijd de laatste <span>.

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 <span> is een inline-element. Een inline-element kan normaal genomen geen breedte krijgen. Maar bij #drie span is de <span> absoluut gepositioneerd, waardoor deze in een soort blok-element is veranderd. Daardoor kan deze eigenschap toch worden gebruikt.

Een breedte in procenten is normaal genomen ten opzichte van de ouder van het element. Dat is hier de <p>, waarbinnen de cirkels staan. Hierdoor wordt de <span> even breed als deze <p>, waardoor het woord in de <span> netjes onder de cirkels geplaatst kan worden.

font-size: 0.15em;

Dit is een onleesbaar kleine letter. Zou je denken, maar dat klopt niet. Bij #drie p:not(:last-child) is de lettergrootte verhoogd naar 7 em. Omdat ook deze <span>'s binnen die <p>'s zitten, geldt die lettergrootte ook voor deze <span>'s.

Deze kleine lettergrootte geldt dus ten opzichte van de lettergrootte van 7 em. De uiteindelijke lettergrootte wordt hierdoor 0,15 x 7 = 1,05 em, wat een vrijwel normale lettergrootte is. (Je wilt het woord 'mix-blend-mode' echt niet zien in een grootte van 7 em...)

Als eenheid wordt de relatieve eenheid em gebruikt, omdat bij gebruik van een absolute eenheid zoals px niet alle browsers de lettergrootte kunnen veranderen. Omdat ook voor de cirkels en dergelijke de eenheid em is gebruikt, blijft het woord ook bij een andere lettergrootte netjes onder de cirkels staan.

font-weight: normal;

Bij #drie p:not(:last-child) is een vette letter opgegeven. Hier wordt dat voor deze <span>'s weer veranderd naar een normale dikte.

text-align: center;

Tekst horizontaal centreren.

mix-blend-mode: normal;

De de zeven <span>'s met cirkels worden later geblend in browsers die mix-blend-mode ondersteunen. De tekst in deze <span>'s moet niet worden geblend. Dit wordt hier al opgegeven, omdat er dan verderop geen css voor deze <span>'s meer hoeft te worden opgegeven. Browsers die mix-blend-mode niet ondersteunen, negeren deze regel gewoon.

bottom: 0; left: 0;

De <span>'s helemaal onderaan en helemaal links binnen hun <p> zetten. Omdat ze iets hierboven met width: 100%; even breed zijn gemaakt als de <p>, staat de tekst in de <span>'s nu netjes onder de cirkels.

css voor browsers die mix-blend-mode ondersteunen

@supports (mix-blend-mode: normal)

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

De css die binnen deze 'feature query' staat, geldt alleen voor browsers die mix-blend-mode: normal; ondersteunen. (Er bestaat geen goede Nederlandse vertaling voor 'feature query'. Het is een vraag of een bepaalde eigenschap en waarde worden ondersteund: iets als 'eigenschap vraag'.)

@supports: hierachter komt tussen haakjes de te onderzoeken eigenschap met een bepaalde waarde te staan.

mix-blend-mode: de eigenschap waarop wordt getest.

normal: de waarde waarop wordt getest. (Afhankelijk van de eigenschap kan dit ook iets zijn als 10px of 5%.)

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

@supports (mix-blend-mode: normal) { body {color: silver;} (...) rest van de css voor deze @supports-regel (...) footer {color: gold;} }

Voor de eerste css binnen deze @supports-regel staat dus een extra {, en aan het eind staat een extra }.

Je kunt ook als voorwaarde opgeven dat meerdere eigenschappen (en/of waarden) moeten worden ondersteund, of één eigenschap van een rijtje eigenschappen, of dat een eigenschap juist niet mag worden ondersteund, maar dat gebeurt hier allemaal niet. Hier is de enige voorwaarde dat mix-blend-mode: normal; wordt ondersteund.

Er wordt hier alleen getest op mix-blend-mode: normal;. Dat wil zeggen dat de browser déze eigenschap met déze specifieke waarde moet ondersteunen. In theorie zou de browser dus mix-blend-mode: normal; wel kunnen ondersteunen, maar mix-blend-mode: difference; niet.

In dit voorbeeld worden bij mix-blend-mode alleen de waarden 'normal', 'difference' en 'color-dodge' gebruikt. Elke browser die de waarde 'normal' ondersteunt, ondersteunt ook 'difference' en 'color-dodge'. Vandaar dat de test op alleen 'normal' hier voldoende is. Maar Safari bijvoorbeeld ondersteunt de waarden 'hue', 'saturation', 'color' en 'luminosity' bij mix-blend-mode niet. Als je één van die waarden zou willen gebruiken, moet je dus ook daarop testen, om voor Safari de css aan te kunnen passen.

Op de pagina met links zijn onder het kopje CSS → Browser supports link naar sites over browser support te vinden. In dit geval is daar gevonden dat alle browsers de genoemde drie waarden ondersteunen, en dat Safari de genoemde vier waarden niet ondersteunt. (Het is trouwens wel verstandig altijd nog even te controleren of die sites wel helemaal de juiste informatie geven. In het algemeen is de informatie op de sites die op de pagina met links worden genoemd uitstekend, maar er kan altijd 'n foutje in sluipen.)

Alleen browsers die mix-blend-mode: normal; ondersteunen voeren de css binnen deze feature query uit. Oudere browsers kennen @supports niet en voeren de css binnen deze feature query daarom niet uit. Dat kan een probleem zijn. Stel dat je op het ondersteunen van @supports (display: block) gaat testen. Elke browser ondersteunt dat, maar browsers die @supports niet ondersteunen, zullen de css voor display: block; toch niet uitvoeren.

Dit is natuurlijk een idioot voorbeeld, want je gaat niet testen op iets dat alle browsers al sinds het Stenen Tijdperk ondersteunen. Het illustreert alleen een potentieel probleem. In dit geval speelt dat niet, omdat elke browser die mix-blend-mode ondersteunt, ook @supports ondersteunt.

(Het omgekeerde is niet het geval: Internet Explorer en Edge bijvoorbeeld ondersteunen @supports wel, maar mix-blend-mode niet. Over niet al te lange tijd zal Edge het vermoedelijk ook gaan ondersteunen, want er is erg veel vraag naar.)

Hoe dan ook voeren alle browsers die mix-blend-mode niet ondersteunen, de css binnen deze feature query niet uit. Omdat de kleuren bij wel of niet blenden volkomen verschillend zijn, is dat uiterst belangrijk. Je kunt met blenden (of juist met niet-blenden) bijvoorbeeld tekst volledig laten verdwijnen, als je niet oppast. Meer hierover is te vinden bij Blenden kan dingen, ook tekst, volledig onzichtbaar maken!

#geen-mix

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.

#geen-mix {background: white; color: black; width: 500px; max-width: 90%; margin: 10px auto 0; border: red solid 10px; padding: 1%;}

Het element met id="geen-mix'. Binnen deze <div> staat een melding dat de browser mix-blend-mode niet ondersteunt.

display: none;

Verberg de melding.

Omdat de melding pas binnen de feature query @supports (mix-blend-mode: normal) wordt verborgen, wordt hij alleen verborgen in browsers die mix-blend-mode ondersteunen. Er is dus geen kans op een nadelige werking voor browsers die mix-blend-mode niet ondersteunen.

#een p:first-of-type span

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.

#een span {background: rgba(255, 255, 255, 0.4); color: black; width: 100%; font-size: 2em; text-align: center; position: absolute; top: 30px; left: 0;}

In div#een zit het bovenste voorbeeld: de twee foto's. Elke foto zit in een eigen <p>, er zijn dus twee <p>'s.

Kinderen van dezelfde ouder kunnen worden geteld, net zoals dat bij kinderen uit een gezin het geval is: eerste kind, tweede kind, derde kind, enzovoort. Je kunt ook alleen 'n bepaald soort element tellen, net zoals je alleen kinderen van ouder of jonger dan zes jaar kunt tellen. Met de selector :nth-of-type() worden alleen elementen van een bepaald soort geteld. Omdat het vaak voorkomt dat je het eerste element van 'n bepaald type wilt hebben, heeft dat een aparte selector: :first-of-type.

#een: het element met id="een".

p: alle <p>'s binnen #een.

:first-of-type: het element met een bepaald volgnummer. In dit geval wordt geen volgnummer gebruikt, maar een speciaal voor het eerste element bedoelde selector: :first-of-type. Omdat voor :first-of-type een p staat, worden alleen <p>'s geteld. Als div#een 327 <span>'s als direct kind heeft, tellen die niet mee. Hadden ze maar 'n <p>moeten zijn.

span: alle <span>'s binnen de geselecteerde <p>. In elke <p> zit maar één <span>: de <span> met het opschrift op de foto.

In normale mensentaal: de <span> met het opschrift van de foto in de eerste <p>, de <p> met de linkerfoto.

De selector :first-of-type kan onverwachte bijwerkingen hebben. In dit geval zit er maar één serie <p>'s in div#een. Maar als binnen div#een bijvoorbeeld nog 'n geneste <div> zou zitten, waarin ook <p>'s zouden zitten, zou deze selector ook voor de eerste <p> in die geneste <div> gelden. (Dit zou je in dit geval bijvoorbeeld kunnen oplossen door het toevoegen van >: #een > p:first-of-type span. Nu geldt de selector alleen voor <p>'s die een direct kind van div#een zijn.)

background: transparent;

De bij #een span opgegeven doorzichtig witte achtergrond weghalen.

Omdat de achtergrond pas binnen de feature query @supports (mix-blend-mode: normal) wordt weggehaald, wordt hij alleen weggehaald in browsers die mix-blend-mode ondersteunen. Er is dus geen kans op een nadelige werking voor browsers die mix-blend-mode niet ondersteunen.

color: #ffe4c4;

De bij #een span opgegeven voorgrondkleur in 'n soort lichtroze veranderen. Dit is ook de kleur van de tekst.

Omdat de kleur pas binnen de feature query @supports (mix-blend-mode: normal) wordt veranderd, wordt hij alleen veranderd in browsers die mix-blend-mode ondersteunen. Er is dus geen kans op een nadelige werking voor browsers die mix-blend-mode niet ondersteunen.

mix-blend-mode: difference;

Verander de tekstkleur in het verschil tussen de gelijk hierboven opgegeven voorgrondkleur en de erachter zittende foto. Omdat pixel voor pixel wordt bekeken, verschilt de tekst overal van de achtergrond. Over deze mode is meer te vinden bij difference.

Hieronder staat twee keer dezelfde foto met het zelfde opschrift. Html en css zijn precies hetzelfde, met één verschil: de voorgrondkleur, wat ook de kleur van de tekst is:

Afbeelding 16: door een verkeerd gekozen kleur kan tekst volledig onleesbaar worden

Bij de mode 'difference' wordt het verschil tussen de voorgrondkleur en de daarachter zittende foto gebruikt.

Links is een voorgrondkleur gebruikt, die een nauwelijks leesbare tekst oplevert. Rechts is de lichtroze voorgrondkleur gebruikt. Deze verschilt overal behoorlijk van de foto, dus er is overal een behoorlijk verschil tussen beide kleuren. De tekst is duidelijk te lezen.

Hieruit blijkt duidelijk, waarom het belangrijk is de juiste mode met de juiste kleuren te kiezen. Waarbij ook gelet moet worden op browsers die mix-blend-mode niet ondersteunen, om te voorkomen dat je 'n kleur kiest die in die browsers niet genoeg contrast heeft. Daarover is meer te lezen bij Blenden kan dingen, ook tekst, volledig onzichtbaar maken!

#twee p:first-of-type span

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.

#twee span {background: rgba(255, 255, 255, 0.6); color: black; padding: 0 10px;}

Afbeelding 17: eerste raster, tekst op achtergrond zonder blenden

In div#twee zit het middelste voorbeeld: de vier woorden 'Raster'. Elk 'Raster' zit in een eigen <p>, er zijn dus vier <p>'s.

Kinderen van dezelfde ouder kunnen worden geteld, net zoals dat bij kinderen uit een gezin het geval is: eerste kind, tweede kind, derde kind, enzovoort. Je kunt ook alleen 'n bepaald soort element tellen, net zoals je alleen kinderen van ouder of jonger dan zes jaar kunt tellen. Met de selector :nth-of-type() worden alleen elementen van een bepaald soort geteld. Omdat het vaak voorkomt dat je het eerste element van 'n bepaald type wilt hebben, heeft dat een aparte selector: :first-of-type. Voor alle latere elementen gebruik je 'n soortgelijke selector, maar dan met een volgnummer: :nth-of-type(). Tussen de haakjes komt het volgnummer. :nth-of-type(1) is precies hetzelfde als :first-of-type, maar de laatste is wat mensvriendelijker.

#twee: het element met id="twee".

p: alle <p>'s binnen #twee.

:first-of-type: het element met een bepaald volgnummer. In dit geval wordt geen volgnummer gebruikt, maar een speciaal voor het eerste element bedoelde selector: :first-of-type. Omdat voor :first-of-type een p staat, worden alleen <p>'s geteld. Als div#twee 327 <span>'s als direct kind heeft, tellen die niet mee. Hadden ze maar 'n <p>moeten zijn.

span: alle <span>'s binnen de geselecteerde <p>. In elke <p> zit maar één <span>: de <span> met het woord 'Raster'.

In normale mensentaal: de <span> met het woord 'Raster' in de eerste <p>, de <p> linksboven in het tweede voorbeeld.

De selector :first-of-type kan onverwachte bijwerkingen hebben. In dit geval zit er maar één serie <p>'s in div#twee. Maar als binnen div#twee bijvoorbeeld nog 'n geneste <div> zou zitten, waarin ook <p>'s zouden zitten, zou deze selector ook voor de <span>'s in de eerste <p> in die geneste <div> gelden. (Dit zou je in dit geval bijvoorbeeld kunnen oplossen door het toevoegen van >: #twee > p:first-of-type span. Nu geldt de selector alleen voor <p>'s die een direct kind van div#twee zijn.)

Omdat deze <span> niet wordt geblend, is de weergave van deze <span> in elke browser hetzelfde, of die nou mix-blend-mode ondersteunt of niet.

background: white;

De eerder bij #twee span opgegeven doorzichtig witte achtergrondkleur veranderen in massief wit.

Omdat de achtergrondkleur pas binnen de feature query @supports (mix-blend-mode: normal) wordt veranderd, wordt hij alleen veranderd in browsers die mix-blend-mode ondersteunen. Er is dus geen kans op een nadelige werking voor browsers die mix-blend-mode niet ondersteunen.

#twee p:nth-of-type(2) span

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.

#twee span {background: rgba(255, 255, 255, 0.6); color: black; padding: 0 10px;}

Afbeelding 18: tweede raster, tekst met schaduw en mode difference

Deze selector werkt precies hetzelfde als die bij #twee p:first-of-type span, alleen gaat het nu om de <span> met het woord 'Raster' uit de tweede <p> in div#twee, de 'Raster' rechtsboven.

background: transparent;

De eerder bij #twee span opgegeven doorzichtig witte achtergrondkleur verwijderen.

Omdat de achtergrondkleur pas binnen de feature query @supports (mix-blend-mode: normal) wordt verwijderd, wordt hij alleen verwijderd in browsers die mix-blend-mode ondersteunen. Er is dus geen kans op een nadelige werking voor browsers die mix-blend-mode niet ondersteunen.

Omdat deze <span> geen achtergrondkleur meer heeft, heeft het iets hieronder opgegeven mix-blend-mode: difference; geen invloed op de achtergrond. Alleen de tekst in de <span> wordt geblend, de doorzichtige achtergrond niet.

color: #ddd;

De eerder bij #twee span opgegeven voorgrondkleur veranderen. Dit is ook de kleur van de tekst.

Omdat de kleur pas binnen de feature query @supports (mix-blend-mode: normal) wordt veranderd, wordt hij alleen veranderd in browsers die mix-blend-mode ondersteunen. Er is dus geen kans op een nadelige werking voor browsers die mix-blend-mode niet ondersteunen.

text-shadow: 8px 8px grey;

Schaduw bij de letters van het woord 'Raster'.

De eerste waarde regelt de horizontale verplaatsing. Omdat het positief is, komt de schaduw 8 px rechts van de tekst te staan. Bij een negatieve waarde zou de schaduw links van de tekst komen te staan.

De tweede waarde regelt de verticale verplaatsing. Omdat het positief is, komt de schaduw 8 px onder de tekst te staan. Bij een negatieve waarde zou de schaduw boven de tekst komen te staan.

Je kunt nog een derde waarde opgeven: de lengte waarover de schaduw vervaagt. Als je hier niets invult, zoals hier het geval is, vervaagt de schaduw niet.

Als laatste wordt een kleur ingevuld. Als je geen kleur invult, wordt de voorgrondkleur (dezelfde kleur als de tekst) gebruikt.

Ook de schaduw wordt door het hieronder staande mix-blend-mode: difference; geblend met de achtergrond met het raster.

mix-blend-mode: difference;

Verander de voorgrondkleur (de tekst en de schaduw) in het verschil tussen de onder de <span> zittende kleur van de achtergrond-afbeelding met het raster en de iets hierboven opgegeven voorgrond- en schaduwkleur. Omdat pixel voor pixel wordt bekeken, is de achtergrond-afbeelding door de tekst en de schaduw heen te zien, terwijl de tekst toch goed leesbaar blijft. Over deze mode is meer te vinden bij difference.

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

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.

#twee span {background: rgba(255, 255, 255, 0.6); color: black; padding: 0 10px;}

Afbeelding 19: derde raster, tekst op achtergrond met mode color-dodge

Deze selector werkt precies hetzelfde als die bij #twee p:first-of-type span, alleen gaat het nu om de <span> met het woord 'Raster' uit de derde <p> in div#twee, de 'Raster' linksonder.

background: transparent;

De eerder bij #twee span opgegeven doorzichtig witte achtergrondkleur verwijderen.

Omdat de achtergrondkleur pas binnen de feature query @supports (mix-blend-mode: normal) wordt verwijderd, wordt hij alleen verwijderd in browsers die mix-blend-mode ondersteunen. Er is dus geen kans op een nadelige werking voor browsers die mix-blend-mode niet ondersteunen.

Omdat deze <span> geen achtergrondkleur meer heeft, heeft het iets hieronder opgegeven mix-blend-mode: color-dodge; geen invloed op de achtergrond. Alleen de tekst in de <span> wordt geblend, de doorzichtige achtergrond niet.

color: red;

De eerder bij #twee span opgegeven voorgrondkleur veranderen. Dit is ook de kleur van de tekst.

Omdat de kleur pas binnen de feature query @supports (mix-blend-mode: normal) wordt veranderd, wordt hij alleen veranderd in browsers die mix-blend-mode ondersteunen. Er is dus geen kans op een nadelige werking voor browsers die mix-blend-mode niet ondersteunen.

mix-blend-mode: color-dodge;

Blend de voorgrondkleur (de tekst) met de onder de <span> zittende kleur van de achtergrond-afbeelding met het raster met de mode 'color-dodge'. Omdat pixel voor pixel wordt bekeken, is de achtergrond-afbeelding door de tekst heen te zien, terwijl de tekst toch goed leesbaar blijft. Over deze mode is meer te vinden bij color-dodge.

#twee p:nth-of-type(4) span

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.

#twee span {background: rgba(255, 255, 255, 0.6); color: black; padding: 0 10px;}

Afbeelding 20: vierde raster, tekst op achtergrond met mode difference

Deze selector werkt precies hetzelfde als die bij #twee p:first-of-type span, alleen gaat het nu om de <span> met het woord 'Raster' uit de vierde <p> in div#twee, de 'Raster' rechtsonder.

background: white;

De eerder bij #twee span opgegeven doorzichtig witte achtergrondkleur veranderen in massief wit.

Omdat de achtergrondkleur pas binnen de feature query @supports (mix-blend-mode: normal) wordt veranderd, wordt hij alleen veranderd in browsers die mix-blend-mode ondersteunen. Er is dus geen kans op een nadelige werking voor browsers die mix-blend-mode niet ondersteunen.

padding: 50px;

Aan alle kanten een padding van 50 px. Omdat de hier gelijk boven opgegeven achtergrondkleur doorloopt onder de padding, staat de achtergrond ook 50 px rechts en links van de tekst. (Geen witte achtergrond, want de achtergrondkleur van de <span> wordt geblend met de eronder zitten achtergrond-afbeelding met het raster.)

Afbeelding 21: zonder overflow: hidden wordt de achtergrond te hoog

Boven en onder is geen padding te zien. De <span>'s zitten in een <p>, die geen hoogte of regelhoogte heeft gekregen. Daarom wordt de <p> niet hoger dan nodig is om de erin zittende tekst weer te geven. En omdat bij #twee p bij de <p> overflow: hidden; is opgegeven, valt de padding boven en onder weg. Als je overflow: hidden; weg zou halen bij de <p>, zou de padding boven en onder ook aanwezig zijn, zoals op de afbeelding is te zien.

mix-blend-mode: difference;

Verander de voorgrondkleur, dat is ook de kleur van de tekst, in het verschil tussen de voorgrondkleur en de achtergrondkleur van de <span>. Verander het resultaat daarvan vervolgens in het verschil met de achter de <span> zittende achtergrond-afbeelding met het raster.

Omdat pixel voor pixel wordt bekeken, is de achtergrond-afbeelding door de tekst heen te zien, terwijl de tekst toch goed leesbaar blijft. Over deze mode is meer te vinden bij difference.)

#drie span

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.

#drie span {opacity: 0.7; position: absolute;}

#drie span:first-of-type {color: red; top: -0.03em; left: 0.06em;}

#drie span;nth-of-type(2) {color: orange; top: -0.28em; left: 0.278em;}

#drie span:nth-of-type(3) {color: indigo; top: -0.27em; left: 0.58em;}

#drie span:nth-of-type(4) {color: green; top: -0.02em; left: 0.78em;}

#drie span:nth-of-type(5) {color: blue; top: 0.32em; left: 0.71em;}

#drie span:nth-of-type(6) {color: yellow; top: 0.45em; left: 0.4em;}

#drie span:nth-of-type(7) {color: violet; top: 0.3em; left: 0.12em;}

#drie span:last-of-type {background: white; color: black; width: 100%; font-size: 0.15em; font-weight: normal; text-align: center; mix-blend-mode: normal; bottom: 0;}

Alle <span>'s in het element met id="drie". In div#drie zitten vier <p>'s, één voor elk groepje cirkels. Binnen elke <p> zitten zeven <span>'s met een cirkel (eigenlijk 'n grote letter 'o'), en als laatste één <span> met het woord 'mix-blend-mode' of 'opacity'.

opacity: 1;

De eerder bij #drie span opgegeven gedeeltelijke doorzichtigheid wordt hier ongedaan gemaakt.

Deze doorzichtigheid was opgegeven om kleur iets te veranderen op de plaatsen, waar de cirkels elkaar overlapten. Dat wordt hier overgenomen door de hierboven opgegeven mix-blend-mode: difference;.

mix-blend-mode: difference;

Verander de voorgrondkleur, dat is ook de kleur van de cirkels, in het verschil tussen de eerder bij #een, #drie opgegeven witte achtergrondkleur onder de <span>, en de eerder voor elke <span> opgegeven voorgrondkleur. Elke <span> heeft een eigen voorgrondkleur. Waar de cirkel elkaar overlappen, blenden de cirkels ook met elkaar.

Over deze mode is meer te vinden bij difference.

#drie p:nth-of-type(2) span, #drie p:nth-of-type(4) span

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.

#drie span {opacity: 0.7; position: absolute;}

#drie span:first-of-type {color: red; top: -0.03em; left: 0.06em;}

#drie span;nth-of-type(2) {color: orange; top: -0.28em; left: 0.278em;}

#drie span:nth-of-type(3) {color: indigo; top: -0.27em; left: 0.58em;}

#drie span:nth-of-type(4) {color: green; top: -0.02em; left: 0.78em;}

#drie span:nth-of-type(5) {color: blue; top: 0.32em; left: 0.71em;}

#drie span:nth-of-type(6) {color: yellow; top: 0.45em; left: 0.4em;}

#drie span:nth-of-type(7) {color: violet; top: 0.3em; left: 0.12em;}

#drie span:last-of-type {background: white; color: black; width: 100%; font-size: 0.15em; font-weight: normal; text-align: center; mix-blend-mode: normal; bottom: 0;}

#drie span {opacity: 1; mix-blend-mode: difference;}

Deze selectors werken precies hetzelfde als die bij #twee p:first-of-type span, alleen gaat het nu om de <span>'s in de tweede en vierde <p> in div#drie. In deze <span>'s zitten de tweede en vierde groep cirkels, die niet geblend worden.

opacity: 0.7;

Bij #drie span iets hierboven is, voor browsers die mix-blend-mode ondersteunen, de nog eerder bij #drie span voor alle browsers opgegeven opacity: 0.7; veranderd naar opacity: 1;. Voor de <span>'s met de cirkels in de tweede en vierde <p> wordt dat weer veranderd naar opacity: 0.7;. Omdat deze <span>'s ook niet worden geblend, zien de tweede en vierde groep cirkels er precies hetzelfde uit als in browsers die mix-blend-mode niet ondersteunen.

Hierdoor is het verschil tussen opacity en mix-blend-mode te zien.

mix-blend-mode: normal;

Bij #drie span iets hierboven is mix-blend-mode: difference; opgegeven. Hier wordt dat voor de <span>'s binnen de tweede en vierde <p> weer terugveranderd naar de standaardwaarde 'normal': niet blenden.

#drie p:nth-of-type(3), #drie p:nth-of-type(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.

#drie p:not(:last-child) {box-sizing: border-box; display: inline-block; min-width: 1.5em; height: 1.6em; font-size: 7em; font-weight: bold; margin: 10px auto 0; border: black solid 2px; position: relative;}

In div#drie zit het onderste voorbeeld met de groepen cirkels. Deze <div> heeft een aantal kinderen, kleinkinderen, enzovoort, waaronder een aantal <p>'s. Om precies te zijn: vijf <p>'s. Vier met in elk een groep cirkels met daaronder een woord, en één met het onderschrift onder die vier groepen.

De derde en vierde <p>, dat zijn de twee rechter <p>'s, moeten een rode achtergrond krijgen.

Kinderen van dezelfde ouder kunnen worden geteld, net zoals dat bij kinderen uit een gezin het geval is: eerste kind, tweede kind, derde kind, enzovoort. Je kunt ook alleen 'n bepaald soort element tellen, net zoals je alleen kinderen van ouder of jonger dan zes jaar kunt tellen. Met de selector :nth-of-type() worden alleen elementen van een bepaald soort geteld.

De eerste selector, die voor de komma:

#drie: het element met id="drie".

p: alle <p>'s binnen #drie.

:nth-of-type(): het element met een bepaald volgnummer. Het volgnummer staat tussen haakjes, dat komt gelijk hieronder aan de beurt. Omdat voor :nth-of-type() een p staat, worden alleen <p>'s geteld. Als div#drie 327 <span>'s als direct kind heeft, tellen die niet mee. Hadden ze maar 'n <p>moeten zijn.

:nth-of-type(3): de derde <p>.

De selector achter de komma is precies hetzelfde, maar dan voor de vierde <p> in div#drie.

In normale mensentaal: de derde en vierde <p> binnen div#drie, de twee rechter <p>'s.

De selector :nth-of-type() kan onverwachte bijwerkingen hebben. In dit geval zitten er maar vijf <p>'s in div#drie, die allemaal een direct kind van div#drie zijn. Maar als binnen div#drie bijvoorbeeld nog 'n geneste <div> zou zitten, waarin ook drie of meer <p>'s zouden zitten, zouden ook de derde en vierde <p> uit die <div> onder deze selector vallen. (Dit zou je in dit geval bijvoorbeeld kunnen oplossen door het toevoegen van >: #drie > p:nth-of-type(3), #drie > p:nth-of-type(4). Nu geldt de selector alleen voor <p>'s die een direct kind van div#drie zijn.)

Als er later aan de html een <p> wordt toegevoegd, kan de nummering van de <p>'s plotsklaps veranderen.

Kortom: een handige selector, mits voorzichtig gebruikt.

background: red; Afbeelding 22: effect van rode achtergrond op blenden

Rode achtergrond.

Deze rode achtergrond wordt alleen maar aangebracht om de invloed van de achtergrondkleur bij blenden te laten zien. Html en css zijn de bij de eerste en derde <p> precies hetzelfde, het enige verschil is de rode achtergrond van de <p>. Maar het effect van die

rode achtergrond is wel, dat de kleuren van de cirkels in de derde <p> volkomen verschillen van die in de eerste <p>, zoals op de afbeelding is te zien.

(Bij de tweede en vierde <p> is dat verschil er niet, want de cirkels daarin worden niet geblend, maar zijn alleen wat doorzichtig.)

Afbeelding 23: rode cirkel weggevallen tegen rode achtergrond

Op de afbeelding hiernaast zijn de twee linkergroepjes met cirkels te zien. Op de afbeelding links met mix-blend-mode, op de afbeelding rechts met opacity. In deze afbeelding is een fout geslopen: bij de afbeelding rechts, die met opacity, valt de rode cirkel linksboven volledig weg tegen de rode achtergrond. Terwijl deze zelfde cirkel op de afbeelding rechts, die met mix-blend-mode, nog is te zien.

Dit was niet de bedoeling, maar het is zo gelaten, omdat het een aardige illustratie is van hoe makkelijk iets kan wegvallen in browsers die mix-blend-mode niet ondersteunen, terwijl het wel zichtbaar is in browsers die dat wel ondersteunen.

css voor vensters maximaal 400 px breed

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

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

(Dat geldt niet voor de css die binnen de feature query @supports (mix-blend-mode: normal) staat, die wordt alleen uitgevoerd door browsers die mix-blend-mode ondersteunen. Maar dat heeft niets te maken met de grootte van het browservenster, waar deze media query voor is bedoeld.)

De css die binnen deze media query staat, geldt alleen voor browservensters die maximaal 400 px breed zijn. In deze smallere vensters worden worden de foto's uit het bovenste voorbeeld iets verkleind, omdat ze anders niet volledig binnen het venster passen.

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

(max-width: 400px): het browservenster mag maximaal r00 px breed zijn. Is het venster breder, 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 (max-width: 400px) { 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 }.

Als je nou 'n mobieltje hebt met een resolutie van – ik roep maar wat – 1024 x 768 px, dan geldt deze media query mogelijk toch voor dat mobieltje. Terwijl dat toch echt meer dan 400 px breed is. Een vuig complot van gewetenloze multinationals? Voordat je je gaat beklagen bij Radar, zou ik eerst even verder lezen.

Steeds meer mobiele apparaten, maar ook steeds meer gewone beeldschermen, hebben een hogere resolutiedichtheid. Dat wil zeggen dat ze kleinere pixels hebben, die dichter bij elkaar staan. Daardoor zijn foto's, tekst, en dergelijke veel scherper weer te geven. Hoe kleiner de puntjes (de pixels) zijn, waaruit een afbeelding is opgebouwd, hoe duidelijker het wordt.

Er ontstaat alleen één probleem: als je de pixels twee keer zo klein maakt, wordt ook wat je ziet twee keer zo klein. En inmiddels zijn er al apparaten met pixels die meer dan vier keer zo klein zijn. Een lijntje van 1 px breed zou op die apparaten minder dan 'n kwart van de oorspronkelijke breedte krijgen en vrijwel onzichtbaar zijn. Een normale foto zou in een thumbnail veranderen. Kolommen zouden heel smal worden. Tekst zou onleesbaar klein worden. Allemaal fantastisch scherp, maar je hebt 'n vergrootglas nodig om 't te kunnen zien.

Om dit te voorkomen wordt een verschil gemaakt tussen css-pixels en schermpixels (in het Engels 'device-pixels'). De css-pixels zijn gebaseerd op de – tot voor kort – normale beeldschermen van de desktop. 1 css-pixel is op zo'n beeldscherm 1 pixel. Het aantal schermpixels is het werkelijk op het apparaat aanwezige aantal pixels (dat is het aantal pixels, waarvoor je hebt betaald).

Dat eerder genoemde mobieltje van 1024 x 768 px heeft wel degelijk meer dan 400 px in de breedte. Maar die zitten dichter bij elkaar. Op een gewoon beeldscherm zitten 96 pixels per inch, wat wordt uitgedrukt met de eenheid dpi ('dots per inch'). Als dat mobieltje een resolutie van 192 dpi heeft, 192 pixels per inch, zijn de pixels ervan twee keer zo klein als op een origineel beeldscherm. Er zijn per inch twee keer zoveel schermpixels aanwezig.

Om nu te voorkomen dat alles op dat mobieltje twee keer zo klein wordt, geeft het mobieltje niet het echte aantal schermpixels (1024 x 768), maar een lager aantal css-pixels door bij een media query. De 192 dpi van het mobieltje is twee keer zo veel als de 96 dpi van een normaal beeldscherm. Het aantal css-pixels is dan het aantal schermpixels gedeeld door 2. 1024 x 768 gedeeld door 2 is 512 x 384 px. Het aantal css-pixels is 512 x 384 px en zit daarmee, in portretstand, dus ruim onder de 400 px van deze media query. In landschapsstand is de breedte 512 px, en dan wordt de css in deze media query inderdaad niet uitgevoerd.

Door deze truc is een lijn van 1 px breed op een normaal beeldscherm ook op het mobieltje nog steeds 1 px breed, alleen wordt die ene (css-)pixel opgebouwd uit twee schermpixels (feitelijk vier, want het verhaal geldt voor breedte én hoogte). De dikte van het lijntje is hetzelfde, maar het is veel fijner opgebouwd. Bij lijntjes is dat verschil bijvoorbeeld in bochten goed te zien.

Hetzelfde verhaal geldt voor hogere resoluties, Een tablet met een breedte van 4096 schermpixels en een dpi van 384 (vier keer de originele dichtheid) geeft 4096 gedeeld door 4 = 1024 css-pixel door. Het lijntje van 1 px breedte op de originele monitor is nog steeds 1 css-pixel breed op de tablet, maar die ene css-pixel is nu opgebouwd uit zestien schermpixel.

(Overigens kun je met behulp van media query's ook testen op de resolutie met gebruik van het sleutelwoord 'resolution'. Apple gebruikt het niet-standaard 'device-pixel-ratio', maar het idee is hetzelfde. Dit kan bijvoorbeeld handig zijn om te bepalen, hoe groot een foto moet zijn.)

Kort samengevat: omdat niet het aantal schermpixels (waarvoor je hebt betaald), maar het aantal css-pixels (de door de ontwerper bedoelde afmeting) wordt doorgegeven, wordt voorkomen dat een hogeresolutiescherm onleesbaar klein wordt.

img

Alle afbeeldingen. Dat zijn er maar twee: de foto's bovenin.

max-width: 100%;

In de html is als breedte bij de foto's 350 px opgegeven, omdat dat de echte breedte van de foto's is. Als je in de css ook een breedte opgeeft, zoals hier gebeurt, overrulet de breedte in de css de in de html opgegeven breedte.

In smallere browservensters staan de twee foto's niet naast, maar onder elkaar. Maar ook dan zijn de foto's nog te breed in vensters smaller dan 400 px (er zijn ook nog wat marges en dergelijke, vandaar de 50 px speling). Als de breedte niet wordt aangepast, moet horizontaal worden gescrold om de hele foto te kunnen zien.

Daarom wordt de breedte beperkt tot maximaal 100%. Een breedte in procenten is normaal genomen ten opzichte van de ouder van het element. Dat is hier één van de <p>'s in div#een. Een <p> is een blok-element en wordt daarom normaal genomen automatisch even breed als z'n ouder, hier div#een.

Bij #een, #drie heeft div#een een maximumbreedte van 95% gekregen. Dat is ook weer ten opzichte van z'n ouder <body>, ook een blok-element. Ook <body> wordt daarom normaal genomen 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. div#een wordt hierdoor nooit breder dan 95% van de breedte van het venster, ongeacht hoe breed dit is.

De in div#een zittende <p>'s worden nooit breder dan div#een: maximaal 95% van de breedte van het browservenster. En omdat de in de <p> zittende <img> maximaal even breed is als de <p>, wordt ook de foto nu nooit breder dan 95% van de breedte van het browservenster, waardoor horizontaal scrollen in smalle vensters wordt voorkomen.

Je zou de breedte (en hoogte) ook helemaal weg kunnen laten in de html, maar het is nog steeds 'n goede gewoonte die wel aan te geven, als dat kan. De benodigde ruimte voor <img>'s kan dan al worden gereserveerd, voordat de <img>'s zijn gedownload.

(Overigens is het verkleinen van een <img> op deze manier in het algemeen een bijzonder slecht idee. Er wordt een groter bestand gedownload, dan nodig is, en vervolgens gaat de browser dat te grote bestand verkleind weergeven. Maar in dit geval wordt zo weinig verkleind dat een veel ingewikkelder constructie met foto's van verschillende afmetingen een beetje onzin zou zijn.)

height: auto;

In de html is ook een hoogte opgegeven bij de foto's. Als de breedte van de foto wordt aangepast, maar de hoogte zou hetzelfde blijven, vervormt de foto. Je krijgt 'n lachspiegel-effect. Door de hoogte op 'auto' in te stellen, verandert de hoogte automatisch met hetzelfde percentage als de breedte. Hierdoor blijven de verhoudingen van de foto bewaard.

#een p

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

#een p {display: inline-block; margin: 5px; position: relative;}

#een p:last-child, #twee p:last-child, #drie p:last-child {background: white; color: black; width: 100%; font-size: 1em; font-weight: normal; text-align: left; margin: 0; border-width: 1px; border-top: black solid 1px; padding: 5px;}

Alle <p>'s in het element met id="een". Dat zijn er hier drie. In de eerste twee staan de twee foto's met opschrift, in de derde staat het onderschrift onder de foto's.

width: 350px; max-width: 95%;

Deze regels zouden niet nodig moeten zijn, maar hebben te maken met een probleem in Internet Explorer en Edge.

In de eerste twee <p>'s zit een foto met een breedte van 350 px. In smallere browservensters wordt de breedte van de foto's iets hierboven bij img met max-width: 100%; beperkt tot maximaal de breedte van de <p>'s. Omdat de <p>'s nooit breder worden dan het venster, wordt daarmee horizontaal scrollen in smalle vensters voorkomen.

In Internet Explorer en Edge blijft de foto in browservensters smaller dan 400 px echter 350 px breed, waardoor horizontaal gescrold moet worden om de volledige foto te zien. De iets hierboven bij img opgegeven css om de breedte van de foto te beperken, wordt volledig genegeerd. Als echter een breedte aan de <p>'s wordt gegeven, werkt het opeens wel. Voor andere browsers is die breedte geen probleem.

Waarmee het opgelost leek.

Helaas blijken browsers die flexbox niet kennen nu de <p>'s altijd op een breedte van 350 px weer te geven. Wat trouwens, anders dan bij Internet Explorer en Edge, correct is (althans: als je als browser flexbox niet kent). Nu moet in deze browsers horizontaal worden gescrold, als het browservenster heel smal is. Een maximumbreedte van 95% lost dat op.

Een breedte in procenten is normaal genomen ten opzichte van de ouder van het element, hier div#een. Bij #een, #drie heeft div#een een maximumbreedte van 95% gekregen. Dat is ook weer ten opzichte van z'n ouder <body>, ook een blok-element. Ook <body> wordt daarom normaal genomen 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. div#een wordt hierdoor nooit breder dan 95% van de breedte van het venster, ongeacht hoe breed dit is.

Als de breedte van deze <p>'s beperkt wordt tot 95% daarvan, kunnen ze dus nooit breder worden dan het venster van de browser. En de erin zittende foto's ook niet.

Waarna alle browsers nog lang en gelukkig leefden.

css voor vensters minimaal 760 px breed

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

De opbouw van deze regel staat beschreven bij @media screen and (max-width: 400px). Er is één verschil: het browservenster moet hier minimaal 760 px (min-width: 760px) breed zijn. De voornaamste aanpassingen zijn hier het beperken van de breedte van de pagina en het in twee kolommen weergeven van de onderschriften onder de voorbeelden.

body

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

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

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

max-width: 1280px;

Maximumbreedte. Als de breedte niet beperkt zou worden, zouden in brede browservensters de voorbeelden wel erg ver uit elkaar komen te staan. Bovendien zou de tekst lastig leesbaar worden, omdat de regels te lang worden. Om dat te voorkomen, wordt de maximumbreedte beperkt.

Deze css is bedoeld voor browservensters met een minimumbreedte van 760 px. Iets hieronder staat nog css voor vensters minimaal 1000 px breed. Deze maximumbreedte zou dus ook daar kunnen, want pas daar heeft de beperking van de breedte nut. Maar omdat hier toch al css staat voor <body>, is het hier neergezet. Dan hoeft er bij de css voor browservensters minimaal 1000 px breed helemaal geen regel voor <body> te komen.

font-size: 110%;

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

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

margin: 0 auto;

Omdat voor onder en links geen waarden zijn ingevuld, krijgen die automatisch dezelfde waarde als boven en rechts. Hier staat dus eigenlijk 0 auto 0 auto in de volgorde boven – rechts – onder – links. Boven en onder geen marge, links en rechts auto, wat hier hetzelfde betekent als evenveel. <body> staat hierdoor altijd horizontaal gecentreerd binnen z'n ouder <html>.

Omdat <html> het buitenste element is, wordt dit normaal genomen even breed als het venster van de browser. <body>, en daarmee de hele pagina, staat hierdoor altijd horizontaal gecentreerd binnen het venster, ongeacht de breedte van het venster.

#een p:last-child, #twee p:last-child, #drie p:last-child

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

#een p {display: inline-block; margin: 5px; position: relative;}

#een p:last-child, #twee p:last-child, #drie p:last-child {background: white; color: black; width: 100%; height: auto; float: none; font-size: 1em; font-weight: normal; text-align: left; border-top: black solid 1px; padding: 10px;}

#twee p {box-sizing: border-box; width: 50%; overflow: hidden; float: left; font-size: 5em; font-weight: bold; text-align: center; margin: 0 0 5px; border: black solid 2px;}

Deze selector selecteert de laatste <p> in div#een, div#twee en div#drie. Dit zijn de <p>'s met de onderschriften onder de voorbeelden. Hoe deze selector precies werkt, is te vinden bij #een p:last-child, #twee p:last-child, #drie p:last-child.

-webkit-column-count: 2; column-count: 2;

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

In browservensters breder dan 760 px wordt de lengte van de regels in de onderschriften zo lang, dat deze lastig is te lezen. Daarom wordt de tekst weergegeven in twee kolommen.

Als de kolommen te hoog worden, moet vanaf de onderkant van 'n kolom terug naar boven worden gescrold om de volgende kolom te kunnen lezen. Dat is ongelooflijk onhandig. Daarom is deze eigenschap op dit moment alleen bruikbaar voor hele korte teksten. Er wordt wel aan gewerkt om dat op te lossen met een nieuw soort overflow, maar het zal nog wel even duren, voordat dat klaar is.

-webkit-column-rule: black solid 1px; column-rule: black solid 1px;

Hier staat in feite twee keer hetzelfde: column-rule: black solid 1px;. Waarom dat zo is, staat bij De voorvoegsels -moz-, -ms- en -webkit-.

Tussen de kolommen een verticaal zwart lijntje van 1 px breed. Omdat de <p>'s met de onderschriften bij #een p:last-child, #twee p:last-child, #drie p:last-child een padding van 5 px hebben gekregen, loopt het lijntje tussen de kolommen net niet tot helemaal onder- en bovenaan door.

css voor vensters minimaal 1000 px breed

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

De opbouw van deze regel staat beschreven bij @media screen and (max-width: 400px). Er is één verschil: het browservenster moet hier minimaal 1000 px (min-width: 1000px) breed zijn. In deze vensters worden de onderschriften onder de voorbeelden in drie kolommen weergegeven.

een p:last-child, #twee p:last-child, #drie p:last-child

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

#een p {display: inline-block; margin: 5px; position: relative;}

#een p:last-child, #twee p:last-child, #drie p:last-child {background: white; color: black; width: 100%; height: auto; float: none; font-size: 1em; font-weight: normal; text-align: left; border-top: black solid 1px; padding: 10px;}

#twee p {box-sizing: border-box; width: 50%; overflow: hidden; float: left; font-size: 5em; font-weight: bold; text-align: center; margin: 0 0 5px; border: black solid 2px;}

#een p:last-child, #twee p:last-child, #drie p:last-child {-webkit-column-count: 2; column-count: 2; -webkit-column-rule: black solid 1px; column-rule: black solid 1px;}

Deze selector selecteert de laatste <p> in div#een, div#twee en div#drie. Dit zijn de <p>'s met de onderschriften onder de voorbeelden. Hoe deze selector precies werkt, is te vinden bij #een p:last-child, #twee p:last-child, #drie p:last-child.

-webkit-column-count: 3; column-count: 3;

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

In browservensters breder dan 1000 px wordt de lengte van de regels in de onderschriften zo lang, dat deze lastig is te lezen. Daarom wordt de tekst weergegeven in drie kolommen.

Als de kolommen te hoog worden, moet vanaf de onderkant van 'n kolom terug naar boven worden gescrold om de volgende kolom te kunnen lezen. Dat is ongelooflijk onhandig. Daarom is deze eigenschap op dit moment alleen bruikbaar voor hele korte teksten. Er wordt wel aan gewerkt om dat op te lossen met een nieuw soort overflow, maar het zal nog wel even duren voordat dat klaar is.