Skip links en inhoudsopgave

Uitleg pop-up met smileys

Laatst aangepast:

Korte omschrijving

Bij hoveren over, aanraken of aanklikken van, of tabben naar een vraagteken opent een pop-up met smileys.

BELANGRIJK

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

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

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

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

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

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

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

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

Opmerkingen

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

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

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

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

Achterliggend idee

Voor pop-ups wordt vaak JavaScript gebruikt. Maar heel vaak kan dit ook prima met alleen css. Voordelen zijn dat je geen JavaScript hoeft te leren en dat het ook nog werkt als JavaScript uitstaat.

Een pop-up verschijnt meestal als reactie op een handeling van de gebruiker, bijvoorbeeld ergens over hoveren, iets aanraken of ergens op klikken. In dit geval verschijnt de pop-up door aanraken of aanklikken van, hoveren over of tabben naar het vraagteken.

Dit vraagteken is eigenlijk een <label> met id=”vraagteken”, die bij een radioknop met id=”open” hoort. Zodra de <label> wordt aangeraakt of aangeklikt, wordt de radioknop geselecteerd. De <label> staat een eindje na de radioknop met id=”open” in de html. De pop-up zelf staat in een <label> met id=”pop-up”, die bij een radioknop met id=”sluiten” hoort. Door aanraken of aanklikken van de pop-up, wordt radioknop #sluit geselecteerd. En omdat #sluit in dezelfde groep radioknoppen als #open zit, is daarmee #open automatisch niet meer geselecteerd en zal de pop-up sluiten.

Door beide <label>’s in de html na de <input>’s te zetten, kan de pop-up worden getoond met behulp van de selector open:checked ~ #pop-up: doe iets met label#pop-up als input#open is geselecteerd. Het op deze manier gebruiken van <input> en <label> staat bekend als de ’checkbox hack’.

Omdat de pop-up in een <label> zit die bij radioknop input#sluit hoort, wordt input#sluit geselecteerd bij aanraken of aanklikken van de pop-up. Daardoor is radioknop input#open niet meer geselecteerd en sluit de pop-up weer.

Bij openen van de pop-up wordt dus in feite een <label> zichtbaar gemaakt. Binnen die <label> zitten alle afbeeldingen. Er zit echter nog een extra <span> in, die bij openen van de pop-up naast het <label> met het vraagteken wordt gezet. In deze <span> zit een sluitkruisje. Hierdoor is de pop-up ook te sluiten door aanraken of aanklikken van het sluitkruisje.

Dit sluitkruisje is eigenlijk niet nodig, maar het is niet zonder meer duidelijk dat je de pop-up kunt aanraken of -klikken om deze weer te sluiten.

Door label#open, het vraagteken, ook gevoelig te maken voor hoveren, opent de pop-up ook als met de cursor over het vraagteken wordt gehoverd.

Door het toevoegen van een extra <span tabindex="0"> wordt de pop-up ook zichtbaar voor gebruikers van de Tab-toets. Meer hierover is te vinden bij Tabindex.

In de pop-up zitten in totaal 67 smileys. Elk van die smileys is een aparte afbeelding, een <img>. Dat zijn 67 aanroepen naar de server. Althans: dat was in de vorige versie nog zo. Dat aantal aanroepen is in deze versie terug gebracht tot 42. Dat zijn er nog steeds heel veel, dus met dit soort pop-ups moet je echt heel zuinig zijn, of ze veel kleiner maken.

De smileys zijn in twee groepen te verdelen: bewegende en niet-bewegende. De bewegende smileys zijn nog steeds afzonderlijke <img>’s. Dus voor elke bewegende smiley is nog steeds een aanroep naar de server nodig. Omdat er 41 bewegende smileys zijn, zijn daar 41 aanroepen voor nodig.

Naast de bewegende smileys zijn er nog 26 die niet bewegen. Deze kunnen probleem samen op één grote achtergrond-afbeelding worden gemonteerd (een zogenaamde ’sprite’). Dat spaart 25 aanroepen naar de server uit. Op de afbeelding is die achtergrond-afbeelding te zien. Meer hierover is te vinden bij #gif-1.

In de pop-up worden de bewegende smileys gewoon als <img> neergezet. Daartussen komen <span>’s van de juiste maten, die elk een niet-bewegende smiley als achtergrond-afbeelding neerzetten. Met behulp van background-position wordt gezorgd dat de juiste smiley op de juiste plaats komt te staan.

Voor gebruikers van schermlezers kan het gebruik van radioknoppen e.d. voor een pop-up verwarrend zijn. In dit geval is de pop-up ook redelijk zinloos voor schermlezers, omdat er alleen afbeeldingen in staan. Daarom zijn hier de radioknoppen en <label>’s voor het openen en sluiten van de pop-up voor schermlezers verborgen. Van de pop-up zelf wordt alleen een omschrijving gegeven. Meer hierover bij WAI-ARIA-codes.

(Deze manier van het uitschakelen van een pop-up is uiteraard niet altijd te gebruiken. Als er bijvoorbeeld belangrijke teksten in de pop-up staan, is dit niet de juiste manier.)

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

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

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

De belangrijkste browsers hebben elk een eigen voorvoegsel:

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

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

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

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

In dit voorbeeld worden -webkit-animation, @-webkit-keyframes en transform gebruikt.

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

-webkit-animation en @-webkit-keyframes:

Deze twee eigenschappen worden alleen maar gebruikt om een bug in sommige oudere op webkit gebaseerde browsers te repareren. Daarom hoeft alleen maar op browsers gelet te worden, die op webkit zijn gebaseerd. In dit geval is daarom het volgende voldoende:

{-webkit-animation: ...);}

Hetzelfde geldt voor @keyframes:

{@-webkit-keyframes: ...;}

In nieuwere browsers is deze bug niet meer aanwezig, dus de versie zonder voorvoegsel hoeft in dit geval helemaal niet gebruikt te worden.

(In het algemeen is het een bijzonder slechte gewoonte om van een eigenschap alleen één bepaalde versie te gebruiken. Dit gebeurt nogal eens voor iOS, waarmee Apple actief wordt geholpen om sites e.d. 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 bug gaat. Andere browsers hebben deze css helemaal niet nodig.)

transform:

Op dit moment moet je nog het volgende schrijven:

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

In de toekomst kun je volstaan met:

{transform: ...;}

Inmiddels is de algemene mening dat ’vendor prefixes’, zoals deze voorvoegsels in het Engels heten, geen groot succes zijn. Eén van de grootste problemen: veel sitemakers gebruiken alleen de -webkit-variant. Daar kwamen ze in het verleden nog mee weg, omdat Apple op mobiel zo’n beetje ’n monopolie had. Inmiddels is dat niet meer zo, maar deze gewoonte bestaat nog steeds. Waardoor ’n site alleen in op webkit georiënteerde browsers goed is te bekijken.

Dit is zo’n groot probleem dat andere browsers soms de variant met -webkit- ook maar zijn gaan implementeren, naast de standaard. Want als ’n site het niet goed doet in ’n bepaalde browser, krijgt in de regel niet de site maar de browser de schuld.

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

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

Door het op de goede manier gebruiken van semantische elementen, kunnen zoekmachines, schermlezers, enz. 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, e.d. 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. Dit geeft het begin van de belangrijkste inhoud van de pagina aan.

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

<main role="main">

Inmiddels is dit behoorlijk veranderd. Het advies is nu, om deze speciale toevoeging niet meer te gebruiken, omdat de meeste schermlezers e.d. een <main> inmiddels herkennen.

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: aria-hidden en aria-labelledby.

