Skip links en inhoudsopgave

Uitleg met clip-path en drop-shadow() gemaakte pijl naar rechts. Bij aanraken, hoveren of tabben veranderen kleuren en richting

Laatst aangepast: .

Met clip-path gemaakte pijl met schaduw.

Korte omschrijving

Met behulp van clip-path en filter: drop-shadow() wordt een pijl naar rechts gemaakt. Bij aanraken of -klikken van, hoveren over of tabben naar de pijl veranderen richting en kleuren.

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

Er worden twee <div>'s gebruikt: één voor de basisvorm van de pijl, en één voor de schaduwen. (Er is nog een derde buitenste <div>, maar die wordt alleen gebruikt om de kleuren beter uit te laten komen. En omdat-ie er toch is ook voor centreren en zo.)

De <div> met de basisvorm van de pijl staat binnen de <div> met de schaduw:

<div id="schaduw"> <div id="kern"></div> </div>
De pijl bij openen van de pagina.

Op de afbeelding wordt het middelste witte deel gevormd door div#kern, de buitenste rode en blauwe delen zijn schaduwen die bij div#schaduw horen.

Eerst de binnenste <div>, div#kern.

Deze <div> is een doodgewone <div> met een breedte, een hoogte en een witte achtergrondkleur. Breedte en hoogte zijn opgegeven in vw, waardoor de <div> zich aanpast aan de breedte van het venster van de browser.

De pijlvorm is met behulp van clip-path gemaakt. En dat is ook gelijk de reden dat er een tweede <div> voor de schaduw nodig is.

De echte grootte van div#kern zichtbaar gemaakt.

Op de afbeelding is met de stippellijn de werkelijke grootte van div#kern aangegeven. (Het blauw is even veranderd in cyaan, omdat de stippellijn anders nauwelijks is te zien.)

De witte vorm is met behulp van clip-path gemaakt. Het is een polygoon, een veelhoek, met in dit geval zes hoeken. Het enige wat clip-path feitelijk doet, is het doorzichtig maken van alles wat buiten de polygoon ligt. Het wit wat je ziet is het deel van de achtergrond dat binnen de polygoon valt.

Omdat alles buiten de polygoon doorzichtig wordt, zie je ook de rode en blauwe kleur niet, als je die bij div#kern zelf zou aanbrengen. Die worden evengoed doorzichtig. Daarom worden rood en blauw met behulp van een extra div#schaduw aangebracht. Omdat bij div#schaduw geen clip-path wordt gebruikt, is alles daar gewoon normaal zichtbaar.

De pijl in de clip-path editor in Firefox.

De hoeken van de met clip-path gemaakte polygoon worden opgegeven met voor elke hoek twee coördinaten. Op de afbeelding hiernaast zijn die zichtbaar gemaakt, zoals ze eruit zien in de editor in het ontwikkel­gereedschap van Firefox. Je geeft voor elk punt de coördinaten op (horizontale en verticale afstand tot linker- en bovenkant van het element). De browser maakt vervolgens de verbinding tussen die punten, en maakt alles buiten die punten doorzichtig.

Omdat alle maten bij clip-path in procenten zijn opgegeven, is het relatief makkelijk een goede verdeling te krijgen. Bovendien blijft die verdeling bestaan bij een andere grootte van de <div>: 25% vanaf de bovenkant is bij élke grootte 25% vanaf de bovenkant. Als je als eenheid een absolute eenheid als px zou gebruiken, zouden de verhoudingen veranderen bij een andere grootte van de <div> met de pijl: 100 px vanaf de bovenkant is altijd 100 px vanaf de bovenkant, ongeacht de grootte van de <div>.

Goed, we hebben nu het binnenste witte deel van de oorspronkelijke pijl. En omdat clip-path alles buiten dat witte deel doorzichtig maakt, moeten de rode en blauwe schaduw bij een div#schaduw, de ouder van div#kern, worden opgegeven. Dat gebeurt met de eigenschap filter: drop-shadow().

Een filter voert een of andere grafische bewerking uit, zoals het verkleuren van een foto, of het veranderen van kleur in grijstinten. Het filter drop-shadow() maakt een soort spiegel-afbeelding van de inhoud van div#schaduw: de schaduw. Daarbij wordt de omtrek van de inhoud van div#schaduw gevolgd: in dit geval is dat het door div#kern gevormde witte vlak.

Je kunt de plaats en de breedte van de schaduw aangeven. Dat is hier ook weer grotendeels gedaan met de eenheid vw, net zoals de meeste andere maten. Hierdoor krijg je op 'n mobieltje geen schaduw die eigenlijk op een breedbeeldscherm hoort, en omgekeerd.

In dit geval worden aan div#schaduw twee drop-shadows gegeven. Eentje wordt naar links verplaatst en zorgt voor de rode kleur, en eentje wordt naar rechts verplaatst voor de blauwe kleur. Eigenlijk is 'schaduw' hier geen goede naam, want er wordt geen schaduw, maar een massieve kleur gebruikt. Het eindresultaat is de pijl met de drie kleuren, die je bij openen van de pagina ziet.

Deze hele exercitie heeft tot nu een dodelijk simpele afbeelding opgeleverd: een pijlvormige figuur met drie kleuren. Zo'n afbeelding die in zelfs het meest simpele grafische programma in acht seconden is gemaakt. Inclusief plaspauze.

Als je dan 'n tweede afbeelding maakt van de veranderde pijl, ben je in zestien seconden klaar. De eerste afbeelding door de tweede vervangen met iets als :focus en het werkt. Alleen wordt de eerste afbeelding dan altijd zonder enige overgang vervangen door de tweede afbeelding. Hooguit zou je met iets als opacity of door te spelen met breedte en hoogte de verandering wat geleidelijker kunnen maken, maar niet erg veel.

Door de afbeelding te maken met behulp van css, kun je de verandering op tal van manieren aanpassen.

De tweede afbeelding wordt op precies dezelfde manier gemaakt als de oorspronkelijke, maar met wat wijzigingen. Die wijzigingen vinden grotendeels gedurende één seconde plaats, waardoor je een heel aparte verandering krijgt.

* de oorspronkelijke twee schaduwen bij div#schaduw (rood en blauw) worden vervangen door vijf smallere schaduwen in andere kleuren;

* de oorspronkelijke witte achtergrondkleur van div#kern verandert in geel;

* de richting van de pijl in div#kern verandert van richting (en daarmee ook de op die pijl gebaseerde schaduwen bij div#schaduw, want die volgen de inhoud van div#schaduw);

Al deze veranderingen vinden gelijktijdig plaats, uitgesmeerd over één seconde, iets wat met twee afbeeldingen nooit is te bereiken.

Maar zoals eerder gezegd: deze constructie is 'n leuke demo, maar enorm belastend voor de computer. Daarom is ze niet echt geschikt om 'in het echt' te gebruiken.

Ten slotte zijn er nog wat kleine aanpassingen nodig voor gebruikers van de Tab-toets en schermlezers, en uiteraard voor het fantastische iOS en iPadOS.

Om de afbeelding ook te kunnen veranderen met de Tab-toets, krijgt div#schaduw het attribuut tabindex="0".

Om de pijl op een touchscreen weer terug te veranderen naar het origineel, moet je het scherm ergens buiten de pijl aanraken. Dit werkt op iOS en iPadOS niet in alle versies in alle browsers. Om het altijd te laten werken, heeft <html> een tabindex="-1" gekregen.

Een gewone <img> wordt herkend door schermlezers, waardoor het bij de afbeeldingen horende alt-attribuut kan worden voorgelezen. Hier zit de afbeelding echter in een gewone <div>. Daarom wordt aan div#schaduw de WAI-ARIA-code role="img" gegeven, met daarbij het attribuut aria-label, met daarin een voor te lezen omschrijving van het geheel.

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

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

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 clip-path gebruikt.

