Skip links en inhoudsopgave

Als scrollbalk ontbreekt, vervaagt bij overflow tekst onderaan langzaam - uitleg

Laatst aangepast: .

Bij overflow geeft scrollbalk of vervaging aan dat er meer tekst is.

Korte omschrijving

Als tekst te hoog is voor een element en er is geen scrollbalk, vervaagt de tekst onderaan, als indicatie dat er meer tekst is.

BELANGRIJK

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

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

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

Als je deze handleiding graag uitprint (zonde van het bos), gebruik dan de pdf in de download. Deze pagina is niet geoptimaliseerd voor printen, de pdf kan wel makkelijk worden geprint.

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

Opmerkingen

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

Dit voorbeeld is gemaakt op een systeem met Linux (Kubuntu). Daarbij is vooral gebruik gemaakt van Visual Studio Code, GIMP en Firefox met extensies. De pdf-bestanden zijn gemaakt met LibreOffice.

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

Achterliggend idee

Als de tekst niet in een blok-element past, zal op de desktop een verticale scrollbalk verschijnen. Daardoor is het duidelijk dat er meer tekst is, dan zichtbaar is.

Op een smartphone of tablet gebeurt dit niet: er is geen verticale scrollbalk. Soms verschijnt bij scrollen een heel smalle scrollbalk, maar dat moet je dus al weten dat er gescrold moet worden om alle tekst te zien.

Om ook op een smartphone of tablet duidelijk te maken dat de tekst nog verder doorloopt, dan wat je ziet, lost de tekst aan de onderkant als het ware op in de ondergrond: hij wordt steeds vager.

Dit wordt veroorzaakt door een gedeeltelijk doorzichtige gradiënt aan de onderkant over de tekst heen te zetten.

Om vast te stellen of het om een touchscreen gaat, wordt met behulp van een media query gekeken of gehoverd kan worden en wat de gebruikelijke invoermethode is: grof (vinger) of iets anders fijn (muis en dergelijke).

Omdat het element met de gradiënt over de tekst komt te staan, kan de tekst onder de gradiënt niet worden geselecteerd, gekopieerd, en dergelijke. Door het gebruik van pointer-events: none; bij de elementen met de gradiënt kan dit toch.

De voorvoegsels -moz- 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 Edge, 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 en Edge gebruiken Blink.)

In oudere code kun je ook nog de voorvoegsels -o- (Opera) en -ms- (Microsoft Internet Explorer) tegenkomen.

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 Safari herkent -webkit-appearance. Zodra Safari appearance gaat herkennen, zal dit -webkit-appearance overrulen, omdat het er later in staat. Dat ze er beide in staan, is dus geen enkel probleem.

In dit voorbeeld wordt -webkit-overflow-scrolling gebruikt.

-webkit-overflow-scrolling

Deze eigenschap wordt alleen maar gebruikt om een probleem op iOS ouder dan versie 13 op te lossen. Alleen browsers op iOS ondersteunen deze eigenschap. Alle andere browsers en systemen negeren hem. Dat geldt ook voor browsers op iPadOS. Daarom hoeft alleen maar op browsers gelet te worden die op iOS draaien. In dit geval is daarom het volgende voldoende:

{-webkit-overflow-scrolling: ...;}

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

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

Inmiddels is de algemene mening dat 'vendor prefixes', zoals deze voorvoegsels in het Engels heten, geen groot succes zijn. Eén van de grootste problemen: veel sitemakers gebruiken alleen de -webkit-variant. Daar kwamen ze in het verleden nog mee weg, omdat Apple op mobiel zo'n beetje 'n monopolie had, en omdat ook Google Chrome in het verleden met -webkit- werkte. 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 niet meer gebruikt. Nieuwe, experimentele css-eigenschappen zitten inmiddels 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- gebruikt, ben je in feite 'n onbetaalde reclamemaker voor Apple. (Dit geldt dus niet voor het hierboven genoemde -webkit-overflow-scrolling, want dat wordt alleen gebruikt om een probleem op iOS op te lossen.)

Tabindex en Tab-toets

Links, invoervelden in formulieren, en dergelijke kunnen met behulp van de Tab-toets (of een soortgelijke toets) één voor één worden bezocht, in de volgorde waarin ze in de html voorkomen. Shift+Tab-toets keert de volgorde van de Tab-toets om. Dit is een belangrijk hulpmiddel voor mensen die om een of andere reden de muis niet kunnen of willen gebruiken. (En het is vaak ook veel sneller dan de muis, vooral in formulieren.)

In sommige browsers en/of besturingssystemen is dit vreemd genoeg standaard uitgeschakeld en is een zoektocht in de instellingen nodig om dit aan te zetten. Maar gebruikers van de Tab-toets zullen dit al hebben gedaan.

Als je met behulp van de Tab-toets een element hebt bereikt, heeft dit focus: als het een link is en je drukt op Enter, wordt de link gevolgd. Bij een tekstveld kun je tekst gaan invoeren. Enzovoort.

De Tab-toets volgt normaal genomen de volgorde van de elementen in de html. Het maakt niet uit, in welke volgorde ze op het scherm staan. Als je met behulp van css de elementen van plaats verwisselt op het scherm, wordt toch gewoon de volgorde in de html gevolgd.

De volgorde van de Tab-toets kan worden veranderd met behulp van het tabindex-attribuut: <div tabindex="3">. Deze <div> zal nu als derde worden bezocht, ook al krijgt een simpele <div> normaal genomen nooit bezoek van de Tab-toets.

Normaal genomen is het gebruik van een tabindex niet nodig. Het is zeker niet bedoeld om de bezoeker als een kangoeroe op een hindernisbaan van onder via links over rechts naar boven te laten springen. Maar soms kan het handig zijn voor kleinere correcties, als de normale volgorde in de html niet optimaal is. Of om een element bereikbaar te maken voor de Tab-toets, zoals de hierboven genoemde <div>.

Schermlezers blijven altijd de volgorde van de html volgen, dus als de tabindex sterk afwijkt van de volgorde in de html, kan dat behoorlijk verwarrend zijn.

De tabindex kan drie verschillende waarden hebben: -1, 0 of een positief getal.

In principe is de volgorde bij gebruik van de Tab-toets als volgt: eerst worden alle positieve getallen in volgorde afgewerkt. Als twee tabindexen dezelfde waarde hebben, wordt de volgorde in de html aangehouden. Een waarde van '0' wordt, afhankelijk van browser en besturingssysteem, verschillend behandeld, waarover iets hieronder bij Tabindex="0" meer.

tabindex="-1"

Een negatieve waarde van -1 zorgt ervoor dat een element, dat normaal genomen door het gebruik van de Tab-toets de focus kan krijgen, volledig wordt genegeerd door de Tab-toets. Zelfs een link met een negatieve tabindex wordt volledig genegeerd.

Ook kan aan een element met een negatieve tabindex dat normaal genomen geen focus kan krijgen, toch de focus worden gegeven met behulp van JavaScript, een klik of een aanraking. Waarbij gebruikers van de Tab-toets daar geen last van hebben, omdat tabindex="-1" wordt genegeerd door de Tab-toets.

In dit voorbeeld wordt tabindex="-1" niet gebruikt.

tabindex="0"

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

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

(In de praktijk blijkt trouwens dat alle browsers de volgorde van de html aanhouden bij tabindex="0", nadat eerst alle tabindexen met een positief nummer zijn bezocht.)

In dit voorbeeld heeft de <h1> een tabindex="0" gekregen:

<h1 tabindex="0">Opvultekst</h1>

De tekst is te lang om helemaal te tonen, daarvoor moet gescrold worden. Normaal genomen zou een gebruiker van de Tab-toets dat niet kunnen, zonder gebruik te moeten maken van de muis (op een touchscreen speelt dit uiteraard niet). Door de <h1> een tabindex="0" te geven, kan de <h1> toch de focus krijgen. Zodra dat het geval is, kan de tekst ook met behulp van de pijltjestoetsen worden gescrold, dus zonder dat een muis nodig is.