aria-hidden

Met behulp van aria-hidden="true" kan een deel van de code worden verborgen voor schermlezers e.d., zodat dit niet wordt voorgelezen. Op de normale weergave op het scherm heeft dit verder geen enkele invloed.

In dit geval zijn de <input>’s met radioknoppen en de bijbehorende <label>’s verborgen. Deze worden alleen gebruikt om een pop-up met smileys te openen, wat voor een schermlezer redelijk zinloos is.

Dit verbergen gebeurt bij alle <input>’s en <label>’s op dezelfde manier. Door het toevoegen van aria-hidden="true" wordt het element volledig genegeerd door schermlezers. Twee voorbeelden:

<input id="open" type="radio" name="popje" aria-hidden="true">

<label id="vraagteken" for="open" title="Klik om open te houden" aria-hidden="true">

aria-labelledby

Hierboven is beschreven, hoe de bediening van de pop-up voor schermlezers wordt verborgen. Dat is echter wel heel drastisch, want nu is er geen enkele aanwijzing dat er ’n pop-up bestaat. Daarom is aan de <div>, waar de pop-up e.d. in staan, ook een WAI-ARIA-code toegevoegd:

<div id="wrapper" aria-labelledby="omschrijving">

Hiermee wordt verwezen naar de id van het element, waar een omschrijving van de <div> is te vinden. Dat is hier p#omschrijving. In deze <p> staat de tekst ’Blok met smileys’, zodat gebruikers van een schermlezer in ieder geval weten, wat er in de <div> staat.

Dit is uiteraard niet bruikbaar voor pop-ups met teksten e.d., maar in dit geval volstaat het, omdat het omschrijven van 67 smileys niet heel zinvol is.

Tabindex

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

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

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

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.

Binnen div#wrapper staan twee <input>’s, die normaal ook worden bezocht door de Tab-toets. Maar omdat deze met display: none; zijn verborgen, worden ze genegeerd door de Tab-toets. In dit geval wordt de pop-up geopend en gesloten door het toevoegen van een <span>, waarover hieronder bij Tabindex=”0” meer.

tabindex="-1"

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

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

tabindex="0"

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

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

In dit voorbeeld is aan div#wrapper, waar de hele pop-up e.d. in staan, een extra <span> toegevoegd:

<span tabindex="0"></span>

Door de toevoeging van tabindex="0" kan de <span> focus krijgen bij gebruik van de Tab-toets, terwijl een <span> dat normaal genomen niet kan krijgen.

Als elders op de pagina nog een tabindex wordt gebruikt, kan dat dus problemen geven met de volgorde, zoals iets hierboven beschreven. Op de site zelf, waar ook knoppen voor navigatie op de site aanwezig zijn, gaat het goed. Geen enkele knop heeft daar een tabindex, waardoor in alle browsers eerst de navigatieknoppen en dan pas de <span> wordt bezocht. Precies zoals de bedoeling is. Maar als je wel een tabindex elders op de pagina gebruikt, moet je in zoveel mogelijk browsers op zoveel mogelijk systemen de volgorde bij gebruik van de Tab-toets controleren.

Omdat de <span> verder volkomen leeg is, heeft dit geen enkele invloed op touchscreens, hoveren, e.d.. De <span> is alleen via de Tab-toets te bereiken.

tabindex="..."

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

Muis, toetsenbord, touchpad en touchscreen

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

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

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

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

:hover

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

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

Bij gebruik van een muis zit er een verschil tussen hoveren en klikken, maar op een touchscreen is dat verschil er niet: je raakt een touchscreen aan of niet. Dit levert problemen op in iOS en in Edge op een aanraakscherm.

Op iOS moet het vraagteken twee keer worden aangeraakt, voordat het vraagteken in een sluitkruisje veranderd. Het vraagteken zit in een <label> en reageert dus op aanraking. Maar het reageert ook op :hover. Als een element op een aanraking én op hoveren reageert, interpreteert iOS de eerste aanraking als een hover, en pas de tweede aanraking als een ’klik’. Een klein stukje JavaScript zorgt ervoor dat één aanraking genoeg is. Meer hierover is te vinden bij JavaScript.

In Edge op een touchscreen ontstaat bij aanraking een flikkering, waarover iets hieronder bij :active meer is te vinden.

: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, e.d. Waarna ze vervolgens klikken om de link te volgen, tekst in te voeren, of wat ze ook maar willen doen.

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

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

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 is er helemaal geen kadertje, om de eenvoudige reden dat de <span> die focus kan krijgen helemaal leeg is. Maar hier is dat geen probleem: Het openen van de pop-up is al duidelijk genoeg.

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

Bij hoveren over de <label> met het vraagteken, moet de pop-up openen. Als je in Edge het scherm aanraakt, wordt hoveren kennelijk vertaald naar :active: zolang je het scherm aanraakt, is de pop-up geopend. Als je het scherm loslaat, is de <label> niet meer actief en sluit de pop-up dus. Maar met diezelfde aanraking is de radioknop die de pop-up opent geselecteerd, dus opent de pop-up weer.

Dit levert een flikkering op: de pop-up is open, sluit even en opent gelijk weer. Door hoveren niet te laten werken als de <label> met het vraagteken actief is, wordt dit voorkomen:

#vraagteken:not(:active):hover ~ #pop-up

Dit heeft ook een nadeel: als je met de muis over het vraagteken hovert en er dan op klikt om de pop-up geopend te houden, sluit de pop-up even. Op het moment dat je klikt, is de <label> immers actief. Maar dit zal veel minder vaak voorkomen dan openen via aanraken. Bovendien is dit niet storend, maar lijkt het zo te horen.

De code aanpassen aan je eigen ontwerp

Toegankelijkheid en zoekmachines

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

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

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

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

Enkele tips die helpen bij toegankelijkheid:

Specifiek voor dit voorbeeld

Getest in

Laatst gecontroleerd op 2 januari 2016.

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

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

Dit voorbeeld is getest op de volgende systemen:

Er is steeds getest met de laatste versie van de browsers op de aan het begin van dit hoofdstukje genoemde controledatum, omdat ik geen zin heb om rekening te houden met mensen die met zwaar verouderde browsers surfen. Dat is trouwens vragen om ellende, want updates van browsers hebben heel vaak met beveiligingsproblemen te maken.

Ook op Windows XP kunnen mensen surfen met Firefox, Opera of Google Chrome, dus ook daar zijn mensen niet afhankelijk van Internet Explorer 8. Ik maak één uitzondering: Android browser. Omdat Android vaak niet geüpdatet kan worden, test ik ook nog in oudere versies van Android browser.

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

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

Op de desktop is ook getest, als JavaScript uitstaat. Eventuele problemen staan hierboven bij Toegankelijkheid en zoekmachines onder het kopje Specifiek voor dit voorbeeld. (Op iOS, Android en Windows Phone is niet getest zonder JavaScript, omdat je JavaScript in een toenemend aantal mobiele browsers niet uit kunt zetten. Bovendien is een mobiel apparaat zonder JavaScript niet veel meer dan een duur en groot uitgevallen horloge.)

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

Lynx is een browser die alleen tekst laat zien en geen css gebruikt. Er is getest op Linux.

WebbIE is een browser die gericht is op mensen met een handicap. Er is getest op Windows 7.

NVDA is een schermlezer, zoals die door blinden wordt gebruikt. Er is getest in combinatie met Firefox op Windows 7.

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

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