appearance

Op dit moment moet je nog het volgende schrijven:

{-webkit-clip-path: ...; clip-path: ...;}

In de toekomst kun je volstaan met:

{clip-path: ...;}

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 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-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. De meeste schermlezers kunnen dit soort elementen ook gebruiken om snel over de pagina te navigeren.

<main>

Hierbinnen staat de belangrijkste inhoud van de pagina (in dit voorbeeld is dat alleen de pijl met alles erop en eraan).

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.

WAI-ARIA-codes

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

Er worden in dit voorbeeld twee WAI-ARIA-codes gebruikt: role="img" en aria-label.

role="img"

Normaal genomen wordt een afbeelding in de html opgenomen met behulp van <img>. Schermlezers melden dan dat het hier om een afbeelding gaat en lezen de beschrijving van de afbeelding voor, zoals die bij alt is opgegeven.

Hier is de pijl in feite ook een afbeelding. Maar omdat de pijl niet in een <img>-tag, maar in een gewone <div> staat, herkennen schermlezers die niet. Bovendien staat er geen enkele tekst in de <div>, dus zelfs als ze de pijl wel zouden herkennen, valt er weinig voor te lezen. Kortom: schermlezers negeren de pijl volledig. Wat een schermlezers betreft, staan er alleen een paar lege <div>'s in de <html>.

Daarom wordt aan div#schaduw de WAI-ARIA-code role="img" gegeven:

<div id="schaduw" role="img">

Nu herkennen schermlezers de <div> als afbeelding en melden dit ook.

aria-label

Het is natuurlijk hartstikke fantastisch en zo als een schermlezer 'afbeelding' roept, maar als er verder niets meer wordt gemeld, is dat 'n stuk minder fantastisch. Bij een echte afbeelding zou de inhoud van de alt-tag worden voorgelezen, maar die ontbreekt hier. Daarom wordt voor schermlezers nog een aria-label met daarin de omschrijving toegevoegd aan div#schaduw:

<div id="schaduw" tabindex="0" role="img" aria-label="Pijl naar rechts in de kleuren van de Nederlandse vlag. Bij aanraken, hoveren of tabben verandert dit in een pijl naar links met de kleuren van de regenboogvlag.">

De tekst binnen de aanhalingstekens achter aria-label wordt door schermlezers voorgelezen. Van deze tekst zie je verder niets op het scherm, alleen schermlezers gebruiken deze tekst.

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 het element volledig wordt genegeerd door de Tab-toets. Zelfs een link met een negatieve tabindex wordt volledig genegeerd. Normaal genomen heeft een tabindex="-1" maar één nut: je kunt dan met behulp van JavaScript toch focus aan het element geven, zonder dat gebruikers van de Tab-toets erdoor worden gehinderd.

In dit voorbeeld wordt tabindex="-1" voor iets anders gebruikt.

Zoals iets hieronder bij tabindex="0" beschreven, heeft div#schaduw het attribuut tabindex="0" gekregen, waardoor het de focus kan krijgen en de pijl ook door het indrukken van de Tab-toets van uiterlijk kan veranderen.

Op een touchscreen verandert de pijl bij aanraking van uiterlijk. Het is de bedoeling dat de pijl weer terug verandert naar het originele uiterlijk, als je het touchscreen ergens buiten de pijl aanraakt, want door die aanraking verliest div#schaduw de focus weer.

Op iOS en iPadOS gebeurt dat echter niet in alle browsers in alle geteste versies (op Firefox na, daar werkt dit in alle geteste versies). Bij sommige browsers werkt dit in de ene versie wel, in de andere niet. Als het niet werkt, verliest div#schaduw de focus pas weer, als een ander element de focus krijgt. Buiten de <div>'s zijn er echter in dit voorbeeld geen elementen die de focus kunnen krijgen.

Dat betekent dat de gewijzigde pijl in iOS en iPadOS soms, als deze eenmaal is gewijzigd, altijd gewijzigd blijft. Want je kunt de pijl alleen weer terug veranderen, door een ander element de focus te geven. En in dit voorbeeld is die er dus niet.

Daarom wordt aan <html> een negatieve tabindex tabindex="-1" gegeven:

<html lang="nl" tabindex="-1">

Nu reageert ook in deze twee geweldige besturingssystemen het touchscreen altijd, zoals de bedoeling is: bij aanraken buiten de pijl verschijnt de originele pijl weer.

De tabindex wordt aan <html> gegeven, want dan reageert het volledige scherm op een aanraking. Zou je de tabindex aan bijvoorbeeld <body> geven, dan is dat niet zo. <body> wordt normaal genomen niet hoger, dan nodig is om de inhoud ervan weer te geven. Hier zou een tabindex bij <body> dus alleen boven en naast de pijl werken, maar niet onder de pijl. Je zou dit op kunnen lossen door <body> een hoogte te geven, maar dit is veel simpeler en heeft geen bijwerkingen.

Je zou ook tabindex="0" kunnen gebruiken, maar dan wordt div#schaduw ook bezocht, als de Tab-toets wordt ingedrukt. Waardoor gebruikers van de Tab-toets pas bij een tweede keer indrukken van de Tab-toets de pijl zien veranderen, want de eerste Tab wordt zou dan worden gebruikt om, volledig zinloos, <html> de focus te geven.

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 het voorbeeld verandert de pijl, als over div#schaduw wordt gehoverd, of als div#schaduw wordt aangeraakt of -geklikt. De Tab-toets en negeert een gewone <div> normaal genomen volledig, dus gebruikers van de Tab-toets hebben hier niets aan. Daarom wordt aan div#schaduw het attribuut tabindex="0" gegeven:

<div id="schaduw" tabindex="0" (...) rest van de html (...) >

Nu kan div#schaduw de focus krijgen, waardoor selectors met :focus bij div#schaduw gebruikt kunnen worden. Ook bij gebruik van de Tab-toets zal de pijl nu veranderen en, bij nogmaals indrukken van de Tab-toets, weer terug veranderen naar de originele staat.