Het zou iets logischer zijn om deze tabindex bij div#tekst te zetten, maar om een of andere reden loopt schermlezer TalkBack dan volkomen vast, in alle geteste versies van Android. Terwijl die normaal genomen geen problemen heeft met een serie Latijnse paragrafen. Zonder css doet TalkBack het prima. Kennelijk raakt TalkBack op een of andere manier in een coma door de combinatie van een tabindex bij div#tekst met bepaalde css.

Als de tabindex bij div#tekst gezet zou kunnen worden, zou overal :focus-visible kunnen worden gebruikt, in plaats van het nu voor sommige browsers gebruikte :focus-within. Dan zou echt alleen bij gebruik van de Tab-toets een kadertje rondom de tekst worden gezet. Nu gebeurt dat in sommige browsers ook, als de <h1> met 'Kopregel' wordt aangeraakt of -geklikt.

De kans dat precies de <h1> wordt aangeraakt of -geklikt, is echter vrij klein, en als dat toch gebeurt, is het ook geen ramp. Daarom is verder niet heel grondig naar de oorzaak van Talkbacks coma gezocht. (Je kunt heel systematisch naar de oorzaak gaan zoeken, maar dat kost vaak heel veel tijd, en in dit geval is het die tijd niet waard.)

tabindex="..."

Op de plaats van de puntjes moet een positief getal worden ingevuld: het volgnummer. Een element met een positieve tabindex wordt altijd bezocht bij gebruik van de Tab-toets, ook als dit element normaal genomen zou worden genegeerd. Elementen met een tabindex met een positief volgnummer worden altijd als eerste bezocht, voor elementen als een link of tekstveld zonder tabindex, en ook voor elementen met tabindex="0".

Een tabindex met een positief getal wordt in dit voorbeeld niet gebruikt.

Muis, toetsenbord, touchpad en touchscreen

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

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

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

Hieronder staat een lijstje met dingen die zijn aangepast voor de verschillende soorten schermen, zodat dit voorbeeld overal werkt. Een touchpad werkt ongeveer hetzelfde als een muis. Als hieronder iets over een muis staat, geldt dat ook voor een touchpad.

:hover

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

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

Op een touchscreen wordt hoveren vaak hetzelfde afgehandeld als een aanraking.

Bij gebruik van een muis is er een verschil tussen hoveren en klikken, maar op een touchscreen is dat verschil er niet: je raakt een touchscreen aan of niet. Dat levert vooral soms problemen op, als bij een element :hover én klikken worden gebruikt, zoals bij een link die bij hoveren erover verkleurt. Omdat deze combinatie niet wordt gebruikt in dit voorbeeld, spelen deze problemen niet. Een aanraking op een touchscreen werkt in dit geval hetzelfde als hoveren met een muis.

:focus

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

De meeste mensen gaan met een muis naar een link, invoerveld, en dergelijke. Waarna ze vervolgens klikken om de link te volgen, tekst in te voeren, of wat ze ook maar willen doen. (Dit geldt uiteraard niet voor touchscreens.)

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

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

Het kadertje dat de focus aangeeft, moet nooit zonder meer worden weggehaald. Gebruikers van de Tab-toets hebben dan geen idee meer, waar ze zijn.

Bij gebruik van de muis of een aanraakscherm is het kadertje niet nodig, want je mag toch hopen dat iemand weet, waar iemand iets heeft heeft aangeraakt of -geklikt. Als je dat niet meer weet, valt te vrezen dat een kadertje ook geen redding meer biedt.

In het verleden was dat vaak een probleem, omdat dat kadertje nou niet bepaald erg mooi is. En dus eigenlijk alleen bij gebruik van de Tab-toets nodig is. Dit is opgelost met de relatief nieuwe pseudo-class :focus-within: de focus wordt alleen nog aangegeven, als een toetsenbord wordt gebruikt. Bij een klik of een aanraking zie je het kadertje niet meer.

Inmiddels is :focus-within in alle iets nieuwere browsers de standaard, dus eigenlijk hoef je :focus en/of :focus-within alleen nog te gebruiken, als je bijvoorbeeld het uiterlijk van het kadertje wilt aanpassen.

In dit voorbeeld komt een kadertje rondom de tekst te staan, zodat de <h1> bovenaan de tekst door gebruik van de Tab-toets de focus heeft gekregen. Zonder dit kadertje zou een gebruiker van de Tab-toets niet weten dat de tekst nu met behulp van de pijltjestoetsen gescrold kan worden. Een langer verhaal hierover staat bij tabindex="0".

:active

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

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

:active wordt niet gebruikt in dit voorbeeld.

De code aanpassen aan je eigen ontwerp

Toegankelijkheid en zoekmachines

De tekst in dit hoofdstukje is een algemene tekst, die voor elke pagina geldt. Eventueel specifiek voor dit voorbeeld geldende problemen en eventuele aanpassingen om die problemen te voorkomen staan bij Bekende problemen (en oplossingen).

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:

Getest in

Laatst gecontroleerd op 5 januari 2023.

Onder dit kopje staat alleen maar, hoe en waarin is getest. Alle eventuele problemen, ook die met betrekking tot zoomen, lettergroottes, toegankelijkheid, uit staan van JavaScript en/of css, enzovoort staan iets 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!

Dit voorbeeld is getest op de volgende systemen:

Desktopcomputers

Windows 7 (1280 x 1024 px, resolution 96 ppi):
Firefox, Google Chrome en Edge, in grotere en kleinere browservensters.

Linux (Kubuntu 20.04 LTS, 'Focal Fossa') (2560 x 1080 px, resolution: 96 ppi):
Firefox en Google Chrome, in grotere en kleinere browservensters.

Laptops

Windows 8.1 (1366 x 768 px, resolution: 135 ppi):
Bureaublad-versie: Firefox, Google Chrome en Edge, in grotere en kleinere browservensters.

Windows 10 (1600 x 900 px, resolution: 106 ppi):
Firefox, Google Chrome en Edge, in grotere en kleinere browservensters.

OS X 11.7.1 ('Big Sur') (1440 x 900 px, resolution: 96 ppi, device-pixel-ratio: 1):
Firefox, Safari, Google Chrome en Microsoft Edge, in grotere en kleinere browservensters.

Tablets