Als het voorbeeld in deze programma's toegankelijk is, zou het in principe toegankelijk moeten zijn in alle aangepaste browsers en dergelijke. En dus ook voor zoekmachines, want een zoekmachine is redelijk vergelijkbaar met een blinde. Eventuele opmerkingen over de toegankelijkheid specifiek voor dit voorbeeld staan hierboven bij Toegankelijkheid en zoekmachines onder het kopje Specifiek voor dit voorbeeld.

Alleen op de hierboven genoemde systemen en browsers is getest. Er is dus niet getest op bijvoorbeeld 'n Blackberry. De kans is (heel erg) groot dat dit voorbeeld niet (volledig) werkt op niet-geteste systemen en apparaten. Om het wel (volledig) werkend te krijgen, zul je vaak (kleine) wijzigingen en/of (kleine) aanvullingen moeten aanbrengen, bijvoorbeeld met JavaScript.

Er is ook geen enkele garantie dat iets werkt in een andere tablet of smartphone dan hierboven genoemd, omdat fabrikanten in principe de software kunnen veranderen. Dit is anders dan op de desktop, waar browsers altijd (vrijwel) hetzelfde werken, zelfs op verschillende besturingssystemen. Iets wat in Android browser werkt, zal in de regel overal werken in die browser, maar een garantie is er niet. De enige garantie is het daadwerkelijk testen op een fysiek apparaat. En aangezien er duizenden mobiele apparaten zijn, is daar eigenlijk geen beginnen aan.

De html is gevalideerd met de validator van w3c, de css ook. Als om een of andere reden niet volledig gevalideerd kon worden, wordt dat bij Bekende problemen (en oplossingen) vermeld.

Nieuwe browsers test ik pas, als ze uit het bèta-stadium zijn, omdat er anders 'n redelijke kans is dat ik 'n bug zit te omzeilen, die voor de uiteindelijke versie nog gerepareerd wordt. Dit voorbeeld is alleen getest in de hierboven met name genoemde browsers. Vragen over niet-geteste browsers kan ik niet beantwoorden, en het melden van fouten in niet-geteste browsers heeft ook geen enkel nut. (Melden van fouten, problemen, enz. in wel geteste browsers: graag!)

Bekende problemen (en oplossingen)

Waarop en hoe is getest, kun je gelijk hierboven vinden bij Getest in.

Als je hieronder geen oplossing vindt voor een probleem dat met dit voorbeeld te maken heeft, kun je op het forum proberen een oplossing te vinden voor je probleem. Om forumspam te voorkomen, moet je je helaas wel registreren, voordat je op het forum een probleem kunt aankaarten.

Alle browsers

Als de pop-up breder en/of hoger is dan het venster van de browser, verschijnt op de desktop een horizontale of verticale scrollbalk. Op een touchscreen kan de pagina naar beneden of opzij worden verschoven.

Als de pop-up breder is dan het venster, kan in sommige touchscreens niet worden verschoven, maar wordt de pagina verkleind tot de pop-up volledig is te zien. Wat absoluut niet de bedoeling is, omdat de pagina hierdoor heel klein kan worden.

Deze problemen zijn te voorkomen door de pop-up niet breder en/of hoger dan het venster van de browser te maken. Dit is ook precies de reden dat de pop-up in vensters smaller dan 550 px staand wordt weergegeven: dan past de pop-up altijd binnen de breedte van het venster.

Valideren

@webkit-keyframes levert bij validatie een foutmelding op. Omdat de oorzaak van die foutmelding precies bekend is, is dat verder geen probleem.

Wijzigingen

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

:

Nieuw opgenomen.

8 april 2009:

Tekst aangepast aan de nieuw verschenen Internet Explorer 8. De code is niet veranderd.

23 augustus 2010:

7 augustus 2011:

Titel toegevoegd aan link vanwege toegankelijkheid.

2 januari 2016:

Alleen de belangrijkste wijzigingen staan hier, anders is er geen beginnen aan.

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 e.d. 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 e.d.) wordt regelmatig bijgewerkt. Het is daarom niet toegestaan dit voorbeeld (en de bijbehorende uitleg e.d.) op welke manier dan ook te verspreiden, zonder daarbij duidelijk te vermelden dat voorbeeld, uitleg, e.d. 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.

pop-up-018-dl.html: de pagina met het voorbeeld.

pop-up-018.pdf: de uitleg (aangepast aan de inhoud van de download).

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

018-css-dl:

pop-up-018-dl.css: stylesheet voor pop-up-018-dl.html.

018-pics:

afbeeldingen.

De smileys zijn afkomstig van de helaas niet meer bestaande site david.pye.com en mogen vrij worden gebruikt.

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

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

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

<!DOCTYPE html>

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

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

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

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

<html lang="nl">

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

<meta charset="utf-8">

Zorgt dat de browser letters met accenten e.d. 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; e.d.) te gebruiken, maar kun je bijvoorbeeld gewoon ä gebruiken.

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

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

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

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

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

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

Nieuwe sites of pagina’s kunnen echter wel rekening houden met de veel kleinere vensters van mobiele apparaten. Op deze pagina bijvoorbeeld wordt de breedte van de lijst aangepast aan de grootte van het venster, en ook de manier van openen van de officiële teksten wordt aangepast.

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

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

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

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

<p lang="la">

Met het attribuut lang wordt de taal van het element aangegeven. De taal is van belang voor schermlezers, automatisch afbreken, automatisch genereren van aanhalingstekens, juist gebruik van decimale punt of komma, e.d.

’la’ is de code voor Latijn. Tot mijn niet geringe verbazing blijken sommige schermlezers latijn correct voor te lezen. (Voor zover ik dat kan beoordelen, en dat is niet erg ver...)

<div id="wrapper" aria-labelledby="omschrijving">

In de pop-up zitten alleen maar smileys. Weinig zinvol voor schermlezers. Daarom zijn de knoppen e.d. om de pop-up te openen en te sluiten voor schermlezers verborgen.

De <div> waarin de pop-up e.d. zitten krijgt met behulp van het attribuut aria-labelledby wel een verwijzing naar een <p> met id=”omschrijving”, waarin een korte omschrijving zit, zodat schermlezers wel van het bestaan van deze smileys weten.

Meer over WAI-ARIA-codes is te vinden bij WAI-ARIA-codes.

<span tabindex="0"></span>

Deze volledig lege span is aangebracht voor gebruikers van de Tab-toets. Omdat de <span> volledig leeg is, heeft deze geen enkele invloed op touchscreens, hoveren, e.d. Maar met behulp van de aangebrachte tabindex kan de pop-up toch door middel van de Tab-toets worden geopend.

<input id="open" type="radio" name="popje" aria-hidden="true">

<input id="sluit" type="radio" name="popje" aria-hidden="true"> <label id="vraagteken" for="open" title="Klik om open te houden" aria-hidden="true">?</label> <label id="pop-up" for="sluit" title="Klik om te sluiten" aria-hidden="true"></label>

Binnen div#wrapper staan twee <input>’s type=”radio” (radioknoppen) en twee bijbehorende <label>’s. Deze hebben geen nut voor schermlezers, maar kunnen wel heel verwarrend zijn. Met behulp van het attribuut aria-hidden="true" worden ze verborgen voor schermlezers. Meer hierover bij WAI-ARIA-codes.

Bij input worden deze <input>’s verborgen met behulp van display: none;. Hierdoor leveren ze ook geen problemen op voor gebruikers van de Tab-toets.