(Bijkomend voordeel: als op div#schaduw wordt geklikt, blijft de pijl in veranderde staat, ook als de cursor buiten de <div> wordt gebracht, omdat div#schaduw ook bij klikken de focus krijgt. Pas bij klikken buiten de pijl verandert deze weer terug naar het origineel.)

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

In dit voorbeeld wordt een positieve tabindex 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.

Verschillende browsers en verschillende systemen behandelen dit op verschillende manieren. Soms moet je de link twee keer aanraken: bij de eerste aanraking wordt het verkleuren bij :hover afgehandeld, bij de tweede aanraking wordt de link gevolgd.

Soms moet je de link lang aanraken. Je ziet de verkleuring, en na 'n tijdje wordt de link gevolgd. Soms zie je de verkleuring, maar wordt de link gelijk gevolgd. (Dat is vooral geestig als er bij :hover een tekst verschijnt en na 0,2 seconde of zo weer verdwijnt.)

Kortom: een gezellige puinhoop.

In dit voorbeeld reageert div#schaduw op een aanraking (of een klik) én op :hover. Hier levert het echter geen enkel probleem op, omdat in beide gevallen precies hetzelfde gebeurt: de pijl verandert van uiterlijk.

: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. In dit voorbeeld verandert de pijl van uiterlijk, als div#schaduw de focus heeft. Omdat die verandering overduidelijk is, kan hier het kadertje worden weggehaald. Het is foeilelijk en als iemand de verandering van de pijl niet ziet, dan zal dat kadertje ook niet echt meer helpen.

: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 3 oktober 2021.

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.

OS X 10.14.6 ('Mojave') (1680 x 1050 px, resolution: 96 ppi, device-pixel-ratio: 1):
Firefox, Safari, Google Chrome en Microsoft 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.

Tablets

iPad met iOS 12.5.4 (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 15 (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 11 (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 (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.

Als JavaScript is gebruikt, is op de desktop ook getest zonder JavaScript. Op iOS, iPadOS en Android 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. Ook in Edge is niet getest zonder JavaScript, omdat Microsoft het onmogelijk heeft gemaakt dit uit te zetten. Ten slotte 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 Windows7.

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 11

VoiceOver is een in iOS en OS X ingebouwde schermlezer. Er is getest in combinatie met Safari op iOS 12.5.4 en 15, iPadOS 15 en OS X 10.14.6.

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 css

Geen problemen.

Zonder css zie je gewoon helemaal niets, want in de html staan alleen wat lege <div>'s. (Dat maakt deze techniek dus volledig ongeschikt voor het overbrengen van welke informatie dan ook, want zonder css zie je die informatie niet.)

Gebruikers Tab-toets

Geen problemen.

Door het aanbrengen van tabindex="0" bij div#schaduw, verandert de pijl ook van uiterlijk bij gebruik van de Tab-toets.

Tekstbrowsers

Geen problemen.

Lynx laat helemaal niets zien, want er is gewoon niets.

WebbIE zet de tekst binnen aria-label met de beschrijving van de pijl op het scherm.

Schermlezers

Geen problemen.

Schermlezers melden door de toevoeging role="img" dat de pijl een afbeelding is en lezen de tekst met de beschrijving van de pijl binnen aria-label voor. Afhankelijk van de combinatie schermlezer/browser en hoe de schermlezer wordt gebruikt, wordt de veranderde pijl wel of niet getoond. (Bij gebruik van de Tab-toets bijvoorbeeld wordt de verandering gewoon getoond, maar als bijvoorbeeld met een gebaar of toets naar een volgend element wordt gegaan, gebeurt dit niet altijd.)

Zoomen en andere lettergrootte

Geen problemen.

Omdat bijna alle maten op een of andere manier afhankelijk zijn van de breedte van het browservenster, blijven de verhoudingen van de pijl altijd hetzelfde, ongeacht hoe groot of klein wordt gezoomd. En bij gebrek aan tekst zijn er geen andere lettergroottes.

Overige problemen

Deze constructie is volstrekt ongeschikt om welke serieuze informatie dan ook over te brengen.

Als css uitstaat, of als de stylesheet met de css om een of andere reden niet laadt, zie je helemaal niets van de pijl. Serieuze informatie hoort in de html te staan, want die is altijd zichtbaar. (Behalve natuurlijk bij een complete storing of zo, maar daar is niets aan te doen.)

Deze constructie belast het apparaat heel zwaar.

Het is absoluut af te raden deze constructie 'in het echt' te gebruiken. Feitelijk is het vooral voor de lol gemaakt. Het weergeven van de diverse schaduwen in combinatie met alle veranderingen vormt een enorme belasting voor de computer. Bij het testen leidde dat op de goedkopere mobieltjes en tablets met Android tot een nogal schokkerige verandering. Weliswaar alleen in Firefox, maar het geeft wel de zwaarte van de belasting weer.

Wijzigingen

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

:

Nieuw opgenomen.

(Oorspronkelijk stond hier een heel ander voorbeeld: het maken van een schaduw met behulp van een extra afbeelding. Dat doe je tegenwoordig 309 keer zo goed en 6209 zo makkelijk met box-shadow, dus dat was echt volledig verouderd. Vandaar dat het is vervangen.)

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.

schaduw-051-dl.html: de pagina met het voorbeeld.

schaduw-051.pdf: deze uitleg (aangepast aan de inhoud van de download).

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

051-css-dl:

schaduw-051-dl.css: stylesheet voor schaduw-051-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" tabindex="-1">

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.

Het attribuut tabindex="-1" is nodig voor iOS en iPadOS. Als de pijl door een aanraking van uiterlijk is veranderd, moet deze door een aanraking buiten de pijl weer terug veranderen naar de originele staat. Zonder deze toevoeging werkt dit niet in alle browsers op iOS en iPadOS Een uitgebreider verhaal staat bij tabindex="-1".

<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 hij of zij wil zien.

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

Nieuwe sites of pagina's kunnen echter wel rekening houden met de veel kleinere vensters van mobiele apparaten. In dit voorbeeld bijvoorbeeld worden breedte en hoogte van de pijl aangepast aan de breedte van het browservenster.

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

<div id="schaduw" tabindex="0" role="img" aria-label="Pijl naar rechts in de kleuren van de Nederlandse vlag. Bij aanraken, hoveren of tabben verandert dit in een pijl naar links met de kleuren van de regenboogvlag.">

Binnen deze <div> staat alles, wat met de pijl te maken heeft.

Binnen de html staan alleen maar 'n paar lege <div>'s, verder helemaal niets. De pijl wordt volledig met behulp van css gemaakt. Als je over de pijl hovert of deze aanraakt of -klikt, verandert het uiterlijk van de pijl.

Schermlezers en gebruikers van de Tab-toets hebben hier niets aan. Voor een schermlezer valt er niets voor te lezen, en met de Tab-toets kun je niet hoveren of aanraken of zo. Daarom worden een paar extra attributen toegevoegd, die de pijl ook voor schermlezers en Tab-toets toegankelijk maken.

Normaal worden bij indrukken van de Tab-toets alleen elementen als links, tekstvelden, en dergelijke bezocht. Een gewone <div> wordt door de Tab-toets genegeerd. Door de toevoeging van tabindex="0" aan div#schaduw kan de <div> toch de focus krijgen, waardoor ook bij gebruik van de Tab-toets de pijl van uiterlijk verandert (en bij nogmaals indrukken van de Tab-toets weer teruggaat naar de originele staat). Meer hierover is te vinden bij tabindex="0".

De pijl is in feite een afbeelding. Als een afbeelding binnen een <img> staat, wordt deze door schermlezers herkend en gemeld, en de tekst binnen het alt-attribuut van de <img> wordt voorgelezen. Door de toevoeging van role="img" wordt voor schermlezers duidelijk, dat in de <div> eigenlijk een afbeelding staat. De tekst binnen aria-label is ook bedoeld voor schermlezers: deze wordt voorgelezen. Op het scherm merk je verder niets van deze twee attributen. Meer hierover is te vinden bij WAI-ARIA-codes.

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

/* schaduw-051-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.

margin: 0;

Slim om te doen vanwege verschillen tussen browsers.

#wrapper

Het element met id="wrapper". Deze <div> wordt alleen gebruikt om de kleuren van de pijl beter zichtbaar te maken. En omdat 't ding er nou eenmaal toch is, wordt de <div> ook gebruikt om de pijl op de juiste plaats neer te zetten.

background: lightgrey;

Lichtgrijze achtergrondkleur.

width: 90vw; height: 25.5vw;

Breedte en hoogte.

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 90 vw is 90% van de breedte. div#wrapper wordt hierdoor nooit breder dan 90% van de breedte van het venster, ongeacht de breedte van het venster.

Voor de hoogte geldt hetzelfde, maar dan uiteraard in de hoogte. Omdat ook de hoogte op de breedte van het browservenster is gebaseerd, blijft de verhouding tussen breedte en hoogte altijd dezelfde, ongeacht de breedte van het venster.

margin: 30px auto 0;

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

Aan de bovenkant een kleine afstand tot de bovenkant van het browservenster. Onder geen marge.

Links en rechts auto, wat hier hetzelfde betekent als evenveel. Hierdoor staat div#wrapper altijd horizontaal gecentreerd binnen z'n ouder <main>, een blok-element. Een blok-element wordt normaal genomen even breed als z'n ouder. De ouder van <main> is <body>, ook weer een blok-element. <body> wordt daarom normaal genomen ook weer even breed als z'n ouder <html>. Omdat <html> het buitenste element is, wordt dit normaal genomen even breed als het venster van de browser.

Uiteindelijk staat div#wrapper, en daarmee ook alles wat daarin zit, altijd horizontaal gecentreerd binnen het browservenster, ongeacht de breedte van het venster.

padding-top: 3vw; Zonder padding valt afscheiding aan bovenkant weg.

div#wrapper heeft een grijze achtergrond om de kleuren van de pijl beter uit te laten komen. De inhoud van een <div> komt normaal genomen tegen de bovenkant van de <div> te staan. De grijze achtergrond zou daardoor aan de bovenkant wegvallen, zoals op de afbeelding is te zien.

Een kleine padding aan de bovenkant lost dat op.

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 3 vw is 3% van de breedte. De padding past zich hierdoor aan de breedte van het venster aan. Omdat vrijwel alle maten die met de pijl te maken hebben dat doen, blijft de pijl altijd in het midden van de grijze achtergrond van div#wrapper staan.

#schaduw

Het element met id="schaduw". Dit is de <div> die voor de schaduwen zorgt: de rode en blauwe vlakken links en rechts van het witte vlak.

filter: drop-shadow(-22.4vw 0 0 red) drop-shadow(22.4vw 0 0 blue);

Met behulp van de eigenschap filter kun je allerlei grafische bewerkingen uitvoeren. Zoals het lichter of donkerder maken van een foto, kleuren omkeren, en nog veel meer. Welke bewerking wordt uitgevoerd, wordt bepaald door de bij filter gebruikte functie. Hier is dat drop-shadow(). Dit filter maakt een soort schaduw-afbeelding van wat er binnen div#schaduw zit. Tussen de haakjes staan waarden die bepalen hoe die schaduw eruit ziet.

De afmetingen van de pijl worden traploos aangepast aan de breedte van het venster van de browser. Daarom moeten ook de maten van de schaduw worden aangepast, want anders zou je in een smal venster een (veel) te grote schaduw krijgen, en in een breed venster juist een (veel) te kleine. Voor dat aanpassen aan de breedte van het venster wordt weer de eenheid vw gebruikt.

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 10 vw is 10% van de breedte. Omdat alle belangrijke maten bij de pijl in vw zijn opgegeven, blijven de verhoudingen in alle vensters hetzelfde, ongeacht de breedte van het venster.

drop-shadow() zorgt ervoor dat de omtrek van de inhoud van div#schaduw wordt gevolgd. Hier is die inhoud maar heel weinig: alleen div#kern met het witte vlak. Er worden twee schaduwen gemaakt. Een rode schaduw aan de linkerkant van het witte vlak, en een blauwe schaduw aan de rechterkant van het witte vlak. Omdat drop-shadow() de omtrek van het witte vlak volgt, hoeven alleen de plaats en de grootte van de schaduw geregeld te worden om de rood-wit-blauwe pijl te krijgen.

Eerst de eerste drop-shadow():

drop-shadow(-22.4vw 0 0 red)

De eerste waarde -22.4vw is de horizontale verplaatsing van de schaduw ten opzichte van het witte vlak: 22,4 vw naar links. Naar links, want het is een negatieve waarde. Zou er 22.4vw staan, dan zou er naar rechts worden verplaatst.

De echte grootte van div#kern zichtbaar gemaakt.

div#kern met het witte vlak krijgt bij #kern een breedte van 35 vw. Op de afbeelding is met een stippellijn de omtrek van div#kern weergegeven (de blauwe kleur is voor de duidelijkheid wat aangepast). Maar het witte vlak zelf is overal maar 22,5 vw breed, want met behulp van clip-path worden er links en rechts delen van verborgen.

Om de rode schaduw even breed als het witte vlak te laten zijn, moet die dus ook 22,5 vw breed worden, en links van het witte vlak worden neergezet. Dat is precies wat de waarde -22.4vw doet.

Een drop-shadow is even breed als de vorm, waar de schaduw bij hoort. Als je hem helemaal niet zou verplaatsen, zou de schaduw exact achter de vorm komen te staan. Door de rode schaduw 22,4 vw naar links te verplaatsen, komt er een vlak van 22,4 vw links van het witte vlak te staan. Met de vorm van het witte vlak, want het is een schaduw.

Kier tussen rode en witte vlak maakt de overeenkomende vorm zichtbaar.

Op de afbeelding wordt de rode schaduw niet 22,4 vw, maar 25 vw naar links verplaatst. Dan is duidelijk te zien, dat de rode schaduw inderdaad een kopie van het witte vlak is: er zit nu een kier tussen het rode en witte vlak.

Het is ook om zo'n kier te voorkomen dat 22,4 vw wordt verplaatst en geen 22,5 vw, wat precies evenveel zou zijn als de breedte van het witte vlak. Dit kleine verschil zie je niet, maar het voorkomt een mogelijke kier tussen het rode en witte vlak. Door afrondingsverschillen zou die kier anders af en toe zichtbaar zijn. Door het rode vlak feitelijk 0,1 vw onder het witte vlak te laten staan, wordt dat net voorkomen.

(Dat die schaduw even breed is als het origineel is trouwens geen enkele beperking: als je voor de rode schaduw nóg 'n rode schaduw zet, vormen de twee schaduwen samen één brede schaduw. En 'n derde schaduw ervoor zou het nog breder maken. Enzovoort.)

De tweede waarde 0 is de verticale verplaatsing van de schaduw ten opzichte van de pijl: helemaal niets. Het rode vlak staat op precies dezelfde hoogte als het witte vlak. En dit toont gelijk één van de beperkingen van drop-shadow(): de omtrek van de vorm wordt zonder enige fantasie volkomen precies gevolgd, ook als dat niet de bedoeling is.

Naar boven verplaatsen vervormt de vlag.

Op de afbeelding is de rode schaduw 20 px naar boven verplaatst. Omdat de omtrek van het witte vlak wordt gevolgd, levert dat een in dit geval volkomen ongewenst resultaat.

Dit is ook de reden, waarom de Nederlandse vlag en de regenboogvlag zijn omgebouwd van horizontale banen naar verticale: je zou deze verspringingen anders ook bij de pijl krijgen te zien.

(Het zou trouwens wel werken als je in plaats van een pijl een gewone rechthoek gebruikt. Dan kun je gewoon verticaal verplaatsen. Maar ook dan kun je niet horizontaal én verticaal verplaatsen, want ook dan zouden er gaten in de schaduw vallen. Maar de lol was nou net om de pijl ook van richting te laten veranderen, dus een rechthoek was niet bruikbaar.

Je zou dit allemaal op kunnen lossen door (veel) meer <div>'s en dergelijke toe te voegen. Die geef je dan ook een achtergrond en/of schaduw geven en/of je verbergt ze gedeeltelijk met behulp van clip-path. Maar op 'n gegeven moment wordt het dan eenvoudiger om gewoon per post een afbeelding op te sturen, die de bezoeker er dan zelf voor kan houden. Oftewel: je kunt dan beter andere technieken gaan gebruiken.)

De derde waarde 0 bepaalt, over welke afstand de schaduw vervaagt. Hier is die afstand 0 px, waardoor helemaal niet wordt vervaagd. Daardoor is de benaming 'schaduw' hier eigenlijk wat vreemd, want deze 'schaduw' is zo scherp, dat die 'n hoofdrol kan spelen in de thriller De Dodelijke Schaduw.

Rode schaduw met vervagende rand.

Op de afbeelding is de derde waarde veranderd in 50 px. Nu ziet de 'schaduw' er al veel meer uit als een echte schaduw. Maar drop-shadow() is dus ook prima te gebruiken voor vormen met een scherpe rand.

De vierde en laatste waarde red is de kleur: rood. Die waarde is niet verplicht, als je hem weglaat wordt de voorgrondkleur (color) gebruikt. Hier zou dan zwart worden gebruikt.

De tweede drop-shadow:

drop-shadow(22.4vw 0 0 blue)

Als je meerdere filters gebruikt, zoals hier het geval is met twee keer drop-shadow(), wordt eigenschap filter zelf niet herhaald. Latere filters filter zet je gewoon achter de eerdere, zonder komma ertussen.

Deze drop-shadow() werkt precies hetzelfde als de eerste, die gelijk hierboven wordt beschreven. Met twee verschillen.

Omdat de eerste waarde hier 22.4vw is, een positieve waarde, wordt naar rechts verplaatst: het blauwe vlak komt rechts van het witte vlak te staan. En de kleur is hier niet red (rood), maar blue (blauw).

Wat je hier niet ziet: filters worden als het ware gestapeld. Eerst wordt het eerste filter aangebracht. Bij het aanbrengen van het tweede filter, geldt dat tweede filter voor het geheel van het origineel én het eerste filter. Bij een derde filter, geldt dat derde filter voor het geheel van het origineel, het eerste en het tweede filter, enzovoort.

Een tweede drop-shadow vormt ook een schaduw bij de eerste schaduw.

Op de afbeelding is de rode schaduw een heel eind naar links verplaatst. Omdat dit het eerste filter is, wordt deze als eerste getekend. Vervolgens wordt de blauwe schaduw getekend. Nu is zichtbaar, dat deze een kopie is van het witte vlak én van de rode schaduw. In het voorbeeld zie je dat niet, omdat de de helft van het blauwe vlak precies onder het witte vlak komt te staan.

transition: 1s;

Hierboven zijn met filter twee schaduwen aan de inhoud van div#schaduw gegeven. Als je nu bij :hover, :focus, :checked, en dergelijke een andere waarde bij filter opgeeft, zorgt transition ervoor dat die nieuwe filters niet in één keer worden toegepast. Hier worden de twee schaduwen vervangen door vijf schaduwen, die ook nog eens een andere verplaatsing en andere kleuren hebben. Die verandering vindt hier dus geleidelijk aan plaats, niet in één keer.

(Trouwens ongelooflijk dat de browsermakers het voor elkaar hebben weten te krijgen om dit te laten werken. Twee veranderen in vijf, nog los van de andere veranderingen.)

transition brengt een geheel eigen risico met zich mee. In de specificatie staat, welke eigenschappen met behulp van transition kunnen veranderen. Je kunt eventueel bij transition opgeven, voor welke eigenschappen het geldt. Als je bijvoorbeeld top en left beide wilt veranderen bij :checked, kun je bijvoorbeeld aangeven dat de geleidelijke verandering met behulp van transition alleen voor top geldt. left verandert dan gewoon in één keer.

Als je niet opgeeft, voor welke eigenschappen transition geldt, geldt het voor álle eigenschappen die bij :hover, :focus, :checked, en dergelijke worden veranderd. Als daar 'n eigenschap bij zit die op dit moment niet door transition kan worden vertraagd, verandert die gewoon in één keer. Maar als de specificatie of een van de browsermakers de geest krijgt en plotsklaps die eigenschap ook onder transition laat vallen, kan dat tot heel onverwachte resultaten leiden.

Stel dat je een bepaalde eigenschap heel traag wilt veranderen bij :hover en een andere eigenschap flitsend snel. Mogelijk wordt dat flitsend snel dan opeens ook heel traag, als transition in de toekomst die eigenschap ook gaat ondersteunen.

Daarom moet je absoluut zeker weten dat ook in de toekomst geen problemen kunnen ontstaan. Bij twijfel: geef aan welke eigenschap(pen) transition mag aansturen.

Als alle eigenschappen mogen worden vertraagd door transition, is er geen enkel risico voor de toekomst. Dat is hier het geval. Iets verderop bij #schaduw:hover, #schaduw:focus wordt filter veranderd. Verder verandert er niets. In dit geval mag dus alles vertraagd worden veranderd en is er geen risico voor de toekomst. Als dat niet zo zou zijn, moet je opgeven, voor welke eigenschappen transition geldt.

Je kunt transition beperken tot bepaalde eigenschappen door die eigenschappen te noemen, gevolgd door tijdsduur en eventueel vertraging:

transition: width 0.5s;

Nu geldt transition alleen voor width, ongeacht wat er in de toekomst mogelijk nog zou kunnen veranderen. Maar hier is dat dus niet nodig, omdat bij #schaduw:hover, #schaduw:focus alleen filter wordt veranderd.

Bij transition staat maar één waarde: 1s. Als er maar één waarde wordt opgegeven, bepaalt die over hoeveel tijd de verandering wordt uitgesmeerd. Dat is hier tamelijk lang voor een animatie: één seconde. Maar omdat er nogal veel verandert, is dat hier een prima waarde.

Een eventuele tweede waarde, die hier ontbreekt, geeft een eventueel uitstel aan het begin van de verandering aan.

Het is ook nog mogelijk om het verloop van de verandering aan te geven met behulp van sleutelwoorden of getallen. Hiermee kun je bijvoorbeeld aangeven dat de verandering aan het eind snel of juist langzaam moet gaan. Hier werkt de standaardwaarde ease (langzaam beginnen, sneller middendeel, langzaam eindigen) het best.

Bij #schaduw:hover, #schaduw:focus staat precies dezelfde regel: transition: 1s;. De regel daar zorgt ervoor dat de verandering van origineel naar veranderde pijl gedurende één seconde plaatsvindt, dus geleidelijk.

De hier opgegeven regel zorgt ervoor dat de verandering van veranderde pijl terug naar het origineel ook één seconde duurt, dus in beide richtingen gaat de verandering geleidelijk. Als je deze regel hier zou weglaten, zou de verandering van veranderde pijl terug naar origineel in één keer zonder vertraging plaatsvonden.

#kern

Het element met id="kern". De <div> waarin het witte vlak zit (na de verandering het gele vlak). De hierboven bij div#schaduw beschreven rode en blauwe schaduw volgen de vorm van het witte vlak. Hier bepaalt dat witte vlak (en na verandering het gele vlak) grotendeels, hoe de uiteindelijke pijl eruit komt te zien.

background-color: white;

Achtergrondkleur.

Dit levert een doodgewone <div> met witte achtergrond op. De pijlvorm wordt eruit 'gesneden' met behulp van clip-path gelijk hieronder.

-webkit-clip-path: polygon(0 0, 70% 0, 100% 50%, 70% 100%, 0 100%, 35% 50%); clip-path: polygon(0 0, 70% 0, 100% 50%, 70% 100%, 0 100%, 35% 50%);

Hier staat eigenlijk twee keer hetzelfde: clip-path: polygon(0 0, 70% 0, 100% 50%, 70% 100%, 0 100%, 35% 50%);. Waarom dat zo is, is te vinden bij De voorvoegsels -moz,- -ms- en -webkit-.

Bij een eerste blik lijkt dit misschien op een koers voor een ruimteschip of zo. Maar als je het in stukjes hakt, valt dit enigszins mee. Bovendien heb je allerlei handige gereedschappen om te helpen met het vinden van de juiste getallen.

Om te beginnen valt het hele deel voor clip-path: weg. Het deel achter clip-path: is een herhaling van het deel achter ‑webkit-clip-path:. Sommige browsers hebben het voorvoegsel -webkit- nog nodig, vandaar.

Dat halveert de ellende al, dat schiet lekker op.

Met het sleutelwoord polygon wordt aangegeven dat hier een polygoon, een 'veelhoek' wordt gemaakt. Dat is een figuur met een (groot) aantal hoeken. Het kan een onregelmatige figuur zijn, zoals een ster, maar ook een gewoon vierkant of rechthoek. Of, zoals hier, een pijl.

Je geeft aan waar de hoekpunten van de figuur komen, en de browser trekt daar dan rechte lijnen tussen. Van het laatste hoekpunt trekt de browser een rechte lijn naar het eerste hoekpunt, zodat je een gesloten figuur krijgt. Alles buiten die figuur wordt dan verborgen.

(Je kunt met andere sleutelwoorden ook bijvoorbeeld ronde lijnen maken, of een afbeelding gedeeltelijk verbergen, maar dat gebeurt hier allemaal niet.)

Omdat de browser een gesloten veelhoek maakt, maakt de volgorde van de hoekpunten niet uit. Bij een gesloten figuur is er niet echt een eerste of een laatste punt. In het voorbeeld is het eerst opgegeven punt de linkerbovenhoek van het witte vlak. Waarom? Omdat dat toevallig zo ontstond.

De <div> waar het witte vlak in zit, is een doodgewone rechthoek. De breedte is 45 vw: 45% van de breedte van het browservenster. De hoogte is 22,5 vw, 22,5% van de breedte van het venster. De <div>, en daarmee het erin zittende witte vlak, verandert dus mee met de breedte van het venster.

Daarom worden hier de maten van de hoekpunten in procenten opgegeven. De procenten gelden ten opzichte van de <div>, bijvoorbeeld 25% vanaf de bovenkant van de <div>. Als de <div> van grootte verandert, verandert de positie van de hoekpunten nu in dezelfde verhouding mee.

Anders dan bij absolute maten zoals px verandert die 25% mee met de grootte van de <div>: 25% vanaf de bovenkant is áltijd 25%, ongeacht de hoogte van de <div>. Maar als dat beter uitkomt, kun je ook andere eenheden dan procenten gebruiken.

De hoekpunten worden opgegeven met behulp van twee coördinaten, twee getallen. Achter het sleutelwoord polygon worden die tussen haakjes in paren van twee opgegeven, gescheiden door een komma. Het eerste getal van elk tweetal is de horizontale afstand tot de linkerkant van het element (hier div#kern), het tweede getal is de afstand tot de bovenkant van het element.

Het eerste tweetal is hier 0 0 (bij 0 mag je meestal de eenheid weglaten). 0% vanaf de linkerkant van de <div>, dat is hetzelfde als helemaal links. En 0% vanaf de bovenkant, dus helemaal bovenaan.. Dit hoekpunt bepaalt de bovenste linkerhoek.

Op de afbeelding hieronder staat alleen div#kern met het witte vlak (zonder de rode en blauwe schaduw, want die horen bij div#schaduw). Omdat wit op grijs wat onduidelijk is, heeft de <div> daar even een zwarte rand gekregen, die de omtrek van de <div> aangeeft.

Daaronder staat div#kern nogmaals, maar dan zonder achtergrond (zonder het witte vlak), en met hoekpunten en dergelijke. De buitenste zwarte rand op die onderste afbeelding is div#kern. De bij de hoekpunten gebruikte percentages worden met stippellijnen weergegeven, en de hoekpunten zelf zijn weergegeven met getallen in cirkeltjes, in de volgorde waarin ze bij clip-path staan.

Als kind had je van die afbeeldingen met getallen, waartussen je lijntjes moest trekken. Dat leverde dan uiteindelijk een herkenbare tekening op. De afbeelding werkt hetzelfde: als je denkbeeldige rechte lijnen tussen de hoekpunten trekt, zie je het witte vlak. Alles binnen die rechte lijnen is wit, alles buiten die lijnen is doorzichtig, waardoor je daar de grijze achtergrondkleur van div#wrapper ziet.

Alleen het witte vlak van de pijl.

Witte vlak met maatlijnen en dergelijke.

De coördinaten van het eerste hoekpunt zijn 0 0: punt 1 staat helemaal linksboven in de <div>.

De coördinaten van het tweede hoekpunt zijn 70% 0: 70% vanaf links en aan de bovenkant van de <div>. Dit levert een rechte lijn tussen punt 1 en punt 2 op.

De coördinaten van het derde hoekpunt zijn 100% 50%: helemaal rechts en verticaal halverwege de <div>. Dit levert een schuine lijn tussen punt 2 en punt 3 op.

De coördinaten van het vierde hoekpunt zijn 70% 100%: 70% vanaf links en helemaal aan de onderkant van de <div>. Dit levert een schuine lijn tussen punt 3 en punt 4 op.

De coördinaten van het vijfde hoekpunt zijn 0 100%: helemaal links aan de onderkant van de <div>. Dit levert een horizontale lijn tussen punt 4 en punt 5 op.

De coördinaten van het zesde en laatste hoekpunt zijn 35% 50%: 35% vanaf de linkerkant en verticaal halverwege de <div>. Dit levert een schuine lijn tussen punt 5 en punt 6 op.

En omdat punt 6 het laatste opgegeven hoekpunt is, trekt de browser nog een schuine lijn tussen punt 6 en punt 1. Waarmee de polygoon gesloten is.

Dit is natuurlijk allemaal fantastisch en geweldig en zo en wat kun je er 'n mooie dingen mee doen, maar hóé doe je dat? Je kunt gewoon in het wilde weg met 'n serie getallen beginnen. Maar als je nog nooit met clip-path hebt gewerkt, moet je dat alleen doen, als je verzekerd ben voor opname in een rusthuis.

Gelukkig zijn er hulpmiddelen. Op de pagina met links zijn onder CSS → Online uitproberen, code genereren, en dergelijke links naar online-editors voor clip-path te vinden.

In Firefox is in de ontwikkelgereedschappen een uitermate handige editor voor clip-path en shape-outside ingebouwd. Als je een element met clip-path of shape-outside selecteert en op de veelhoek rechts klikt, worden bij dat element de hoekpunten zichtbaar. Die punten kun je vervolgens verslepen, waarbij het uiterlijk van het element en de bijbehorende css mee veranderen. Als je dubbelklikt op een lijn van de editor, verschijnt een nieuw hoekpunt. En als je op 'n bestaand punt dubbelklikt, verdwijnt dit. Echt ongelooflijk handig.

Die pijlen zijn als volgt ontstaan. Gewoon lukraak beginnen had weinig zin. Ook niet met de editor in Firefox, want je moet íéts van 'n begin hebben. Als je zomaar begint met het maken van 'n pijl, heb je grote kans dat er 'n tulpenbol of 'n knolraap blijkt te verschijnen. Of zoiets.

Om te beginnen is 'n online-editor 'n basisvorm uitgezocht, die enigszins op een pijl lijkt. Die was vervolgens redelijk overzichtelijk goed te krijgen met de editor in Firefox. Het handige daarvan is, dat je gelijk op de pagina zelf de veranderingen ziet.

Die editor in Firefox levert echter geen mooie 70% op, maar 70,87%. Of zoiets. Dus daarna zijn de percentages nog handmatig op elkaar afgestemd. Dat is redelijk simpel te doen.

Bij #schaduw:hover #kern, #schaduw:focus #kern wordt clip-path veranderd, waardoor de pijl niet meer naar rechts, maar naar links wijst. De witte achtergrondkleur wordt daar ook in geel veranderd. De getallen bij de coördinaten zijn hetzelfde, alleen staan ze op andere plaatsen. Dat levert de verandering van richting op, en ook wordt het gele vlak hierdoor maar half zo breed als het witte vlak van de originele pijl.

Hieronder staat de tekening met de maten en dergelijke, zoals die na de verandering zijn.

Witte vlak met maatlijnen en dergelijke na de verandering.

De na de verandering bij deze tekening horende waarden bij clip-path zijn:

clip-path: polygon(35% 0, 70% 0, 35% 50%, 70% 100%, 35% 100%, 0 50%);

Waarbij het eerste paar weer bij de '1' hoort, het tweede paar bij de '2', enzovoort.

width: 35vw;

Breedte.

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 35 vw is 35% van de breedte. De <div> met het witte vlak wordt hierdoor nooit breder dan 35% van de breedte van het venster, ongeacht de breedte van het venster. Hierdoor is er altijd voldoende ruimte voor de rode en blauwe schaduwen opzij van het witte vlak.

Omdat vrijwel alle maten in de eenheid vw zijn opgeven, blijven de verhoudingen van de pijl altijd hetzelfde, ongeacht de breedte van het browservenster.

height: 22.5vw;

Voor de hoogte geldt hetzelfde als voor de breedte gelijk hierboven, maar dan uiteraard in de hoogte. Omdat ook de hoogte op de breedte van het browservenster is gebaseerd, blijft de verhouding tussen breedte en hoogte altijd dezelfde, ongeacht de breedte van het venster.

margin: 0 auto;

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

Boven en onder geen marge.

Links en rechts auto, wat hier hetzelfde betekent als evenveel. Hierdoor staat div#kern (en alles daarin) altijd horizontaal gecentreerd binnen z'n ouder div#schaduw.

Bij #wrapper is div#wrapper horizontaal gecentreerd binnen het venster van de browser. Hierdoor staat uiteindelijk div#kern ook horizontaal gecentreerd binnen het venster. En daarmee ook de op het witte vlak in div#kern gebaseerde rode en blauwe schaduw.

(Normaal genomen zou een marge niet tot de essentiële css worden gerekend. Hier is dat echter wel zo. Een met filter gemaakte drop-shadow neemt geen ruimte in. Wat betreft de rest van de pagina, bestaat die schaduw helemaal niet, net zoals met bijvoorbeeld position: absolute; het geval is. Andere elementen kunnen er dus door worden verborgen. In dit geval zou een groot deel van de schaduwen links van het witte (of na verandering gele) vlak daardoor links buiten het browservenster verdwijnen. Door horizontaal te centreren wordt dat voorkomen.)

transition: 1s;

Hierboven is bij background-color een achtergrondkleur opgegeven, en bij clip-path een pijlvorm naar rechts. Bij #schaduw:hover #kern, #schaduw:focus #kern wordt dit veranderd in een gele achtergrond een pijlvorm naar links.

De eigenschap transition zorgt ervoor dat die verandering niet in één keer plaatsvindt, maar geleidelijk. Als de achtergrondkleur van wit veranderd naar geel, vindt die verandering geleidelijk aan plaats. (De browser kan dat omdat elke kleur wordt vertaald naar getallen. En in het veranderen van getallen is een browser erg goed. Die veranderende getallen zien wij dan weer als een veranderende kleur.)

Bij transition staat maar één waarde: 1s. Als er maar één waarde wordt opgegeven, bepaalt die over hoeveel tijd de verandering wordt uitgesmeerd. Dat is hier één seconde. Dat is vrij lang voor 'n animatie, maar omdat hier nogal veel verandert, werkt dat hier prima. Een eventuele tweede waarde, die hier ontbreekt, geeft een eventueel uitstel aan het begin van de verandering aan.

Het is ook mogelijk om het verloop van de verandering aan te geven met behulp van sleutelwoorden of getallen. Hiermee kun je bijvoorbeeld aangeven dat de verandering aan het eind snel of juist langzaam moet gaan. Hier werkt de standaardwaarde ease (langzaam beginnen, sneller middendeel, langzaam eindigen) het best.

transition brengt een geheel eigen risico met zich mee. In de specificatie staat, welke eigenschappen met behulp van transition kunnen veranderen. Je kunt eventueel bij transition opgeven, voor welke eigenschappen het geldt. Als je bijvoorbeeld top en left beide wilt veranderen bij :checked, kun je bijvoorbeeld aangeven dat de geleidelijke verandering met behulp van transition alleen voor top geldt. left verandert dan gewoon in één keer.

Als je niet opgeeft, voor welke eigenschappen transition geldt, geldt het voor álle eigenschappen die bij :hover, :focus, :checked , en dergelijke worden veranderd. Als daar 'n eigenschap bij zit die op dit moment niet door transition kan worden vertraagd, verandert die gewoon in één keer. Maar als de specificatie of een van de browsermakers de geest krijgt en plotsklaps die eigenschap ook onder transition laat vallen, kan dat tot heel onverwachte resultaten leiden.

Stel dat je een bepaalde eigenschap heel traag wilt veranderen bij :hover en een andere eigenschap flitsend snel. Mogelijk wordt dat flitsend snel dan opeens ook heel traag, als transition in de toekomst die eigenschap ook gaat ondersteunen. Daarom moet je absoluut zeker weten dat ook in de toekomst geen problemen kunnen ontstaan. Bij twijfel: geef aan welke eigenschap(pen) transition mag aansturen.

Als alle eigenschappen mogen worden vertraagd door transition, is er geen enkel risico voor de toekomst. Dat is hier het geval. Iets verderop bij #schaduw:hover #kern, #schaduw:focus #kern worden background-color en filter veranderd. Verder verandert er niets. In dit geval mag dus alles vertraagd worden veranderd en is er geen risico voor de toekomst. Als dat niet zo zou zijn, moet je opgeven, voor welke eigenschappen transition geldt.

Je kunt transition beperken tot bepaalde eigenschappen door die eigenschappen te noemen, gevolgd door tijdsduur en eventueel vertraging:

transition: width 0.5s;

Nu geldt transition alleen voor width, ongeacht wat er in de toekomst mogelijk nog zou kunnen veranderen. Maar hier is dat dus niet nodig, omdat bij #schaduw:hover #kern, #schaduw:focus #kern alleen background-color en filter worden veranderd.

Bij #schaduw:hover #kern, #schaduw:focus #kern staat precies dezelfde regel: transition: 1s;. De regel daar zorgt ervoor dat de verandering van originele pijl naar veranderde pijl gedurende één seconde plaatsvindt, dus geleidelijk.

De hier opgegeven regel zorgt ervoor dat de verandering van veranderde pijl terug naar originele pijl ook één seconde duurt, dus in beide richtingen gaat de verandering geleidelijk. Als je deze regel hier zou weglaten, zou de verandering van veranderde pijl terug naar originele pijl in één keer zonder vertraging plaatsvonden.

#schaduw:hover, #schaduw: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.

#schaduw {filter: drop-shadow(-22.4vw 0 0 red) drop-shadow(22.4vw 0 0 blue); transition: 1s;}

Het element met id="schaduw", maar alleen als hierover wordt gehoverd of als het de focus heeft.

div#schaduw zorgt voor alle kleuren bij de veranderde vlag, behalve de gele (dat is de achtergrond van div#kern).

De selector met :hover werkt altijd, als je met een muis over een <div> hovert. Op touchscreens werkt dit ook, want die behandelen :hover ongeveer als een aanraking. Maar een <div> kan normaal genomen geen focus krijgen. Door echter het attribuut tabindex="0" toe te voegen kan dit wel. Hierdoor werkt klikken op de <div> ook, en ook door het indrukken van de Tab-toets kan de <div> nu de focus krijgen. Meer hierover is te vinden bij tabindex="0".

filter: drop-shadow(11.2vw 0 0 green) drop-shadow(-11.2vw 0 0 orange) drop-shadow(11.2vw 0 0 indigo) drop-shadow(-11.2vw 0 0 red) drop-shadow(11.2vw 0 0 violet);

Bij openen van de pagina bestaat de pijl uit links een rood vlak, in het midden een wit vlak en rechts een blauw vlak. Het rode en blauwe vlak zijn eigenlijk schaduwen, die met behulp van drop-shadow() bij #schaduw zijn gemaakt. Door de manier waarop ze worden weergegeven zien ze er niet als schaduwen uit, maar als massieve vlakken. Maar het rode en blauwe vlak zijn technisch gezien wel degelijk schaduwen van het witte vlak.

Hier worden de rode en blauwe schaduw vervangen door vijf andere schaduwen. De weergave werkt op precies dezelfde manier als is beschreven bij filter: filter: drop-shadow(-22.4vw 0 0 red) drop-shadow(22.4vw 0 0 blue);. Hieronder worden alleen de veranderingen beschreven.

Er zijn vier verschillen met de eerdere twee schaduwen:

* geen twee, maar vijf schaduwen;

* andere kleuren;

* de richting van de pijl is niet naar links, maar naar rechts;

* de breedte van de schaduwen is gehalveerd.

De verandering van twee naar vijf schaduwen met andere kleuren is een rechtstreeks gevolg van wat hier is opgegeven bij filter: vijf keer een drop-shadow() met vijf verschillende kleuren.

Een drop-shadow() volgt de vorm van de inhoud van het element. De schaduwen zijn opgegeven bij div#schaduw, de inhoud daarvan is div#kern met het witte vlak. Iets verderop bij #schaduw:hover #kern, #schaduw:focus #kern wordt met behulp van clip-path het uiterlijk van het witte vlak veranderd: de punt staat niet meer naar rechts, maar naar links gericht. Omdat de schaduwen de vorm van het witte vlak volgen, veranderen die automatisch mee met de richting van het witte vlak. Daar hoef je verder niets voor te veranderen.

Ook de breedte van deze vijf schaduwen is anders dan die van de twee originele schaduwen: half zo breed. Bij openen van de pagina is het witte vlak overal 22,5 vw breed. Daarom worden de rode en blauwe schaduw 22,4 vw naar links en naar rechts verplaatst (0,1 vw minder dan zou kunnen om een mogelijke kier bij zoomen en dergelijke te voorkomen). Hierdoor zie je drie even brede banen (dat verschil van 0,1 vw zie je niet).

Iets verderop bij #schaduw:hover #kern, #schaduw:focus #kern wordt met behulp van clip-path de breedte van het witte vlak gehalveerd: van 22,5 vw naar 11,25 vw (kan 'n pixel schelen, voor de preciezen onder ons). Daarom is de horizontale verplaatsing van de schaduwen hier ook gehalveerd: geen 22,4 vw, maar 11,2 vw. Afhankelijk van waar ze komen te staan is dat naar links of naar rechts.

outline: none;

Omdat div#schaduw een tabindex="0" heeft gekregen, kan deze <div> de focus krijgen: een kadertje dat aangeeft, waar een gebruiker van de Tab-toets op de pagina zit. Dat is belangrijk, want anders zou de gebruiker niet weten welke link bijvoorbeeld wordt gevolgd bij het indrukken van Enter. Daarom mag dat kadertje nooit zonder meer worden verwijderd.

Het kadertje wordt gevormd door de eigenschap outline. Hier wordt die verwijderd, waardoor het (foeilelijke) kadertje verdwijnt. Hier is dat geen probleem, want dat div#schaduw de focus heeft, wordt al duidelijk uit het veranderen van de pijl.

transition: filter 1s;

Hier gelijk boven wordt filter: drop-shadow() veranderd, als div#schaduw de focus heeft, wordt aangeraakt of -geklikt, of als erover wordt gehoverd. Normaal genomen vindt zo'n verandering in één keer plaats.

Deze regel zorgt ervoor dat de verandering geleidelijk aan verloopt: gedurende één seconde. Een uitgebreidere beschrijving staat bij transition: 1s;.

#schaduw:hover #kern, #schaduw:focus #kern

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.

#kern {background-color: white; -webkit-clip-path: polygon(0 0, 70% 0, 100% 50%, 70% 100%, 0 100%, 35% 50%); clip-path: polygon(0 0, 70% 0, 100% 50%, 70% 100%, 0 100%, 35% 50%); width: 45vw; height: 22.5vw; margin: 0 auto; transition: 1s;}

Doe iets met het element met id="kern" dat binnen het element met id="schaduw" ligt, maar alleen als over #schaduw wordt gehoverd, of als #schaduw de focus heeft.

div#schaduw zorgt voor de schaduwen bij de veranderde pijl. De binnen div#schaduw zittende div#kern zorgt voor het origineel voor de schaduwen bij de veranderde pijl: het gele vlak.

De selector met :hover werkt altijd, als je met een muis over een <div> hovert. Op touchscreens werkt dit ook, want die behandelen :hover ongeveer als een aanraking. Maar een <div> kan normaal genomen geen focus krijgen. Door echter het attribuut tabindex="0" toe te voegen kan dit wel. Hierdoor werkt klikken op de <div> ook, en ook door het indrukken van de Tab-toets kan de <div> nu de focus krijgen. Meer hierover is te vinden bij tabindex="0".

background-color: yellow;

Bij openen van de pagina heeft div#kern een witte achtergrondkleur, die wordt hier veranderd in een gele. Nu heb je 'n doodgewone <div> met een gele achtergrond. De pijlvorm wordt eruit 'gesneden' met behulp van clip-path gelijk hieronder.

-webkit-clip-path: polygon(35% 0, 70% 0, 35% 50%, 70% 100%, 35% 100%, 0 50%); clip-path: polygon(35% 0, 70% 0, 35% 50%, 70% 100%, 35% 100%, 0 50%);

Hier staat eigenlijk twee keer hetzelfde: clip-path: polygon(35% 0, 70% 0, 35% 50%, 70% 100%, 35% 100%, 0 50%);. Waarom dat zo is, is te vinden bij De voorvoegsels -moz,- -ms- en -webkit-.

Met clip-path wordt bepaald, welk deel van de gele achtergrond van div#kern wordt verborgen. Door het doorzichtig maken van delen van de gele achtergrond ontstaat de pijlvorm. In dit geval wordt een polygoon, een veelhoek, gemaakt. Alles buiten die polygoon wordt doorzichtig gemaakt.

De hoekpunten van de polygoon worden in paren van twee opgegeven, gescheiden door een komma. het eerste getal geeft de horizontale verplaatsing vanaf de linkerkant van div#kern aan, het tweede getal de verticale verplaatsing vanaf de bovenkant van de <div>.

Een uitgebreide beschrijving hiervan staat bij -webkit-clip-path: polygon..., inclusief een tekening van de veranderde pijl, want het is overzichtelijker alles op één plaats bij elkaar te zetten.

transition: 1s;

Hier gelijk boven wordt clip-path veranderd, als div#schaduw de focus heeft, wordt aangeraakt of -geklikt, of als erover wordt gehoverd. Iets hoger wordt de witte achtergrond van div#kern veranderd in geel. Normaal genomen vindt zo'n verandering in één keer plaats.

Deze regel zorgt ervoor dat deze veranderingen geleidelijk aan verlopen: gedurende één seconde. Een uitgebreidere beschrijving staat bij transition: 1s;.