iPad met iOS 12.5.6 (2048 x 1536 px, device-pixel-ratio: 2:
Safari, Chrome, Firefox en Microsoft Edge (alle portret en landschap).

iPad met iOS 13.3 (gesimuleerd in Xcode):
Safari (portret en landschap).

iPad met iPadOS 16.2 (2160 x 1620 px, 264 ppi):
Safari, Chrome, Firefox en Microsoft Edge (alle portret en landschap).

Android 6.0 ('Marshmallow') (1920 x 1200 px, resolution: 224 ppi):
Samsung Internet, Firefox en Chrome (alle portret en landschap).

Android 8.1 ('Oreo') (1920 x 1200 px, resolution: 218 ppi):
Samsung Internet, Firefox, Microsoft Edge en Chrome (alle portret en landschap).

Android 12 (2000 x 1200 px, resolution: 225 ppi):
Samsung Internet, Firefox, Microsoft Edge en Chrome (alle portret en landschap).

Smartphones

iPhone 7 met iOS 12.4 (gesimuleerd in Xcode):
Safari (portret en landschap).

iPhone 8 met iOS 13.3 (gesimuleerd in Xcode):
Safari (portret en landschap).

iPhone met iOS 15.7.2 (1334 x 750 px, 326 ppi):
Safari, Chrome, Firefox en Microsoft Edge (alle portret en landschap).

Android 7.0 ('Nougat') (1280 x 720 px, resolution: 294 ppi):
Samsung Internet, Firefox, Microsoft Edge en Chrome (alle portret en landschap).

Android 9.0 ('Pie') (1920 x 1080 px, resolution: 424 ppi):
Samsung Internet, Firefox, Microsoft Edge en Chrome (alle 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 iOS, iPadOs en Android, waar een touchscreen is gebruikt. Op Windows 8.1 en 10 is getest met touchscreen, touchpad, toetsenbord, muis, en - waar dat zinvol was - op een combinatie daarvan. Op OS X 11.7.1 is getest met (een combinatie van) toetsenbord, touchpad en muis.

Als in een voorbeeld JavaScript is gebruikt, is ook getest of het werkt zonder JavaScript. Dat is alleen gedaan in de browsers, waarin in de instellingen JavaScript kan worden uitgeschakeld.

Ook is getest zonder css en - als afbeeldingen worden gebruikt - zonder afbeeldingen.

Schermlezers en dergelijke

Naast deze 'gewone' browsers is ook getest in Lynx, WebbIE, NVDA, TalkBack, VoiceOver 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 6.0, 7.0, 8.1, 9 en 12

VoiceOver is een in iOS en OS X ingebouwde schermlezer. Er is getest in combinatie met Safari op iOS 12.5.6 en 15.7.2, iPadOS 16.2 en OS X 11.7.1.

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

(Voor de bovenstaande programma's zijn links naar sites met uitleg en dergelijke te vinden op de pagina met links onder Toegankelijkheid → Schermlezers, tekstbrowsers, en dergelijke.)

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 problemen in schermlezers (en eventuele aanpassingen om die te voorkomen) staan iets hieronder bij Bekende problemen (en oplossingen).

Alleen op de hierboven genoemde systemen en browsers is getest. Er is dus niet getest op bijvoorbeeld 'n Blackberry. Er is een kans dat dit voorbeeld niet (volledig) werkt op niet-geteste systemen en apparaten. Om het wel (volledig) werkend te krijgen, zul je soms (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 Samsung Internet op Android 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 geen beginnen aan.

De html is gevalideerd met de html-validator, de css met de css-validator van w3c. 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. Anders is er 'n redelijke kans 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! Dat kan op het forum.)

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.

Bij toegankelijkheid is er vaak geen goed onderscheid te maken tussen oplossing en probleem. Zonder (heel simpele) aanpassingen heb je vaak 'n probleem, en omgekeerd. Daarom staan wat betreft toegankelijkheid aanpassingen en problemen hier bij elkaar in dit hoofdstukje.

Voor zover van toepassing wordt eerst het ontbreken van JavaScript, css en/of afbeeldingen besproken. Vervolgens problemen en aanpassingen met betrekking tot toegankelijkheid voor specifieke groepen bezoekers, zoals zoomen en andere lettergrootte, Tab-toets, tekstbrowsers en schermlezers. Als laatste volgen de overige problemen in één of meer specifieke browsers.

Als in een onderdeel geen problemen aanwezig zijn, staat in een smal groen kadertje 'Geen problemen'. Bij een onderwerp over toegankelijkheid zijn er soms geen problemen, maar alleen aanpassingen. Ook in dat geval staat bovenaan in een smal groen kadertje 'Geen problemen'. Daaronder staan dan de aanpassingen.

Als in een onderdeel één of meer problemen worden besproken, staat van elk probleem in een breed rood kadertje een korte samenvatting daarvan.

Als bij het probleem een oplossing wordt gegeven, staat de samenvatting in een rode stippellijn. Bij een onderwerp over toegankelijkheid zijn er soms, naast de opgeloste problemen, ook aanpassingen. In dat geval staan staan die aanpassingen boven de kadertjes met opgeloste problemen.

Als bij het probleem geen oplossing is gevonden, staat de samenvatting in een rode ononderbroken lijn. Bij een onderwerp over toegankelijkheid zijn er soms, naast de problemen, ook aanpassingen. In dat geval staan staan die aanpassingen boven de kadertjes met problemen.

Zonder JavaScript

Geen problemen.

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

Zonder css

Geen problemen.

Zonder css wordt de tekst gewoon volledig weergegeven. Uiteraard is de lay-out verdwenen.

Gebruikers Tab-toets

Geen problemen.

Om te zorgen dat ook gebruikers van de Tab-toets de tekst kunnen scrollen, heeft de <h1> een tabindex="0" gekregen:

<h1 tabindex="0">Opvultekst</h1>

Nu kan de <h1> de focus krijgen, waarna de eronder staande tekst met behulp van de pijltjestoetsen gescrold kan worden. Een langer verhaal hierover staat bij tabindex"=0".

Tekstbrowsers

Geen problemen.

Lynx en WebbIE tonen beide de volledige tekst.

Schermlezers

Probleem: in VoiceOver op iOS en iPadOS staat tekst soms onder de gradiënt.

In alle op een touchscreen geteste schermlezers wordt de tekst tijdens het voorlezen automatisch gescrold. Met uitzondering van VoiceOver op iOS en iPadOS wordt de tekst steeds zoveel gescrold, dat je desgewenst kunt meelezen tijdens het voorlezen. In VoiceOver op iOS en iPadOS wordt de tekst veel minder naar boven gescrold, waardoor de tekst die op dat moment wordt voorgelezen, soms nog gedeeltelijk onder de gradiënt staat. Alles wordt dus wel voorgelezen, maar meelezen is lastig.

Bij de onderste paragraaf met tekst ontstaat een probleem: deze blijft in alle schermlezers onder de gradiënt staan. Dit is opgelost door op touchscreens de onderste paragraaf aan de onderkant een grote padding te geven. Hierdoor wordt deze paragraaf extra ver naar boven gescrold en is toch zichtbaar. (Een marge werkt niet, het moet echt een padding zijn.)

VoiceOver op iOS en iPadOS negeert deze padding volledig: daarin blijft de onderste paragraaf onder de gradiënt staan. (De tekst wordt wel gewoon volledig voorgelezen.) Ook dingen als een extra marge, de paragraaf verplaatsen met een negatieve marge aan de bovenkant, relatief positioneren, verplaatsen met translateY(), de onderste <p> een hoogte geven, extra <br>'s, onzichtbare tekens, een schop tegen het kolere-apparaat, noem maar op, hadden geen enkel effect.

Zoomen en andere lettergrootte

Probleem: op iOS ouder dan versie 13 kan de tekst niet worden gescrold, als wordt ingezoomd (vergroot).

Op iOS ouder dan versie 13 kan de tekst nauwelijks worden gescrold. Om dat op te lossen is -webkit-overflow-scrolling: touch; gebruikt. Een bijwerking daarvan is dat de tekst niet meer gescrold kan worden, zodra wordt ingezoomd (vergroot). Je kunt wel scrollen, inzoomen, lezen, weer uitzoomen, stukje scrollen, inzoomen, enzovoort, maar dat is natuurlijk heel omslachtig. Meer hierover is te vinden bij -webkit-overflow-scrolling: touch;.

Overige problemen

Probleem: scrollbar-gutter en :has() valideren niet.

scrollbar-gutter is een tamelijk nieuwe eigenschap, :has() is een tamelijk nieuwe pseudo-class. Daarom geven deze nog een foutmelding in de css-validator. Deze foutmeldingen kunnen worden genegeerd, want deze eigenschappen worden al in veel nieuwere browsers gewoon ondersteund. Als een van beide of beide (nog) niet worden ondersteund, negeert de browser de betreffende regels.

Wijzigingen

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

:

Nieuw opgenomen.

10 april 2009:

13 april 2009:

Hierboven genoemde meta-tag weer weggehaald, het wordt nu ook goed weergegeven in de standaardmodus van Internet Explorer 8.

In de vorige versie stond de div met de doorzichtige png relatief gepositioneerd, zodat hij precies op de goede plaats gezet kon worden. Voor dat op de goede plaats zetten werd mede een negatieve marge aan de bovenkant van de div gebruikt. In Internet Explorer 8 blijkt een bug te zitten, waardoor dit niet meer kon.

De combinatie relatieve positie met een negatieve marge aan de bovenkant zorgde ervoor, dat de div met de doorzichtige png bij scrollen met de tekst mee omhoog schoof, dus over de tekst bleef staan. Bovendien kreeg de ruimte onder de div, die maar 60 px hoog is, dezelfde kleur als de achtergrond van de pagina, waardoor de tekst niet meer zichtbaar was.

Bij gebruik van top met een negatieve waarde gebeurde precies hetzelfde.

Door de relatieve positie van de div te veranderen in een absolute werd het probleem opgelost: nu blijft de div, en dus de png, wel op z'n plaats staan als de tekst wordt gescrold. Ook de horizontale marges moesten worden aangepast.

Er was al aparte css voor Internet Explorer 6 en 7. Als er ook nog aparte css voor Internet Explorer 8 zou komen, zouden er in totaal vier versies zijn: eentje voor alle serieuze browsers, en drie voor het speelgoed van de firma Microsoft. Dus de is div#vervaag zo aangepast, dat hij in alle browsers werkt (behalve in Internet Explorer 6, want daar werkt dit hele voorbeeld niet).

5 januari 2023:

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 min of meer 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-057-dl.html: de pagina met het voorbeeld.

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

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

057-css-dl:

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

HTML

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

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

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

<!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 grootte. En dat is een probleem. Sites waren, in ieder geval tot enkele jaren geleden, 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 deze wil zien.

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

Nieuwe sites of pagina's kunnen echter wel rekening houden met de veel kleinere vensters van mobiele apparaten. In dit voorbeeld bijvoorbeeld wordt de tekst nooit breder dan 80 procent van het venster.

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

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

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. Als een iPad in portretstand bijvoorbeeld 768 px breed is, wordt de pagina ook 768 px breed.

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 wordt niet gebruikt. De bezoeker kan zelf nog gewoon zoomen, wat belangrijk is voor mensen die wat slechter zien.

<h1 tabindex="0">Opvultekst</h1>

Dit is de kopregel boven de tekst. Door het attribuut tabindex="0" kan de <h1> de focus krijgen, wat normaal genomen niet kan. Hierdoor kan de <h1> ook bij gebruik van de Tab-toets de focus krijgen, waarna detekst met de pijltjestoetsen gescrold kan worden.

<p lang="la">

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

CSS

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

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 het kopje Gereedschap → Snelheid, testen, gzip, comprimeren (inclusief theorie) links naar sites vinden, waar je bestanden kunt comprimeren.

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

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

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;

Slim om te doen vanwege verschillen tussen browsers.

#content

Het element met id="content". De <section> waar alles in zit.

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: 80vw;

Hier gelijk boven is een breedte van 500 px opgegeven. In browservensters die smaller zijn dan 500 px zou hierdoor horizontaal gescrold moeten worden om alle tekst te kunnen zien. Daarom wordt hier een maximumbreedte opgegeven.

De eenheid vw is gebaseerd op de breedte van het venster van de browser. 1 vw is 1% van de breedte van het venster, en 80 vw is 80% van de breedte. De <section> wordt hierdoor nooit breder dan 80% van de breedte van het venster, ongeacht de breedte van het venster.

margin: 20px auto 0;

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

Aan de bovenkant een kleine marge voor wat ruimte tot de bovenkant van het browservenster.

Links en rechts auto, wat hier hetzelfde betekent als evenveel. Hierdoor komt de <section> altijd horizontaal gecentreerd binnen z'n ouder <main> te staan. <main> is een blok-element en wordt daardoor normaal genomen automatisch even breed als z'n ouder <body>. Ook <body> is een blok-element en wordt daardoor 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.

Hierdoor staat uiteindelijk section#content altijd horizontaal gecentreerd binnen het venster van de browser, ongeacht de breedte van het venster. En daarmee ook de in de <section> zittende tekst en dergelijke.

Deze manier van horizontaal centreren van een blok-element werkt alleen, als het blok-element een breedte heeft, want anders zou het normaal genomen even breed worden als de ouder ervan. Dat is geregeld, want iets hierboven heeft de <section> zowel een breedte van 500px als een maximumbreedte van 80vw gekregen.

border: black solid 1px;

Zwart randje.

#tekst

Het element met id="tekst". De <div> waar de tekst in zit.

height: 380px;

Hoogte. Normaal genomen wordt een blok-element zoals een <div> precies hoog genoeg om de inhoud ervan weer te geven. In dit geval is dit de in de <div> zittende tekst. Door een hoogte aan de <div> te geven, past de tekst niet meer binnen de <div>.

overflow: auto; Zonder overflow: auto wordt alle tekst getoond.

De eigenschap overflow regelt, wat er gebeurt als de inhoud van een blok-element groter is dan dat element zelf. Standaard is de waarde 'visible': ook al past de inhoud niet in het blok-element, geef het toch weer. Mogelijk wordt dan de lay-out verstoord, maar er verdwijnt in ieder geval geen tekst of zo. Dit is precies, wat er op de afbeelding gebeurt: de tekst loopt gewoon door onder div#tekst gewoon door. De zwarte border hoort bij section#content, die precies hoog genoeg wordt om de erin zittende div#tekst met een hoogte van 380 px weer te geven.

(div#vervaag met de gradiënt zit ook in section#content, maar die wordt met een negatieve marge aan de bovenkant een eind naar boven verplaatst, waardoor deze geen invloed meer heeft op de hoogte van section#content.)

De hier gebruikte waarde 'auto' wil zeggen dat er, als de inhoud niet in het blok-element past, gescrold kan worden. Op de desktop verschijnt hierbij een verticale scrollbalk, maar niet op smartphones en tablets.

-webkit-overflow-scrolling: touch;

Deze eigenschap is nodig om een probleem op iOS ouder dan versie 13 op te lossen. Daarom is het hier geen probleem dat alleen de eigenschap met het voorvoegsel ‑webkit- wordt gebruikt, want deze eigenschap wordt alleen door browsers op iOS ouder dan versie 13 herkend. Meer over voorvoegsels is te vinden bij De voorvoegsels -moz- en -webkit-.

De tekst kan op iOS ouder dan versie 13 nauwelijks worden gescrold. Dit probleem doet zich meestal voor als een element fixed is gepositioneerd, maar in dit geval gebeurt het hier om een of andere reden ook.

Als je de tekst wilt scrollen, gaat dat ongelooflijk houterig. Je kunt uiteindelijk wel overal komen, maar vraag niet hoe. Een jichtige olifant die de chachacha danst, met als partner een giraf met een nekhernia, is een toonbeeld van soepelheid en elegantie, vergeleken met het scrollen van de tekst op iOS voor versie 13.

Om een of andere reden lost deze eigenschap het probleem met het scrollen op.

Helaas heeft deze eigenschap echter de meest wilde bijwerkingen. Heel vaak verdwijnen er gewoon delen van de pagina bij gebruik van deze eigenschap, of een link werkt niet meer, of... Het regende hier klachten over, maar zoals gewoonlijk reageerde Apple nergens op. Allerlei mensen bedachten hier zelf oplossingen voor, maar die werkten nooit in alle gevallen.

Als je deze eigenschap gebruikt, moet je dus echt heel goed testen, of er geen dingen verdwijnen en op andere bijwerkingen. Een vrijwel altijd voorkomende bijwerking is dat het element, waarbij deze eigenschap gebruikt wordt, niet meer ingezoomd én gescrold kan worden. Dat is hier ook het geval: als je inzoomt, kun je de tekst niet meer scrollen. Je kunt wel eerst scrollen, dan inzoomen, lezen, uitzoomen, weer 'n stuk scrollen, weer inzoomen, enzovoort, maar dat is nogal omslachtig.

Ook hier regende het klachten over, maar omdat Apple gewoon nooit ergens op reageert, was zelfs onduidelijk of dit zo hoorde, of het een bug was, wat dan ook. Applefans noemen dit soort dingen trouwens meestal een feature. Hoe dan ook: in versie 13 van iOS (en dus ook in iPadOS) is het gelukkig eindelijk opgelost. Daarin is deze eigenschap niet meer nodig en wordt zelfs volledig genegeerd.

padding: 5px;

Aan alle kanten wat ruimte tussen de buitenkant van div#tekst en de erin zittende tekst.

h1

Alle <h1>'s. Dat is er maar één: de titel boven de tekst zit erin.

margin: 0;

Van zichzelf heeft een <h1> een marge aan boven- en onderkant. Die wordt hier weggehaald.

font-size: 1.2em;

De lettergrootte van een <h1> is vergelijkbaar met de grootte van het ego van Baudet: veel te groot. Anders dan bij het ego van Baudet, kan de lettergrootte simpel wat worden verkleind.

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.

#content p

Alle <p>'s binnen het element met id="content". De <p>'s waarin de tekst staat.

margin: 0;

Van zichzelf heeft een <p> een marge aan boven- en onderkant. Die wordt hier weggehaald.

#vervaag-buiten

Het element met id="vervaag-buiten". Binnen deze <div> zit de <span> met de vervagende gradiënt. Waarom deze extra <div> nodig is en je niet alleen met die <span> kunt volstaan, staat iets hieronder bij scrollbar-gutter: stable;.

display: none;

Verbergen. Bij @media (hover: none) and (pointer: coarse) wordt gekeken of er een scrollbalk aanwezig is. Als dat zo is, hoeft de hele gradiënt niet getoond te worden, want dan is al duidelijk dat er gescrold kan worden om meer tekst te zien.

overflow: auto;

div#vervaag-buiten is een blok-element en wordt daardoor, als je geen hoogte opgeeft, automatisch precies hoog genoeg om de erin zittende inhoud weer te geven. Hier is die inhoud alleen de <span> met de gradiënt.

Omdat geen hoogte is opgegeven en de inhoud dus per definitie binnen de <div> past, is overflow overbodig. Maar het hier gelijk onder staande scrollbar-gutter werkt alleen, als overflow de waarde auto, scroll of hidden heeft.

scrollbar-gutter: stable;

Deze eigenschap werkt alleen als overflow de waarde auto, scroll of hidden heeft. Dat is gelijk hierboven bij overflow geregeld.

In een volmaakte wereld zou deze eigenschap niet nodig zijn. Als een scrollbalk wordt getoond, is de vervagende gradiënt afwezig. Als het goed is. Als als aan de test bij @media (hover: none) and (pointer: coarse) wordt voldaan is, het apparaat een smartphone of tablet, is er geen scrollbalk en wordt de gradiënt getoond. Als niet aan die test wordt voldaan, is er wel een scrollbalk en wordt de gradiënt niet getoond. In principe kunnen gradiënt en scrollbalk elkaar dus nooit bijten.

Maar in het verleden zouden bijvoorbeeld Samsung tablets soms onjuiste waarden hebben gegeven als op pointer werd getest. En wie weet wat voor exotische apparaten er in Verweggistan door een professor Sickbock in elkaar zijn geknutseld, of wat de toekomst nog voor vreemdigheden gaat opleveren.

Hoewel die kans klein is, zou het dus toch kunnen dat scrollbalk en gradiënt gelijktijdig worden getoond. Op de afbeeldingen hieronder is dit gesimuleerd: scrollbalk én gradiënt zijn aanwezig.

Op de afbeeldingen is de scrollbalk bij div#tekst, waarin de tekst zit, zwart gemaakt, zodat deze duidelijker opvalt. div#vervaag-buiten heeft geen achtergrond of zoiets en is dus doorzichtig. Om div#vervaag-buiten toch zichtbaar te maken, heeft deze een groene outline gekregen. span#vervaag, de <span> met de gradiënt, heeft een rode border gekregen.

Op de afbeelding rechts ontbreekt scrollbalk-gutter. div#vervaag-buiten is even breed als ouder section#content, en span#vervaag is weer even breed als ouder div#vervaag-buiten. Ook div#tekst met de tekst is even breed als z'n ouder section#content. Alle drie de elementen zijn dus even breed, met als resultaat dat de gradiënt over de onderkant van de scrollbalk van div#tekst heen staat. Geen grote ramp, maar het is gewoon niet zo netjes.

Zonder scrollbar-gutter staat gradiënt over de scrollbar.

Op de afbeelding links is scrollbalk-gutter: stable; gebruikt bij div#vervaag-buiten. De scrollbalk bij div#tekst is nog precies hetzelfde. Ook div#vervaag-buiten is nog precies hetzelfde en staat nog steeds vrolijk over de scrollbalk van div#tekst heen. Maar omdat div#vervaag-buiten geen achtergrond of zo heeft, is die doorzichtig en is dat geen enkel probleem: je ziet de scrollbalk gewoon door div#vervaag-buiten heen.

span#vervaag, en daarmee ook de erin zittende gradiënt, is nu smaller, waardoor de scrollbalk van div#tekst gewoon volledig zichtbaar is.

scrollbalk-gutter: stable; reserveert ruimte voor een scrollbalk, ook als die niet aanwezig is. div#vervaag-buiten is nog steeds even groot, maar de inhoud ervan is nu precies de breedte van een scrollbalk smaller, ook als die scrollbalk niet aanwezig is. En omdat die niet aanwezige scrollbalk even breed is als de wel aanwezige scrollbalk bij div#tekst, is de scrollbalk van div#tekst nu volledig zichtbaar.

Je zou natuurlijk ook gewoon div#vervaag met de gradiënt iets smaller kunnen maken, maar helaas zijn de scrollbalken van verschillende browsers niet even breed. Bovendien kun je sinds 'n tijdje met css de breedte van de scrollbalk aanpassen, dus mogelijk heeft de bezoeker dat ook gedaan. En wie weet, wat er in de toekomt nog meer mogelijk wordt. scrollbar-gutter past zich aan de gebruikte breedte van de scrollbalk aan, dus de breedte daarvan is altijd hetzelfde als de breedte van de scrollbalk.

margin-top: -120px; Gradiënt staat verkeerd.

div#vervaag-buiten heeft geen eigen hoogte gekregen. Omdat het een blok-element is, wordt het daardoor even hoog als de inhoud ervan. Die inhoud is span#vervaag, die bij #vervaag een hoogte van 120 px krijgt. Dat is dus ook de hoogte van div#vervaag. Door de <div> door middel van een negatieve marge aan de bovenkant 120 px naar boven te verplaatsen, komt deze over de onderkant van de tekst heen te staan.

Een negatieve marge verplaatst het element daadwerkelijk. Als je verplaatst met iets als position: relative; en top: -120px;, of transform: translateY(-120px);, krijg je het resultaat op de afbeelding: de <div> wordt wel verplaatst, maar de oorspronkelijke ruimte blijft gereserveerd. Dat levert in dit geval een lege ruimte van 120 px onder div#vervaag-buiten op, en daarmee ook onder de daarin zittende span#vervaag met de gradiënt.

pointer-events: none;

div#vervaag-buiten is gelijk hierboven met een negatieve marge naar boven verplaatst. Omdat div#vervaag-buiten in de html na div#tekst staat, komt div#vervaag-buiten daardoor over div#tekst heen te staan. Hierdoor kun je onder div#vervaag-buiten – en dus onder de daarin zittende gradiënt – geen tekst selecteren, kopiëren, en dergelijke. div#vervaag-buiten blokkeert een aanraking, klik, en dergelijke.

Met behulp van deze regel negeert div#vervaag-buiten aanraken en klikken volledig en gaan deze door naar het eronder zittende element: div#tekst. Nu kun je toch tekst onder de gradiënt selecteren, kopiëren, en dergelijke.

Tenzij je bij nakomelingen van div#vervaag een andere waarde opgeeft bij pointer-events, negeren ook die aanraken, klikken, en dergelijke.

#vervaag

Het element met id="vervaag". De <span> met de vervagende gradiënt.

background: linear-gradient(rgba(255, 255, 153, 0), rgba(255, 255, 153, 0.5) 25%, rgba(255, 255, 153, 0.7) 50%, rgba(255, 255, 153, 0.9) 90%);

Als achtergrond wordt een gradiënt gebruikt: een verlopende kleur.

Je kunt een gradiënt zelf uitvogelen, maar vaak is het makkelijker om gebruik te maken van een gradiënt-editor. Op de pagina met links zijn onder het kopje CSS → Online uitproberen, code genereren, en dergelijke links naar gradiënt-editors te vinden.

In dit geval is geen gradiënt-editor gebruikt, omdat hier uitgeprobeerd moest worden, wat de beste waarden zijn voor een vervagende gradiënt boven een stuk tekst.

linear-gradient bestaat uit twee of meer parallel lopende kleuren, die eventueel (geleidelijk) in elkaar over kunnen gaan. De Nederlandse vlag kun je maken met een gradiënt met drie kleuren: drie verschillend gekleurde boven elkaar liggende horizontale banen.

Je kunt de richting van de kleuren in een gradiënt aangeven: van boven naar onder of omgekeerd, en van links naar rechts of omgekeerd. Ook kun je eventueel de banen onder een hoek weergeven. Dat is hier allemaal niet gebeurd, waardoor de standaardwaarde to bottom wordt gebruikt: van boven naar beneden horizontale banen.

De hier gebruikte gradiënt heeft dezelfde kleur als de achtergrond van de pagina, maar dan geleidelijk verlopend van volledig doorzichtig naar vrijwel ondoorzichtig. Daardoor is de eronder zittende tekst bovenaan de gradiënt gewoon leesbaar en onderaan de gradiënt vrijwel niet meer te zien.

In een gradiënt, waarin alle banen dezelfde min of meer doorzichtige kleur hebben, zijn de verschillende banen vrijwel niet te zien. Dat is ook precies de bedoeling, maar ietwat onhandig als je het wilt beschrijven. Daarom is diezelfde gradiënt hieronder weergegeven met dezelfde banen, maar nu met verschillende kleuren. De gradiënt uit het voorbeeld heeft vier banen, dus hier worden ook vier banen gebruikt. Omdat hierboven de Nederlandse vlag al is genoemd, zijn de eerste drie kleuren rood, wit en blauw. Tja, de vierde kleur. Dat moet dan maar oranje worden, hoewel dat voor een republikein eigenlijk een acute identiteitscrisis oproept.

Gradiënt met beter zichtbare kleuren.

De bovenste rode baan begint bovenaan.

De tweede witte baan begint op 25% van de bovenkant.

De derde blauwe baan begint halverwege.

De onderste oranje baan begint op 90% van de bovenkant.

De browser regelt automatisch dat de kleuren geleidelijk aan in elkaar overgaan. (Als je niet wilt dat de kleuren geleidelijk in elkaar overgaan, geef je gewoon begin én einde van een baan aan, wat hier niet is gedaan.)

Omdat rood, wit, blauw en oranje duidelijker zijn dan vier keer dezelfde doorzichtige kleur, worden eerst deze kleuren gebruikt. Later worden die dan vervangen door de kleuren die in het voorbeeld worden gebruikt. De kleuren worden gescheiden door een komma:

linear-gradient(red, white, blue, orange);

Omdat hier geen begin- of eindpunt voor de kleuren is opgegeven, worden deze gelijk verdeeld: elke kleur krijgt 25% van de beschikbare ruimte.

Met de beginpunten erbij wordt het:

linear-gradient(red, white 25%, blue 50%, orange 90%);

Achter elke kleur staat nu het beginpunt van die kleur. Gemeten vanaf de bovenkant, want de banen lopen van boven naar beneden. Rood heeft geen beginpunt nodig, omdat dat de eerste kleur is: die begint bovenaan. Omdat geen eindwaarde voor de kleuren is opgegeven, gaan de kleuren geleidelijk in elkaar over. Overigens kun je begin- en eindpunten ook in andere waarden dan procenten opgeven, zoals px.

Deze code levert de hierboven staande rood-wit-blauw-oranje gradiënt op.

In het voorbeeld is de volgende gradiënt gebruikt:

linear-gradient(rgba(255, 255, 153, 0), rgba(255, 255, 153, 0.5) 25%, rgba(255, 255, 153, 0.7) 50%, rgba(255, 255, 153, 0.9) 90%);

Hier staan nog steeds vier kleuren en drie percentages, gescheiden door een komma. De simpele kleuren van de gradiënt hierboven zijn hier echter vervangen door rgba() met vier getallen tussen de haakjes. rgba() is gewoon een andere manier om kleuren te definiëren. Bovendien kun je hiermee de doorzichtigheid van een kleur opgeven. Dat kan met iets als red of niet.

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

Bij alle vier de kleuren in dit voorbeeld zijn de eerste drie getallen 255, 255 en 153. Dit levert de beige kleur van de achtergrond van de pagina 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. Dit getal is bij alle vier de kleuren verschillend en zorgt voor de geleidelijk aan van boven naar beneden toenemende ondoorzichtigheid.

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 zijn de waarden voor doorzichtigheid achtereenvolgens 0 (volledig doorzichtig), 0.5 (half doorzichtig), 0.7 (nog minder doorzichtig) en 0.9 (vrijwel ondoorzichtig).

Omdat geen eindwaarden voor de kleuren zijn opgegeven, verloopt ook de doorzichtigheid geleidelijk aan.

Het eindresultaat is een gradiënt in de kleur van de achtergrond van de pagina, bovenaan doorzichtig en naar onder toe geleidelijk aan ondoorzichtig wordend. Deze waarden zijn door uitproberen gevonden.

display: block;

Een <span> is een inline-element. Daardoor kunnen eigenschappen als hoogte niet worden gebruikt. Door de <span> als blok-element weer te geven, kan dat wel.

height: 120px;

Behalve de achtergrond zit er niets in de <span>. Daardoor heeft de <span> geen hoogte en is de erin zittende achtergrond (de gradiënt) niet te zien. Door de <span> een hoogte te geven, is de achtergrond wel te zien.

position: relative;

In principe bepaalt de volgorde in de html, welke elementen boven andere elementen komen te staan. Dat is hier ook zo. De ouder van deze <span> is div#vervaag-buiten, die bij #vervaag-buiten met een negatieve marge boven de <div> met de tekst is gezet. Omdat deze <span> in div#vervaag-buiten zit, komt ook de <span> (en daarmee de erin zittende gradiënt) boven de tekst te staan.

Alleen zijn er nog andere regels die bepalen, wat uiteindelijk bovenaan komt te staan, en daarmee zichtbaar is.

Zonder position staat de gradiënt achter de tekst.

Op de afbeelding hiernaast is in de <span> een wanstaltig grote letter 'o' neergezet. Omdat dat gewone tekst is, wordt die inderdaad boven de tekst uit div#tekst neergezet en verbergt die volledig.

Voor achtergronden gelden echter andere regels: die worden normaal genomen altijd helemaal onderaan gezet. Daar zijn het ook achtergronden voor: achter de rest. Dat is ook wat op de afbeelding gebeurt: de als achtergrond gebruikte gradiënt staat onder de tekst, waardoor deze gewoon volledig leesbaar is.

Door de <span> een relatieve positie te geven, verandert dit. De achtergrond van elementen met een andere positie dan statisch komt wél bovenaan te staan, waardoor de tekst wel in toenemende mate vervaagt.

h1:focus

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

h1 {margin: 0; font-size: 1.2em;}

Alle <h1>'s, maar alleen als de <h1> de focus heeft. Er is maar één <h1>: de kop boven de tekst staat erin.

outline solid blue 3px;

Blauw kadertje rondom de <h1> zetten.

Dit is bedoeld voor gebruikers van de Tab-toets. Normaal genomen kunnen alleen knoppen, links, tekstvelden, en dergelijke de focus krijgen. Een <h1> kan normaal genomen geen focus krijgen, maar door het toevoegen van tabindex="0" kan dit hier wel.

Als de <h1> de focus krijgt, wordt een blauw kadertje rondom de <h1> gezet. Hierdoor is voor gebruikers van de Tab-toets duidelijk, dat ze met met behulp van de pijltjestoetsen door de tekst kunnen scrollen.

Het zou duidelijker zijn, als dit kadertje niet alleen rondom de <h1>, maar om de volledige te scrollen tekst zou komen te staan. Voor nieuwere browsers gebeurt dat gelijk hieronder ook met behulp van :has(), :focus-visible en :focus-within. Iets verder bij @supports (not selector(:has(*))) and selector(:focus-within) gebeurt dat voor iets minder nieuwe browsers, die :has() (nog) niet ondersteunen, maar wel :focus-within.

De regel hier is bedoeld voor browsers, die dit allemaal (nog) niet ondersteunen. Een kadertje alleen rondom de <h1> is dan nog altijd beter dan helemaal geen kadertje, want dan hebben gebruikers van de Tab-toets geen enkele indicatie dat ze de tekst met de pijltjestoetsen kunnen scrollen.

#content:has(:focus-visible)

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.

#content {background: white; color: black; width: 500px; max-width: 80vw; margin: 20px auto 0; border: black solid 1px;}

Het element met id="content", maar alleen als een nakomeling daarvan :focus-visible heeft.

De nieuwe :has() pseudo-class wordt nog niet door alle browsers ondersteund. Browsers die dit nog niet ondersteunen, negeren deze regel gewoon. Hetzelfde geldt voor het al iets minder nieuwe :focus-visible. Voor browsers die :has() en :focus-visible geen van beide ondersteunen, staat gelijk hierboven bij h1:focus een regel, voor browsers die :has() (nog) niet maar :focus-within wel ondersteunen, staat gelijk hieronder bij @supports (not selector(:has(*))) and selector(:focus-within) een regel.

:has() kijkt of binnen het element een nakomeling zit, die voldoet aan de voorwaarden binnen de haakjes. In dit geval moet een nakomeling :focus-visible hebben: een nakomeling moet de focus hebben (waarom :focus-visible en niet :focus wordt gebruikt, staat iets verderop).

Dit is bedoeld voor gebruikers van de Tab-toets. In section#content zit onder andere een <h1>. Normaal genomen kunnen alleen knoppen, links, tekstvelden, en dergelijke de focus krijgen. Een <h1> kan normaal genomen geen focus krijgen, maar door het toevoegen van tabindex="0" kan dit hier wel. Dit is het enige element binnen section#content dat de focus kan krijgen. Ook section#content zelf kan niet de focus krijgen.

Doordat de <h1> de focus kan krijgen, kunnen gebruikers van de Tab-toets met behulp van de pijltjestoetsen door de tekst scrollen. Dit wordt duidelijk gemaakt met behulp van een kadertje, dat rondom de tekst verschijnt, zodra de <h1> de focus heeft.

De markering met het kadertje is niet nodig op een touchscreen of bij gebruik van een muis: de bezoeker heeft dan zelf iets aangeraakt of -geklikt en weet dan (hopelijk), op welke plaats dat is gedaan. Voor het mooie hoef je een element met focus niet te markeren, dus bij aanraken of klikken kun je dat kadertje missen als kiespijn. Dit probleem is met :focus-visible opgelost: bij een aanraking of klik werkt de selector niet, maar bij gebruik van de Tab-toets wel. Het (lelijke) kadertje verschijnt nu alleen bij gebruik van de Tab-toets.

Alle iets nieuwere browsers gebruiken inmiddels standaard :focus-visible in plaats van :focus. Browsers die :focus-visible nog niet ondersteunen, negeren deze regel gewoon.

outline: blue solid 3px;

Om voor gebruikers van de Tab-toets duidelijk te maken dat de tekst gescrold kan worden, wordt een blauw kadertje rondom section#content gezet, en daarmee rondom de hele erin zittende tekst.

#content:has(:focus) h1

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

h1 {margin: 0; font-size: 1.2em;}

h1:focus {outline: blue solid 3px;}

Alle <h1>'s, maar alleen als binnen div#content een element zit dat de focus heeft.

outline: none;

Omdat nu een kadertje rondom de volledige tekst staat, is het kadertje rondom de <h1> boven de tekst niet meer nodig. Dat kadertje was alleen voor oudere browsers die :has() en/of :focus-visible (nog) niet ondersteunen.

@supports (not selector(:has(*))) and selector(:focus-within)

De css die binnen deze 'feature query' staat, geldt alleen voor browsers die :has() níét en :focus-within wél ondersteunen. (Een 'feature query' is een vraag of een bepaalde eigenschap en waarde, of een bepaalde selector, worden ondersteund: iets als 'eigenschap vraag'.)

@supports: hierachter komen tussen haakjes de te onderzoeken selector(s) en/of de te onderzoeken eigenschap(pen) met eventueel een bepaalde waarde te staan.

(not selector(:has(*))):

(not): hier wordt gekeken, of iets juist níét wordt ondersteund. Het gebruik van het sleutelwoordje not keert het erachter staande selector(:has(*)) om. Om duidelijk te maken waar het deel waarvoor not geldt begint en eindigt, staat dit tussen haakjes.

selector(): als je, zoals hier gebeurt, niet op een eigenschap met waarde, maar op een selector wilt testen, gebruik je het sleutelwoord selector(). Tussen de haakjes komt dan de selector te staan, waarvan je de ondersteuning wilt testen.

:has(*): dit is de selector, waarop wordt getest: :has(). Bij :has() kun je een hele reeks variaties opgeven, daarom moet bij :has() ook worden opgegeven, waarop wordt getest, want niet alle browsers ondersteunen al foutloos alle verschillende variaties.

Hier wordt op * getest, wat in css 'alles' betekent. Oftewel: het maakt niet uit hoeveel of hoe weinig of hoe verkeerd iets van :has() wordt ondersteund, als het maar enigszins wordt ondersteund, werkt deze selector al niet meer.

(not selector(:has(*))) bij elkaar: :has() mag niet worden ondersteund.

and: er volgt nog een tweede voorwaarde.

selector(): weer het sleutelwoord dat aangeeft dat er op een selector getest gaat worden.

(:focus-within): de selector, waarvan je de ondersteuning wilt testen. Omdat :focus-within altijd zonder verdere toevoeging wordt gebruikt, is dit voldoende.

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 (not selector:has(*))) and selector(:focus-within)) { body {color: silver;} (...) rest van de css voor deze feature query (...) footer {color: gold;} }

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

Alleen browsers die :has() níét en :focus-within wél ondersteunen, voeren de css binnen deze feature query uit. Oudere browsers kennen :focus-visible niet en voeren de css binnen deze feature query daarom niet uit. Als een browser zo oud is dat het hele @supports niet wordt onder\steund, negeert ook die browser alle css binnen de feature query.

Het testen op eigenschappen wordt al langer ondersteund, maar het op selectors testen met behulp van selector() is relatief nieuw. Niet alle browsers die @supports ondersteunen, ondersteunen ook al selector(). Ook als dat het geval is, werkt het weer hetzelfde: de css binnen de feature query wordt genegeerd. (Standaard negeren browsers css die ze niet kennen.)

Er moet ook op het níét ondersteunen van :has() worden getest, omdat deze regel anders de in de css hoger staande regel bij #content:has(:focus-visible) overrulet, omdat deze regel lager staat. Een browser die :has() ondersteunt zal (vrijwel) altijd ook :focus-within ondersteunen, waardoor de iets beter werkende hoger staande regel niet meer werkt. Door browsers die :has() ondersteunen uit te sluiten, wordt dit voorkomen.

#content:focus-within

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.

#content {background: white; color: black; width: 500px; max-width: 80vw; margin: 20px auto 0; border: black solid 1px;}

Het element met id="content", maar alleen als dit element of een van de nakomelingen ervan de focus heeft.

Ook dit is bedoeld voor gebruikers van de Tab-toets, net als bij het iets hierboven staande #content:has(:focus-visible). Maar dit is bedoeld voor browsers, die :has() (nog) niet ondersteunen.

In section#content zit onder andere een <h1>. Normaal genomen kunnen alleen knoppen, links, tekstvelden, en dergelijke de focus krijgen. Een <h1> kan normaal genomen geen focus krijgen, maar door het toevoegen van tabindex="0" kan dit hier wel. Dit is het enige element binnen section#content dat de focus kan krijgen. Ook section#content zelf kan niet de focus krijgen.

Doordat de <h1> de focus kan krijgen, kunnen gebruikers van de Tab-toets met behulp van de pijltjestoetsen door de tekst scrollen. Dit wordt duidelijk gemaakt met behulp van een kadertje rondom de tekst dat verschijnt, zodra de <h1> de focus heeft.

Het zou nog mooier zijn als dit kadertje alleen zou verschijnen als de Tab-toets wordt gebruikt, en niet als de <h1> wordt aangeraakt of -geklikt. Dat zou in principe kunnen door bij de <h1> niet :focus, maar :focus-visible te gebruiken. Alleen maakt :focus-within geen verschil tussen :focus en :focus-visible, dus ook bij het aanraken of of -klikken van de <h1> verschijnt het kadertje rondom de tekst. Overigens geen echt probleem, want de kans dat je nu net die <h1> met je vinger of de muis raakt, is vrij klein, en als dat kadertje verschijnt, is dat ook niet zo erg. Het is alleen niet echt heel erg mooi.

Zodra alle browsers het iets hierboven staande #content:has(:focus-visible) ondersteunen, gaat dit wel overal zo werken: ook het aanraken of -klikken van de <h1> wordt dan genegeerd.

outline: blue solid 3px;

Om voor gebruikers van de Tab-toets duidelijk te maken dat de tekst gescrold kan worden, wordt een blauw kadertje rondom de tekst gezet.

h1:focus

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

h1 {margin: 0; font-size: 1.2em;}

h1:focus {outline: blue solid 3px;}

Alle <h1>'s, maar alleen als de <h1> de focus heeft. Er is maar één <h1>: de kop boven de tekst staat erin.

outline: none;

Omdat nu een kadertje rondom de volledige tekst staat, is het kadertje rondom de <h1> boven de tekst niet meer nodig. Dat kadertje was alleen voor browsers die het eerder gebruikte :has() en/of :focus-visible (nog) niet ondersteunen, en ook niet :focus-within.

@media (hover: none) and (pointer: coarse)

De css binnen deze 'media query' staat, geldt alleen voor tablets en smartphones.

Als een scrollbalk naast de tekst verschijnt, is al duidelijk dat er gescrold moet worden om alle tekst te zien. Op tablets en smartphones verschijnt in de regel geen scrollbalk, daarom wordt daar aangegeven dat er meer tekst is door de tekst onderaan te laten vervagen.

De test hier is niet helemaal honderd procent waterdicht, maar zal vrijwel altijd werken. In het ergste geval verschijnen een scrollbalk én een vervaging onderaan, dat is ook geen ramp. Hierover is meer te vinden bij scrollbar-gutter: stable;, dat er in dat geval voor zorgt dat de vervaging niet over het onderste deel van de scrollbalk kom te staan.

@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 veel meer eigenschappen, zoals of er wel of niet gehoverd kan worden, en of de invoermethode ruw of precies is.

(hover: none): het 'primaire invoermechanisme' (in het Engels 'primary input mechanism') kan niet hoveren. Met een muis kun je boven iets gaan hangen, waardoor bijvoorbeeld de kleur van iets kan veranderen. Op een touchscreen kan dat niet. Weliswaar wordt hoveren vaak geïmiteerd, maar dat is geen echt hoveren zoals met een muis. Ook als je een muis aansluit op een tablet of smartphone is het primaire invoermechanisme niet de muis, maar nog steeds het touchscreen.

(hover: none) staat tussen haakjes, dat hoort gewoon zo bij een @media-regel.

and: er komt nog een voorwaarde.

(pointer: coarse): het primaire invoermechanisme moet 'ruw' (in het Engels 'coarse') zijn. Op gevaar af elke manicure en alle liefhebbende ouders nu dodelijk te beledigen: zelfs het meest fijnzinnig behandelde babyvingertje wordt in dit verband als 'ruw' gezien. (Als je je baby naar de manicure brengt, ligt hier mogelijk een nobele taak voor bepaalde instanties. Maar dat terzijde.)

De andere twee waarden zijn 'none' (geen invoermechanisme) en 'fine' (een precies invoermechanisme zoals een muis).

Ook deze voorwaarde staat weer tussen haakjes.

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:

@media (hover:none) and (pointer: coarse) { body {color: silver;} (...) rest van de css voor deze media query (...) footer {color: gold;} }

Voor de eerste css binnen deze media query staat dus een extra {, en aan het eind staat een extra }.

Als op een apparaat niet gehoverd kan worden én de invoermethode is ruw, dan zal dat (vrijwel) altijd een smartphone of tablet zijn. Alleen in dat geval wordt de css binnen deze media query uitgevoerd.

#content p:last-child

Deze selector werkt alleen op smartphones en tablets. Voor andere apparaten is de uitleg hieronder niet van belang.

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

#content p {margin: 0;}

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: alleen het laatste kind. Omdat dit zo vaak voorkomt, is hier een apart sleutelwoord voor: last-child.

#content: het element met id="content". De <section> waarin de tekst en de vervagende gradiënt zitten.

p: alle <p>'s binnen die section#content.

:last-child: alleen de <p>'s die een laatste kind zijn. Dit is de laatste <p> met tekst.

De hele selector in gewone taal: alle <p>'s binnen section#content, die een laatste kind zijn.

Omdat er zes <p>'s als ouder section#content hebben, zou je hier ook p:nth-child(6) kunnen gebruiken. Maar :last-child blijft altijd het laatste kind, ook als er eventueel <p>'s worden toegevoegd of weggehaald.

De in deze selector zittende pseudo-class :last-child kan onverwachte bijwerkingen hebben. In dit geval zit er binnen section#content maar één <div>, waarin een p:last-child zit. Maar als in het voorbeeld binnen section#content nog een ander element met een of meer <p>'s zou zitten, zou deze selector ook voor eventuele <p>'s binnen die <ul> gelden, als ze een laatste kind zijn.

Je kunt dat opvangen door bijvoorbeeld div toe te voegen: #section div p:last-child. Dan geldt de selector alleen voor <p>'s binnen een <sdiv> binnen #content.

padding-bottom: 120px;

Aan de onderkant van de tekst in de laatste <p> een extra grote padding toevoegen. Hierdoor kan de tekst zover naar boven worden gescrold, dat alle tekst boven de vervagende gradiënt kan komen te staan.

#vervaag-buiten

Deze selector werkt alleen op smartphones en tablets. Voor andere apparaten is de uitleg hieronder niet van belang.

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

#vervaag-buiten {display: none; overflow: auto; scrollbar-gutter: stable; margin-top: -120px; pointer-events: none; position: relative;}

Het element met id="vervaag-buiten". De <div> waar de <span> met de vervagende gradiënt in zit.

display: block;

div#vervaag-buiten (en daarmee ook de erin zittende <span>) zijn eerder bij #vervaag-buiten met display: none; verborgen. De opmaak voor beide is eerder al opgegeven, dus hier hoeven ze alleen zichtbaar te worden gemaakt op tablets en smartphones.