(In principe zouden ze door het gebruik van display: none; ook genegeerd moeten worden door schermlezers, ook zonder aria-hidden="true" te gebruiken. Maar in het verleden gebeurde dat niet altijd. En omdat veel schermlezers peperduur zijn, zal niet iedereen met de nieuwste versie werken. Voor de zekerheid wordt dus ook aria-hidden gebruikt.)

<span id="gif-1"></span><img src="018-pics/gif2.gif" alt=""><

t/m

<img src="018-pics/gif66.gif" alt=""><span id="gif-67"></span>

Ik geen toe dat deze regel mogelijk ietwat aan de lange kant is. Het zou veel overzichtelijker zijn om de <img>’s en <span>’s op meerdere regels te zetten, afgebroken op logische plaatsen. Of zelfs allemaal op ’n eigen regel.

Edoch, om maar ’ns ’n modern woord te gebruiken.

<img>’s en <span>’s zijn inline-elementen. Als er meerdere inline-elementen achter elkaar staan, zoals hier het geval is, en je zet een inline-element op ’n nieuwe regel, komt daar automatisch een spatie tussen te staan. Dat is vaak wat je wilt, maar hier niet.

Er zijn verschillende trucs om dit te voorkomen. De hele handel op één lange regel zetten is daar eentje van. Dat levert wel een redelijk onleesbaar lange regel op, maar in dit geval is dat geen ramp. Het is nogal simpele code: gewoon 41 <img>’s en 26 <span>’s achter elkaar.

De <img>’s zijn gewoon afbeeldingen. Elke <img> is een bewegende smiley. Binnen de <span>’s staat een achtergrond-afbeelding van een niet-bewegende smiley. Door deze 26 niet-bewegende smileys op één grote afbeelding te monteren, worden 25 aanroepen van de server uitgespaard. Hoe dit precies werkt, staat uitgebreider bij #gif-1.

Normaal genomen worden bij een <img> hoogte en breedte opgegeven, zodat de browser vast ruimte kan reserveren voor de afbeelding:

<img src="018-pics/gif2.gif" alt="" width="45" height="30">

Dat heb ik hier niet gedaan. Bij openen van de pagina worden de afbeeldingen niet getoond, dus er hoeft geen ruimte te worden gereserveerd. De browser heeft tijd genoeg om – achter de schermen – uit te vogelen, hoe groot de afbeeldingen zijn.

Zelfs als de pop-up wordt getoond, hoeft geen ruimte te worden vrijgemaakt, want alle afbeeldingen staan in een <label> die absoluut wordt gepositioneerd: óver de rest van de pagina heen.

In dit geval kun je dus veilig de afmetingen weglaten. Bij 41 <img>’s scheelt dat nogal wat typewerk. (En controleren op typefouten en andere kommer en kwel.)

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

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

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

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

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

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

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

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

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

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

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

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

css voor alle vensters

/* pop-up-018-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.

@-webkit-keyframes bugfix

{from {padding-left: 0;} to {padding-left: 0;}}

Bij #pop-up is en #vraagteken een animatie toegevoegd om een bug in oudere versies van Android browser op te lossen. Die animatie wordt hier opgegeven.

Op een aantal plaatsen wordt in een selector gebruik gemaakt van het teken ~ (de ’general sibling’-selector) om de <label> met de pop-up te openen. Oudere versies van Android browser tonen de <label> met de pop-up echter niet, omdat ze problemen hebben met de ~. Door het toevoegen van een animatie wordt de <label> toch getoond.

Als je nou denkt dat hier niets wordt uitgevoerd, omdat de padding links van 0 px in een padding links van 0 px wordt veranderd, dan heb je helemaal gelijk. Toch neutraliseert deze flauwekul de bug.

Normaal genomen is het een bijzonder slecht idee css te gebruiken voor slechts één weergave-machine: webkit. Maar in dit geval is dit terecht, want de bug zit alleen in op webkit gebaseerde browsers. Het heeft dus geen zin om Internet Explorer of Firefox ook met deze ongein te belasten.

Waarom dit alleen in webkit-browsers werkt, staat bij De voorvoegsels -moz-, -ms- en -webkit-.

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 o.a. de kleur van de tekst.

Hoewel dit de standaardkleur is, geef ik de kleur toch op. Hierboven heb ik een achtergrondkleur opgegeven. Sommige mensen hebben zelf de kleur en/of achtergrondkleur veranderd, bijvoorbeeld omdat ze slecht kleuren kunnen onderscheiden. Als ik nu de achtergrondkleur verander, maar niet de voorgrondkleur, loop ik het risico dat tekstkleur en achtergrondkleur te veel op elkaar gaan lijken.

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

max-width: 900px;

In brede browservensters zou de tekst heel breed kunnen worden, waardoor regels heel lastig te lezen zijn. Door de breedte van <body> te beperken tot maximaal 900 px, wordt dit voorkomen.

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

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

margin: 0 auto;

Omdat voor onder en links geen waarde is 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. <body> staat dus altijd horizontaal gecentreerd binnen z’n ouder, ongeacht de breedte van die ouder.

De ouder van <body> is <html>. <html> is het buitenste element. Omdat <html> geen breedte heeft gekregen, wordt <html> automatisch even breed als het venster van de browser. Omdat <body> horizontaal gecentreerd staat binnen <html>, staat <body> hierdoor automatisch horizontaal gecentreerd binnen het venster, ongeacht de breedte van het venster.

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

Verschillende browsers hebben verschillende standaardinstellingen voor de marge bij <body>. Door de marge zelf op te geven, zijn deze verschillen ook gelijk weggewerkt.

padding: 0;

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

main

Alle <main>’s. Dat is er maar eentje. Hierbinnen staat de belangrijkste content van de pagina.

background: white;

Witte achtergrond.

color: black;

Voorgrondkleur zwart. Dit is o.a. de kleur van de tekst.

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

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

Ik heb dit 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.

display: block;

<main> is een blok-element. Internet Explorer en UC browser kennen dit element niet. Een onbekend element wordt standaard als een inline-element weergegeven. Door hier expliciet te melden dat <main> als blok-element moet worden weergeven, gaat het ook in deze browsers goed.

border: black solid 1px;

Zwart randje.

border-top: none;

Aan de bovenkant geen randje.

padding: 5px;

Kleine afstand tussen tekst binnen en rand rondom <main>.

#wrapper

Het element met id=”wrapper”. Dit is de <div>, waar de pop-up met de bijbehorende knoppen, het vraagteken, e.d. in staan.

float: left;

Zo hoog mogelijk en dan zo ver mogelijk naar links neerzetten. Door de <div> naar links te floaten, komt de inhoud van volgende elementen rechts van de <div> te staan. In dit geval komt hierdoor de tekst uit de <p>’s links van de <div> te staan.

position: relative;

Om nakomelingen te kunnen positioneren ten opzichte van een element, moet dit element zelf zijn gepositioneerd. Omdat verder niets wordt opgegeven bij top e.d., heeft dit geen enkele invloed op div#wrapper zelf.

#omschrijving

Het element met id=”omschrijving”. Dit is de <p> waarbinnen een korte omschrijving van de pop-up voor schermlezers staat: ’Blok met smileys’. Zonder zo’n omschrijving zouden schermlezers de pop-up volledig missen.

position: absolute;

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

left: -20000px;

Links buiten het scherm neerzetten. In deze <p> staat alleen de korte omschrijving van de pop-up voor schermlezers. Voor schermlezers maakt het niets uit dat de <p> buiten het scherm staat. Je zou de <p> ook met display: none; kunnen verbergen, maar dan zouden schermlezers de <p> volledig negeren. Op deze manier zien schermlezers de <p>, maar wordt de lay-out op het scherm niet verstoord.

input

Alle <input>’s. Dat zijn er hier twee met type=”radio”: twee radioknoppen. Ze worden gebruikt om de pop-up te tonen en te verbergen.

display: none;

Het openen en sluiten van de pop-up gebeurt door middel van de <label>’s die bij de <input>’s horen. Daardoor kunnen de <input>’s zelf worden verborgen.

Door ze te verbergen met display: none; worden ze ook bij gebruik van de Tab-toets genegeerd.

#vraagteken

Het element met id=”vraagteken”. Dit is de <label> die bij de radioknop voor het openen van de pop-up hoort. In dit <label> staat het vraagteken.

-webkit-animation: bugfix infinite 1s;

Als de pop-up wordt geopend, wordt het vraagteken doorzichtig. Bij weer sluiten van de pop-up krijgt het vraagteken weer z’n normale kleur terug. In oudere versies van Android browser zit een bug, waardoor dit precies omgekeerd wordt uitgevoerd: bij openen van de pop-up houdt het vraagteken z’n normale kleur, bij sluiten van de pop-up wordt het doorzichtig. Precies omgekeerd aan wat er hoort te gebeuren dus. Eerlijk is eerlijk: dit is een bijzonder knap ontworpen bug! Met behulp van deze regel gedraagt Android browser zich niet meer omgekeerd. Meer hierover bij @-webkit-keyframes bugfix.

background: #ccc;

Achtergrondkleurtje.

color: black;

Voorgrondkleur zwart. Dit is o.a. de kleur van de tekst.

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

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

Ik heb dit 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.

display: block;

Een <label> is een inline-element. Daardoor kunnen eigenschappen als breedte en hoogte niet worden gebruikt. Door er een blok-element van te maken, kunnen deze eigenschappen wel worden gebruikt.

width: 46px;

Breedte. De hoogte wordt iets hieronder bij line-height geregeld.

font-size: 2.5em;

Grote letter.

line-height: 46px;

Regelhoogte.

Iets hierboven is een breedte van 46 px opgegeven. Omdat geen hoogte is opgegeven, wordt #vraagteken even hoog als de hier opgegeven regelhoogte. Waarmee #vraagteken dus een vierkant met zijden van 46 px wordt.

Standaard wordt tekst halverwege de regelhoogte neergezet. Omdat de regelhoogte hier even hoog is als de hoogte van #vraagteken, staat het vraagteken verticaal gecentreerd binnen #vraagteken.

text-align: center;

Tekst horizontaal centreren

margin: 4px 10px 0 0;

4px marge aan de bovenkant en 10 px rechts. Door de marge aan de bovenkant staat de <label> iets lager, wat beter uitkomt ten opzichte van de tekst ernaast. De marge rechts geeft wat afstand tussen de <label> en de tekst ernaast.

border: solid black 1px;

Zwart randje.

#pop-up

Het element met id=”pop-up”. Dit is de <label> die bij de radioknop voor het sluiten van de pop-up hoort. Binnen dit <label> zit de pop-up met de smileys.

-webkit-animation: bugfix infinite 1s;

In oudere versies van Android browser zit een bug, waardoor de <label> met de pop-up niet wordt geopend. Met behulp van deze regel wordt de <label> toch geopend. Meer hierover bij @-webkit-keyframes bugfix.

background: black;

Zwarte achtergrond.

width: 200px; height: 535px;

Breedte en hoogte. In browservensters met een minimale breedte van 550 px worden hoogte en breedte omgedraaid, zodat de pop-up liggend wordt weergegeven. Door de pop-up in smallere vensters staand weer te geven, past hij altijd binnen het venster.

Als de pop-up breder wordt dan het venster, wordt de pagina in sommige browsers verkleind, tot de pop-up binnen het venster past. Hierdoor wordt de pagina veel te klein weergegeven.

position: absolute;

Om #pop-up op de juiste plaats neer te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier div#wrapper.

Een <label> is een inline-element. Daardoor zijn eigenschappen als breedte en hoogte niet te gebruiken. Door de <label> absoluut te positioneren, verandert hij in een soort blok-element en zijn deze eigenschappen wel te gebruiken.

left: -20000px;

Links buiten het scherm parkeren. Om de pop-up zichtbaar te maken, hoeft deze alleen maar binnen het venster van de browser te worden geplaatst.

#pop-up span:first-of-type

De eerste <span> binnen het element met id=”pop-up”. #pop-up is de <label>, waarbinnen de pop-up zit. De eerste <span> binnen dit <label> wordt gebruikt om, als de pop-up zichtbaar is, op de plaats van het vraagteken een sluitkruisje weer te geven.

background: #eee;

Lichtgrijze achtergrond.

De <label> met het vraagteken blijft steeds aanwezig. Het sluitkruisje wordt er gewoon overheen gezet. Zonder achtergrondkleur zou je het vraagteken door het kruisje heen blijven zien, zoals op de afbeelding is te zien.

display: none;

Niet tonen. Pas als de pop-up is geopend, moet het sluitkruisje zichtbaar worden.

width: 46px; height: 46px;

Breedte en hoogte. Dit zijn dezelfde breedte en hoogte als label#vraagteken heeft gekregen, zodat dit <label> en dus het daarin zittende vraagteken volledig kan worden afgedekt als het sluitkruisje wordt getoond.

border: black solid 1px;

Randje.

position: absolute;

Om de <span> met het sluitkruisje op de juiste positie te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier #pop-up.

top: -48px;

Deze <span> staat binnen label#pop-up, de <label> met de pop-up. Als #pop-up wordt getoond, staat de bovenkant hiervan op gelijke hoogte met de onderkant van label#vraagteken, waarin het vraagteken zit.

De <span> met het sluitkruisje staat binnen #pop-up en dus ook op deze hoogte: onder het vraagteken, zoals op de afbeelding is te zien. Door de <span> 48 px naar boven te verplaatsen, komt deze op dezelfde hoogte als het vraagteken te staan.

Geen 48 px, zoals je misschien zou denken, want ook de borders tellen mee.

left: 47px;

Rechts naast het vraagteken neerzetten.

#pop-up span:first-of-type::before, #pop-up span:first-of-type::after

Deze selector valt in twee delen uiteen: voor en na de komma. Op het laatste stukje na zijn ze hetzelfde.

Eerst het deel dat hetzelfde is:

#pop-up span:first-of-type: de eerste <span> binnen het element met id=”pop-up”. #pop-up is de <label>, waarbinnen de pop-up zit. De eerste <span> binnen dit <label> wordt gebruikt om, als de pop-up zichtbaar is, op de plaats van het vraagteken een sluitkruisje weer te geven.

Het deel dat verschillend is:

::before: met behulp van ::before wordt bij deze <span> een pseudo-element gemaakt, met behulp waarvan de helft van het sluitkruisje kan worden weergegeven.

::after: met behulp van ::after wordt bij deze <span> een pseudo-element gemaakt, met behulp waarvan de andere helft van het sluitkruisje kan worden weergegeven.

Dat in de selectors met behulp van de dubbele punt meerdere pseudo-classes en pseudo-elementen worden gebruikt, is geen enkel probleem. Ze kunnen gewoon achter elkaar worden gezet.

Het grootste deel van de css voor beide pseudo-elementen is hetzelfde, dus dat kan hier in één keer worden opgegeven.

Het is niet goed mogelijk om een fatsoenlijk kruisje te maken met behulp van de letter ’x’ of een speciale utf-8-code of zoiets. Als dat er in de ene browser goed uitziet, doet de andere browser je acuut naar de fles grijpen om je verdriet te verdrinken. Twee pseudo-elementen met elk een border, die onder een hoek van 45 graden worden weergegeven, leveren wel overal een goed kruisje op.

Op de afbeelding is de met ::before gemaakte lijn rood, de met ::after gemaakte lijn is zwart weergegeven. Hoewel het eindresultaat een kruisje is, is op de afbeelding te zien dat het feitelijk om twee afzonderlijke lijnen gaat, die niets met elkaar te maken hebben.

content: "";

Deze eigenschap is altijd nodig, ook als er geen tekst of zo in het pseudo-element staat. Als er niets in staat, geef je dat aan door niets tussen de aanhalingstekens te zetten.

height: 66px;

Met enig proberen blijkt dit de hoogte te zijn die een goede diagonale lijn oplevert. Een breedte is niet nodig, want er wordt maar één border gebruikt.

border-right: red solid 1px;

Rode border. Dit levert een lijn van 1 px breedte op, die wordt gebruikt voor het kruisje.

position: absolute;

Om het pseudo-element, en daarmee de border, op de juiste plaats neer te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier de <span> waar het pseudo-element bij hoort.

Een met behulp van ::before of ::after gemaakt pseudo-element is een inline-element. Daardoor zijn eigenschappen als breedte en hoogte niet te gebruiken. Door het pseudo-element absoluut te positioneren, verandert het in een soort blok-element en zijn deze eigenschappen wel te gebruiken.

top: -10px; left: 22px;

Met enig uitproberen blijkt dit de juiste positie te zijn om een diagonale lijn van hoek naar hoek te krijgen.

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

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

Tot nu toe is alleen een gewone rode lijn gemaakt: de border van het pseudo-element. Die border staat gewoon rechtop, zoals op de afbeelding is te zien. Door het pseudo-element 45 graden te draaien, loopt de lijn diagonaal van hoek naar hoek.

Er zijn twee rode lijnen: eentje bij het pseudo-element dat met ::before is gemaakt, en eentje bij het pseudo-element dat met ::after is gemaakt. Je ziet er op de afbeelding maar eentje, omdat ze over elkaar heen staan.

Iets hieronder wordt het pseudo-element dat met ::after is gemaakt 45 graden de andere kant op gedraaid, en ziedaar: een diagonaal kruis is geboren.

#pop-up span:first-of-type::after

Voor dit element geldt ook de eerder bij #pop-up span:first-of-type::before, #pop-up span:first-of-type::after opgegeven css, voor zover die hier niet wordt gewijzigd.

Het met behulp van ::after bij de eerste <span> binnen het element met id=”pop-up” gemaakte pseudo-element. Een uitgebreidere beschrijving staat iets hierboven bij #pop-up span:first-of-type::before, #pop-up span:first-of-type::after.

Dit pseudo-element wordt gebruikt om de tweede helft van het sluitkruisje weer te geven.

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

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

Iets hierboven zijn de met ::before en ::after gemaakte pseudo-elementen 45 graden gedraaid, waardoor de rode border diagonaal komt te staan. Door hier alleen het met ::after gemaakte pseudo-element juist 45 graden de andere kant op te draaien, komt de rode border hiervan haaks op de rode border van het met behulp van ::before gemaakte pseudo-element te staan. Samen vormen ze nu een diagonaal kruis.

Hierboven bij #pop-up span:first-of-type::before, #pop-up span:first-of-type::after staat dit wat uitgebreider beschreven, inclusief afbeelding.

#gif-1

Het element met id=”gif-1”. Dit is een <span> waarbinnen een achtergrond-afbeelding komt te staan. Die achtergrond-afbeelding is afkomstig van een zogenaamde ’sprite’: een grote afbeelding waarop 26 smileys zijn gemonteerd.

De smileys zijn in twee groepen te verdelen: bewegende en niet-bewegende.

De bewegende smileys zijn gifs. In werkelijkheid beweegt een gif helemaal niet, maar bestaat uit een hele serie afbeeldingen. Elke afbeelding zit op een eigen laag. Door de afbeelding op zo’n laag steeds iets te veranderen ten opzichte van de eerdere of latere laag en die lagen snel achter elkaar te laten zien, ontstaat de illusie van beweging. Inderdaad, je wordt belazerd, waar je bij staat.

In theorie zou je bewegende gifs kunnen samenvoegen tot ’n soort super-gif. Elke gif bestaat uit een aantal lagen. Om meerdere gifs samen te voegen, zou je elk van die lagen naast elkaar moeten monteren. Elke gif moet dan ook nog exact hetzelfde aantal lagen hebben, anders kom je niet gelijk uit.

Helaas varieert het aantal lagen in de diverse gifs, dus dit gaat niet volledig lukken. Maar je zou nog steeds gifs die hetzelfde aantal lagen hebben, kunnen samenvoegen.

Er zijn 41 bewegende gifs en deze regering bezuinigt schandalig op de geestelijke gezondheidszorg. Die combinatie zorgt ervoor dat ik dit niet doe, want dat samenvoegen – als het al lukt – leidt gegarandeerd tot een intieme kennismaking met de Crisisdienst.

Maar er zijn ook 26 smileys die níét bewegen. En die zijn prima samen te voegen tot een grote afbeelding: de sprite met 26 smileys. Hiermee worden 25 aanroepen naar de server uitgespaard: in plaats van 26 aparte <img>’s wordt één grote afbeelding gedownload.

In de pop-up zitten de bewegende smileys als gewone <img>’s.

De niet-bewegende smileys worden als achtergrond-afbeelding in de <span>’s gezet. In de code is dat ook te zien:

<span id="gif-1"></span><img src="018-pics/gif2.gif" alt=""><img src="018-pics/gif3.gif" alt=""><img src="018-pics/gif4.gif" alt=""><img src="018-pics/gif5.gif" alt=""><img src="018-pics/gif6.gif" alt=""><img src="018-pics/gif7.gif" alt=""><img src="018-pics/gif8.gif" alt=""><span id="gif-9">

Enz., tot en met <span id="gif-67"></span>.

Om verwarring te voorkomen loopt de nummering van de <span>’s en <img>’s gewoon door: de eerste span heeft volgnummer 1, de daaropvolgende <img> heeft volgnummer 2, de daaropvolgende <img> volgnummer 3, enz.

In bovenstaande code is de eerste smiley een niet-bewegende en staat dus als achtergrond-afbeelding in een <span>. De tweede t/m achtste smiley bewegen, dus dit zijn <img>'s. De negende smiley beweegt weer niet en is dus een achtergrond-afbeelding in een <span>.

Op de afbeelding zijn alleen de bewegende smileys zichtbaar, de <img>’s. De achtergrond-afbeeldingen uit de <span>’s zijn weggelaten. Om de <span>’s zichtbaar te maken, hebben ze een witte outline gekregen. Zoals je ziet, staan de <img>’s met bewegende en de <span>’s met niet-bewegende smileys volledig door elkaar heen.

<img>’s en <span>’s zijn beide inline-elementen. Ze kunnen dus probleemloos op dezelfde regel worden gezet.

De niet-bewegende smileys in de <span>’s worden als achtergrond-afbeelding weergegeven. Een achtergrond-afbeelding heeft geen grootte: hij vult de achtergrond van het element waar hij in staat. Hier is dat een <span>. Door de <span> de maat van de te tonen smiley te geven, is de smiley volledig zichtbaar.

Omdat alle niet-bewegende smileys op één grote achtergrond-afbeelding staan, moet ook nog de juiste background-position worden opgegeven. Die is bij elke <span> anders.

background: url(../018-pics/smileys.png) 0 -2px;

De gebruikte achtergrond-afbeelding is ’smileys.png’.

Daarachter staat de background-position. Het eerste getal is de verplaatsing in horizontale richting, het tweede getal de verplaatsing in verticale richting. 0 px horizontaal verplaatsen, en -2 px verticaal. Omdat het tweede getal negatief is, wordt de achtergrond-afbeelding 2 px naar boven verplaatst.

(Jaja, ik weet het: een Pietje Precies zou de smiley op de achtergrond-afbeelding 2 px hoger hebben gemonteerd. Zodra iemand aantoont dat wie dan ook daar echt gelukkiger van wordt, zal ik dat alsnog doen. Het kost veel tijd en levert geen of nauwelijks voordeel op.)

In plaats van background, een zogenaamde ’shorthand’, kun je ook de afzonderlijke eigenschappen background-image en background-position gebruiken, maar dit is veel korter.

display: inline-block;

Een <span> is een inline-element. Daardoor kunnen eigenschappen als breedte en hoogte niet worden gebruikt. Bij een blok-element kunnen ze wel worden gebruikt, maar een blok-element komt op een nieuwe regel te staan. inline-block is het beste uit twee werelden: breedte e.d. kunnen worden gebruikt, en de <span> komt toch niet op een nieuwe regel te staan.

width: 41px; height: 46px;

Breedte en hoogte. Met deze breedte en hoogte wordt de eerste smiley op de grote achtergrond-afbeelding volledig weergegeven.

#gif-9

{background: url(../018-pics/smileys.png) -47px -3px; display: inline-block; width: 23px; height: 15px;}

Het element met id=”gif-9”. De <span> voor de negende smiley.

Alles is precies hetzelfde als bij #gif-1 hier gelijk boven, alleen zijn de grootte en positie aangepast.

Horizontaal wordt de achtergrond-afbeelding 47 px naar links verschoven, en verticaal 3 px naar boven. Naar links en naar boven, omdat het negatieve getallen zijn. Hiermee wordt precies de goede smiley zichtbaar.

Binnen deze een breedte van 23 px en een hoogte van 15 px past de negende smiley precies.

#gif-10

{background: url(../018-pics/smileys.png) -71px -3px; display: inline-block; width: 44px; height: 46px;} #gif-11 {background: url(../018-pics/smileys.png) -117px -4px; display: inline-block; width: 41px; height: 46px;} #gif-13 {background: url(../018-pics/smileys.png) -164px -6px; display: inline-block; width: 23px; height: 20px;} #gif-14 {background: url(../018-pics/smileys.png) -191px -4px; display: inline-block; width: 17px; height: 17px;} #gif-15 {background: url(../018-pics/smileys.png) -212px -4px; display: inline-block; width: 15px; height: 27px;} #gif-19 {background: url(../018-pics/smileys.png) -47px -24px; display: inline-block; width: 18px; height: 20px;} #gif-20 {background: url(../018-pics/smileys.png) -168px -31px; display: inline-block; width: 64px; height: 46px;} #gif-21 {background: url(../018-pics/smileys.png) 0 -53px; display: inline-block; width: 44px; height: 46px;} #gif-23 {background: url(../018-pics/smileys.png) -44px -57px; display: inline-block; width: 16px; height: 16px;} #gif-24 {background: url(../018-pics/smileys.png) -62px -55px; display: inline-block; width: 44px; height: 25px;} #gif-25 {background: url(../018-pics/smileys.png) -118px -55px; display: inline-block; width: 33px; height: 20px;} #gif-26 {background: url(../018-pics/smileys.png) -160px -66px; display: inline-block; width: 28px; height: 22px;} #gif-30 {background: url(../018-pics/smileys.png) -47px -82px; display: inline-block; width: 15px; height: 15px;} #gif-38 {background: url(../018-pics/smileys.png) -228px -3px; display: inline-block; width: 32px; height: 36px;} #gif-39 {background: url(../018-pics/smileys.png) -235px -45px; display: inline-block; width: 19px; height: 20px;} #gif-40 {background: url(../018-pics/smileys.png) -67px -83px; display: inline-block; width: 21px; height: 22px;} #gif-41 {background: url(../018-pics/smileys.png) -88px -76px; display: inline-block; width: 26px; height: 32px;} #gif-46 {background: url(../018-pics/smileys.png) -231px -71px; display: inline-block; width: 25px; height: 26px;} #gif-47 {background: url(../018-pics/smileys.png) -114px -82px; display: inline-block; width: 19px; height: 25px;} #gif-48 {background: url(../018-pics/smileys.png) -134px -78px; display: inline-block; width: 21px; height: 21px;} #gif-50 {background: url(../018-pics/smileys.png) -191px -80px; display: inline-block; width: 15px; height: 15px;} #gif-52 {background: url(../018-pics/smileys.png) -187px -74px; display: inline-block; width: 24px; height: 32px;} #gif-53 {background: url(../018-pics/smileys.png) -259px -2px; display: inline-block; width: 22px; height: 27px;} #gif-67 {background: url(../018-pics/smileys.png) -259px -35px; display: inline-block; width: 32px; height: 32px;}

Voor deze <span>’s is het verhaal precies hetzelfde als voor de hierboven staande #gif-1 en #gif-9. Alleen zijn overal de achtergrondpositie en de breedte en hoogte aangepast aan de weer te geven smiley.

#open:checked ~ #pop-up, #vraagteken:not(:active):hover ~ #pop-up, #wrapper span:first-of-type:focus ~ #pop-up

De selectors die de pop-up laten zien. Het zijn drie selectors, gescheiden door een komma. De eerste zorgt voor openen bij aanraken of aanklikken van het vraagteken. De tweede zorgt voor openen bij hoveren over het vraagteken. De derde zorgt voor openen met behulp van de Tab-toets.

De eerste selector: #open:checked ~ #pop-up

#open:checked: als het element met id=”open” is geselecteerd. Dit is een <input> type=”radio” (radioknop).

~: het hierachter staande element moet ergens in de html staan, na het hiervoor staande element. Het hoeft er, anders dan bij de +, niet gelijk op te volgen, als het maar ergens na het eerste element in de html staat.

De enige voorwaarde is verder dat het voor en het na de ~ staande element dezelfde ouder hebben. Dat is hier het geval: #open voor de ~ en #pop-up na de ~ hebben beide als ouder div#wrapper.

#pop-up: het element met id=”pop-up”. Dit is de <label>, waarbinnen de pop-up staat.

Alles bij elkaar: doe iets met label#pop-up als input#open is geselecteerd.

De tweede selector: #vraagteken:not(:active):hover ~ #pop-up

#vraagteken: het element met id=”vraagteken”. Dit is de <label>, waarbinnen het vraagteken staat.

:not(:active): als #vraagteken niet actief is. Een element is actief, als de muis boven het element wordt ingedrukt. Dit stukje voorkomt een flikkering in Edge, als de pop-up via aanraken wordt geopend. Een uitgebreider verhaal is te vinden bij :active.

:hover: als wordt gehoverd over #vraagteken.

~: het hierachter staande element moet ergens in de html staan, na het hiervoor staande element. Het hoeft er, anders dan bij de +, niet gelijk op te volgen, als het maar ergens na het eerste element in de html staat.

De enige voorwaarde is verder dat het voor en het na de ~ staande element dezelfde ouder hebben. Dat is hier het geval: #vraagteken voor de ~ en #pop-up na de ~ hebben beide als ouder div#wrapper.

#pop-up: het element met id=”pop-up”. Dit is de <label>, waarbinnen de pop-up staat.

Alles bij elkaar: doe iets met label#pop-up als over label#vraagteken wordt gehoverd, maar niet als label#vraagteken actief is.

Dat in de selector met behulp van de dubbele punt meerdere pseudo-classes worden gebruikt, is geen enkel probleem. Deze kunnen gewoon achter elkaar worden gezet.

De derde selector: #wrapper span:first-of-type:focus ~ #pop-up

#wrapper: het element met id=”wrapper”. Dit is de <div>, waar de hele pop-up in zit.

span:first-of-type: de eerste <span> binnen div#wrapper.

:focus: als deze <span> focus heeft. Normaal genomen kan een <span> geen focus krijgen. Hier is deze <span> juist speciaal aangebracht voor die focus, zodat ook gebruikers van de Tab-toets de pop-up kunnen openen. Hoe dat verder precies werkt, is te vinden bij Tabindex.

~: het hierachter staande element moet ergens in de html staan, na het hiervoor staande element. Het hoeft er, anders dan bij de +, niet gelijk op te volgen, als het maar ergens na het eerste element in de html staat.

De enige voorwaarde is verder dat het voor en het na de ~ staande element dezelfde ouder hebben. Dat is hier het geval: de <span> voor de ~ en #pop-up na de ~ hebben beide als ouder div#wrapper.

#pop-up: het element met id=”pop-up”. Dit is de <label>, waarbinnen de pop-up staat.

Alles bij elkaar: doe iets met label#pop-up als de eerste <span> binnen div#wrapper focus heeft.

Dat in de selector met behulp van de dubbele punt meerdere pseudo-classes worden gebruikt, is geen enkel probleem. Deze kunnen gewoon achter elkaar worden gezet.

Deze drie selectors sturen dus alle drie de hieronder staande css aan, ook al zien ze er volkomen verschillend uit.

left: 0;

Na de indrukwekkende serie selectors die deze css aanstuurt, kan het niet anders of de css zelf valt bitter tegen. Is dit alles?

Ja, dit is alles.

Bij #pop-up is label#pop-up met left: -20000px; links buiten het scherm geparkeerd. Daar is ook de rest van de opmaak al opgegeven, De <label> hoeft nu alleen nog maar binnen het venster van de browser te worden gezet, en dat gebeurt hier.

#open:checked ~ #pop-up span:first-of-type

Voor dit element geldt ook de eerder bij #pop-up span:first-of-type opgegeven css, voor zover die hier niet wordt gewijzigd.

#open:checked: als het element met id=”open” is geselecteerd. Dit is een <input> type=”radio” (radioknop).

~: het hierachter staande element moet ergens in de html staan, na het hiervoor staande element. Het hoeft er, anders dan bij de +, niet gelijk op te volgen, als het maar ergens na het eerste element in de html staat.

De enige voorwaarde is verder dat het voor en het na de ~ staande element dezelfde ouder hebben. Dat is hier het geval: input#open voor de ~ en #pop-up na de ~ hebben beide als ouder div#wrapper.

#pop-up: het element met id=”pop-up”. Dit is de <label>, waarbinnen de pop-up staat.

span:first-of-type: de eerste <span> binnen label#pop-up. Dit is de <span> die voor het sluitkruisje zorgt.

Alles bij elkaar: doe iets met de eerste <span> binnen label#pop-up, als input#open is geselecteerd.

display: block;

Bij #pop-up span:first-of-type is deze <span> met display: none; verborgen. Daar is ook de hele opmaak van het sluitkruisje al opgegeven. Nu mag het sluitkruisje worden getoond.

#open:checked ~ #vraagteken

Voor dit element geld ook de eerder bij #vraagteken opgegeven css, voor zover die hier niet wordt gewijzigd.

#open:checked: als het element met id=”open” is geselecteerd. Dit is een <input> type=”radio” (radioknop).

~: het hierachter staande element moet ergens in de html staan, na het hiervoor staande element. Het hoeft er, anders dan bij de +, niet gelijk op te volgen, als het maar ergens na het eerste element in de html staat.

De enige voorwaarde is verder dat het voor en het na de ~ staande element dezelfde ouder hebben. Dat is hier het geval: input#open voor de ~ en #vraagteken na de ~ hebben beide als ouder div#wrapper.

#pop-up: het element met id=”pop-up”. Dit is de <label>, waarbinnen de pop-up staat.

color: rgba(0, 0, 0, 0.2);

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

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

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

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

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

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

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

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

Omdat in dit voorbeeld drie keer 0 is opgegeven, levert dit een zwarte kleur op.

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

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

In dit voorbeeld is de kleur behoorlijk doorzichtig: 0.2. Hierdoor wordt het vraagteken veel vager weergegeven en valt het sluitkruisje beter op.

css voor vensters minimaal 550 px breed

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

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

De css die binnen deze media query staat, geldt alleen voor vensters die minimaal 550 px breed zijn. In deze vensters wordt de pop-up niet staand, maar liggend weergegeven.

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

screen: deze regel geldt alleen voor schermweergave.

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

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

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

@media screen and (min-width: 550px) { body {color: silver;} (...) rest van de css voor deze @media-regel (...) footer {color: gold;} }

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

#pop-up

Het element met id=”pop-up”. Dit is de <label>, waarbinnen de hele pop-up staat.

width: 535px; height: 200px;

Breedte en hoogte. In deze bredere browservensters is er genoeg ruimte om de pop-up niet staand, maar liggend te tonen.

JavaScript

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

<script> document.getElementById("vraagteken").addEventListener("touchstart", function () {return null; }); </script>

<script> en </script>

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

document.getElementById("vraagteken")

Zoek naar het element met id=”vraagteken”. Dit is de <label> waar het vraagteken in staat.

addEventListener

Voeg aan dat element met id=”vraagteken” een ’eventlistener’ toe. Dat is een ding dat luistert, of er iets gebeurt. Zo’n gebeurtenis kan een aanraking van het scherm zijn, een liefdevolle aai van de muis, een ram op het toetsenbord, van alles.

"touchstart"

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

function () {return null; }

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

function() is gewoon een soort aankondiging dat er iets gaat gebeuren. Erachter tussen de accolades staat, wat er gaat gebeuren: return null;. Doe niets. Helemaal niets. Vanavond niet, schat, ik heb hoofdpijn. Of, afhankelijk van opvoeding, omgeving, enz.: blijf met je gore rotpoten van me af, viespeuk.

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

In feite wordt hier gewoon gezegd: als het scherm wordt aangeraakt, blijf dan niet dom tot het jaar 3017 wachten op wat er verder gebeurt, maar reageer gelijk. Zonder dit stukje JavaScript verandert het vraagteken pas bij een tweede aanraking in een sluitkruisje, omdat eerst het hoveren over het vraagteken wordt afgehandeld en pas bij een tweede aanraking de radioknop die bij label#vraagteken hoort, wordt geselecteerd.

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