Drie manieren om pagina of blok-element met onbekende hoogte verticaal te centreren - uitleg
Laatst aangepast: .

Korte omschrijving
Drie manieren om een pagina of blok-element met onbekende hoogte verticaal te centreren: display: table;
flexbox en translateY()
.
Gele blok
Pagina. Met behulp van display: table;
verticaal gecentreerd in het venster van de browser, ongeacht de hoogte van de pagina.
Tekst en blauwe blok links
Gewone <div> met wat tekst en 'n geneste (blauwe) <div>. Als de hoeveelheid tekst toeneemt, wordt de pagina hoger, maar deze blijft verticaal gecentreerd.
Witte blokje midden
Met behulp van flexbox binnen de pagina gecentreerde <div>.
Witte blok rechts
De witte <div> is verticaal gecentreerd met behulp van flexbox. De tekst in de <div> staat in een geneste <div>. De geneste <div> is weer verticaal gecentreerd in de witte <div> met behulp van translateY()
.
BELANGRIJK
Deze uitleg hoort bij het voorbeeld dat in de download zit. Het voorbeeld uit de download verschilt iets van het voorbeeld hier op de site. In de download ontbreekt bijvoorbeeld de navigatie voor de site. Ook in de kopregels zit vaak wat verschil. Daarnaast kunnen er nog andere (meestal kleine) verschillen zijn.
Als je deze uitleg leest naast de broncode van het voorbeeld op de site, kan het dus bijvoorbeeld zijn dat 'n <h1> uit de css bij 'n <h2> uit de html hoort. Maar het gaat niet om hele grote, fundamentele afwijkingen.
Als je dit lastig vindt, kun je bovenaan de pagina de hele handel downloaden. In de download zit 'n voorbeeld dat wel naadloos aansluit op de uitleg in de download.
Alles op deze site kan vrij worden gebruikt, met drie beperkingen:
* Je gebruikt het materiaal op deze site volledig op eigen risico. Het kan prima zijn dat er fouten in de hier verstrekte info zitten. Voor eventuele schade die door gebruik van materiaal van deze site ontstaat, in welke vorm dan ook, zijn www.css-voorbeelden.nl en medewerkers daarvan op geen enkele manier verantwoordelijk.
* Deze uitleg wordt regelmatig bijgewerkt. Het is daarom niet toegestaan deze uitleg op welke manier dan ook te verspreiden, zonder daarbij duidelijk te vermelden dat de uitleg afkomstig is van www.css-voorbeelden.nl en dat daar altijd de nieuwste versie is te vinden. Dit is om te voorkomen dat er verouderde versies worden verspreid.
* Het kan zijn dat materiaal is gebruikt dat van anderen afkomstig is. Dat materiaal kan onder een bepaalde licentie vallen, waardoor het mogelijk niet onbeperkt gebruikt mag worden. Als dat zo is, wordt dat vermeld onder Inhoud van de download en licenties.
Een link naar www.css-voorbeelden.nl wordt trouwens altijd op prijs gesteld.
Alle code is geschreven in een afwijkende
lettersoort en -kleur. De code die te maken heeft met de basis van dit voorbeeld (essentiële code), is in de hele uitleg onderstippeld blauw
. Alle niet-essentiële code is bruin
. (In de inhoudsopgave staat alles vanwege de leesbaarheid in een gewone letter.)
Opmerkingen
- Als je de hele pagina verticaal wilt centreren, zou je je eerst nog even kunnen afvragen, of dat echt bijdraagt aan het geluk van de mensheid. Er zijn misschien uitzonderingen te bedenken, maar in het algemeen is dit een tamelijk zinloze exercitie. In ieder geval kun je beter niet flexbox of
translateY()
gebruiken. Als de pagina hoger is dan het venster van de browser, kan bij die methoden een deel van de pagina aan de bovenkant van het venster verdwijnen. Bij de methode metdisplay: table;
speelt dit probleem niet. Meer hierover bij Bekende problemen (en oplossingen). - Deze manieren van verticaal centreren werken bij een onbekende hoogte. Als de hoogte van de inhoud verandert, wordt de pagina of het blok-element weer opnieuw verticaal gecentreerd. Voor het centreren van andere elementen zie www.css-voorbeelden.nl/positioneren.
- Op de site staat de pagina (het gele blok) gecentreerd in het venster van de browser, net zoals in de download. Voor het centreren worden de knoppen en de kopregel genegeerd. Als die mee zouden doen, zou het gele blok iets lager komen te staan dan in de download.
Links in deze uitleg, vooral links naar andere sites, kunnen verouderd zijn. Op de pagina met links vind je steeds de meest recente links.
Dit voorbeeld is gemaakt op een systeem met Linux (Kubuntu). Daarbij is vooral gebruik gemaakt van Komodo Edit, GIMP en Firefox met extensies. De pdf-bestanden zijn gemaakt met LibreOffice.
Vragen of opmerkingen? Fout gevonden? Ga naar het forum.
Achterliggend idee
Omdat verticaal centreren alleen zinvol is in grotere browservensters, wordt in vensters smaller dan 760 px en/of lager dan 500 px niet verticaal gecentreerd. Het is wat raar om <div>'s speciaal hoger te gaan maken, zodat de inhoud ervan gecentreerd kan worden. Maar in principe werken de hier beschreven technieken precies hetzelfde in kleinere vensters.
Verticaal centreren van een blok-element met onbekende hoogte kon tot voor kort behoorlijk lastig zijn. De enige echt bruikbare methode was weergave in een tabel, omdat in de cel van een tabel met vertical-align
de hele inhoud simpel verticaal gecentreerd kan worden, inclusief eventuele blok-elementen in de cel. En ook als de hoogte van de inhoud van de cel onbekend was.
Inmiddels kan uit meerdere methodes worden gekozen. In dit voorbeeld worden drie manieren van verticaal centreren van een blok-element met onbekende hoogte getoond: het gebruik van een css-tabel (dat is iets totaal anders dan een html-tabel), flexbox en translateY()
.
Als je de hele pagina verticaal wilt centreren, zou ik me eerst nog 'ns afvragen, wat het nut daarvan is. Is 'n kleine marge aan de bovenkant of zoiets niet voldoende? Dat is veel simpeler dan allerlei speciale constructies. Als je bijvoorbeeld afbeeldingen centraal wilt weergeven, is het dan niet veel simpeler die afbeelding (of het element waar de afbeelding in zit) verticaal te centreren?
Tabel
Dit is de enige methode die geschikt is voor het verticaal centreren van de volledige pagina. Bij flexbox en translateY()
is er een grote kans dat een deel van de pagina bovenaan het browservenster verdwijnt.
Alle moderne browsers kunnen een element weergeven, alsof het een tabel is, of een cel uit een tabel. Als je van een element met behulp van display: table;
een css-tabel maakt, en je zet daar met behulp van display: table-cell;
een css-tabelcel in, dan kun je vertical-align
gebruiken om verticaal te centeren.
De tabel, het ouder-element, krijgt een bepaalde hoogte. De css-tabelcel wordt, net zoals bij html-tabelcellen, niet hoger dan nodig is om de inhoud ervan weer te geven. Met behulp van vertical-align: middle;
kan de cel dan verticaal in de tabel worden gecentreerd. Waardoor ook de inhoud van de cel verticaal binnen de tabel wordt gecentreerd. Ook al is de hoogte van de inhoud van de tabelcel onbekend, de inhoud wordt toch verticaal gecentreerd.
Het verticaal centreren van de hele pagina kan op precies dezelfde manier. De ouder van <body> is <html>. Als je <html> 100% hoog maakt, wordt <html> even hoog als het browservenster. Als je vervolgens ook <body> 100% hoog maakt, zal ook <body> het hele venster vullen. Maak van <body> een css-tabel en je kunt de inhoud van <body> verticaal centreren met behulp van css-tabelcellen.
<body> is in dit voorbeeld even hoog als het browservenster gemaakt en met display: table;
in een css-tabel veranderd. <main>, het element waar de pagina in staat, is met display: table-cell;
in een css-tabelcel veranderd en kan daardoor met vertical-align: middle;
verticaal in <body> worden gecentreerd. En daarmee staat de hele pagina verticaal gecentreerd binnen het venster.
Eh, 'n tabel voor lay-out??? Daar staat inmiddels toch zeven jaar mosselen duiken in de Waddenzee op? En nu moet je opeens 'n tabel voor lay-out gebruiken?
Ja.
Een tabel is inderdaad bedoeld voor tabulaire gegevens, zoals een kalender. Een tabel voor lay-out maakt je pagina uiterst ontoegankelijk voor schermlezers, zoekmachines, en dergelijke. En tabellen, zeker geneste tabellen, zijn uiterst moeilijk te onderhouden. Maar het gaat dan om een html-tabel, en dit is een css-tabel.
De eigenlijke inhoud van de pagina bestaat nog steeds uit doodgewone <div>'s en dergelijke. De css-tabel wordt alleen voor de lay-out gebruikt, voor de weergave, niet om de inhoud van de pagina zelf in een tabel te zetten. Dus de hierboven aangegeven problemen zullen zich niet voordoen. In het verleden werd voor verticaal centreren vaak een html-tabel gebruikt, en dan heb je die nadelen wel.
Bij een html-tabel zijn er allerlei regels. Zo moet een <td> (een tabelcel) binnen een <tr> (een tabelregel) staan. Bij een css-tabel is dat niet zo. De browser maakt automatisch de missende onderdelen van de tabel aan. Je hoeft dus niet allerlei overbodige elementen aan de html toe te voegen om een css-tabel te kunnen gebruiken.
Overigens blijft het een goede gewoonte om tabellen alleen voor tabulaire gegevens te gebruiken, omdat de css anders al snel even rommelig en moeilijk te onderhouden wordt als een html-tabel. Maar om verticaal te centreren is zo'n enkele css-tabelcel heel handig.
Flexbox
Deze methode is absoluut ongeschikt om een hele pagina mee te centreren. Als de pagina hoger is dan het venster van de browser, valt in onder andere Internet Explorer aan de bovenkant van het venster een deel van de pagina weg. Als wordt ingezoomd (vergroot) en de pagina daardoor hoger wordt dan het venster, valt in een groot deel van de browsers aan de bovenkant een deel van de pagina weg.
Met behulp van display: flex;
kan een element worden veranderd in een zogenaamde 'flex container'. Dat is een blok-element, waarbinnen allerlei aparte regels gelden voor positioneren, uitlijnen, en dergelijke.
De directe kinderen binnen een flex container zijn zogenaamde 'flex items'. Dat geldt alleen voor de directe kinderen van de flex container:
<div id="flexbox" style="display: flex;">
<div class="direct-kind">
<p id="ondergeschoven-kindje"></p>
</div>
<div class="direct-kind"></div>
</div>
div#flexbox
is met display: flex;
veranderd in een flex container. Beide <div>'s met class="direct-kind" zijn directe kinderen van div#flexbox
en zijn veranderd in een flex item. p#ondergeschoven-kindje
is geen direct kind van div#flexbox
, maar van de eerste div.direct-kind
. p#ondergeschoven-kindje
is dan ook niet veranderd in een flex item.
Ook voor flex items gelden aparte regels voor positioneren, uitlijnen, en dergelijke.
Flexbox, zoals het geheel van eigenschappen op dit gebied heet, is gemaakt om problemen als verticaal centreren, onderverdelen in gelijke stukken, en dergelijke op te lossen.
De hele pagina staat binnen het element <main>, dat maar één direct kind heeft: div#voor-flex
. Deze <div> is met display: flex;
veranderd in een flex container. De directe kinderen div#links
, div#midden
en div#rechts
zijn hiermee veranderd in flex items.
(Feitelijk is die hele div#voor-flex
min of meer overbodig, omdat ook <main> in een flex container had kunnen worden veranderd met display: flex;
. Maar bij <main> staat al display: table-cell;
, dus dat kon niet meer. Op een 'normale' pagina zou dat waarschijnlijk wel kunnen.)
Door bij de flex container align-items: center;
te gebruiken worden alle directe kinderen van div#voor-flex
verticaal gecentreerd, of de hoogte nu bekend is of niet.
Op div#links
, waarin de tekst links en het blauwe blok staan, heeft dit verticaal centreren geen invloed. Deze <div> is van de drie kinderen van div#voor-flex
het hoogste en bepaalt daarmee de hoogte van div#voor-flex
. Centreren van deze <div> is dus zinloos, want hij is automatisch even hoog als div#voor-flex
.
div#midden
, het kleine witte blokje in het midden, wordt wel verticaal gecentreerd binnen div#voor-flex
. Deze <div> is heel laag, waardoor dit duidelijk is te zien. Als in div#midden
inhoud wordt toegevoegd of verwijderd, blijft div#midden
toch verticaal gecentreerd. Terwijl de hoogte van deze <div> onbekend is. Bij het opbouwen van de pagina rekent de browser alle groottes uit. De browser kan dat, omdat bij weergave grootte, resolutie, en dergelijke van scherm en browservenster bij de browser bekend zijn. De browser kan daardoor de hoogte van div#voor-flex
berekenen en vervolgens div#midden
verticaal daarbinnen centreren.
Op div#rechts
, het witte blok rechts, heeft align-items: center;
ook geen invloed. Normaal genomen zou dat wel zo zijn, maar bij div#rechts
staat in de css align-self: stretch;
. Hierdoor wordt div#rechts
even hoog als de flex container div#voor-flex
en kan dus niet worden gecentreerd. (Dat de witte achtergrond van div#rechts
niet de volle hoogte vult, komt doordat boven en onder de <div> een marge staat.)
Dit is trouwens een van de vele handige dingen van flexbox: je kunt bij de flex container (hier div#voor-flex
) eigenschappen opgeven voor álle flex items, en bij de afzonderlijke flex items kun je die eventueel weer overrulen met aparte css specifiek voor 'n bepaald flex item.
Blok-elementen zoals een <div> komen normaal genomen op een nieuwe regel te staan. Flex items, directe kinderen van een flex container, blijven echter normaal genomen op dezelfde regel staan. Als dat nodig is, worden ze eventueel versmald. Daardoor blijven in dit voorbeeld div#rechts
, div#midden
en div#links
naast elkaar staan. (Je kunt dit veranderen, zodat ze wel op een nieuwe regel komen te staan.)
Browsers die flexbox niet kennen, negeren het gewoon. Dat zijn van de geteste browsers alleen Android browser en UC browser op Android. In deze browsers zouden de <div>'s daardoor toch onder elkaar komen te staan. Dat is echter niet zo, omdat de <div>'s ook worden gefloat. Browsers die flexbox kennen, negeren een float bij een flex item, maar oudere browsers die flexbox niet kennen, voeren de float gewoon uit.
In browsers die flexbox niet kennen, staat div#midden
gewoon bovenin div#voor-flex
, en div#rechts
vult niet de volle hoogte van div#voor-flex
. Alleen de lay-out verschilt, er verdwijnt geen tekst of zo. Bij Bekende problemen (en oplossingen) staat hiervan een afbeelding.
transform: translateY();
Deze methode is absoluut ongeschikt om een hele pagina mee te centreren. Als de pagina hoger is dan het venster van de browser, valt aan de bovenkant een deel van de pagina weg.
Het idee van deze methode is om het te centreren blok-element eerst halverwege de hoogte van de ouder (of een voorouder) te zetten. Daarna wordt het de halve hoogte van het element zelf terug naar boven gezet, waardoor de helft van het element boven en de helft onder het midden van de ouder of voorouder komt te staan. Oftewel: verticaal gecentreerd.
In dit voorbeeld wordt deze methode gebruikt om de tekst in div#rechts
, het witte blok rechts, te centreren. Die tekst staat in een eigen <div> binnen div#rechts
. Als de <div> met de tekst (die ik vanaf nu de 'binnenste' <div> noem) verticaal wordt gecentreerd binnen div#rechts
, zal uiteraard ook de tekst daarin verticaal gecentreerd staan binnen div#rechts
.
De binnenste <div> wordt halverwege de hoogte van div#rechts
gezet met behulp van top: 50%;
. Om top
te kunnen gebruiken, moet de binnenste <div> een relatieve of absolute positie krijgen. Als bij top
een percentage wordt gebruikt, geldt dit bij een relatieve positie ten opzichte van de ouder van het element, hier div#rechts
. (Vaak wordt gedacht dat top
altijd ten opzichte van het element zelf is bij een relatieve positie, maar dat is niet zo als een percentage wordt gebruikt.)
Om een relatieve positie te kunnen gebruiken, moet div#rechts
dus een hoogte hebben. Omdat dit voorbeeld nou juist gaat over blok-elementen die geen bekende hoogte hebben, kan geen hoogte in de css worden opgegeven aan div#rechts
. Maar bij het weergeven van de pagina kent de browser alle hoogtes, omdat dan grootte, resolutie, en dergelijke van scherm en browservenster bekend zijn. De browser kent dan dus ook de hoogte van div#rechts
en zou die kunnen gebruiken.
Helaas blijkt een fors aantal browsers (waaronder Safari en de meeste mobiele browsers) de hoogte van div#rechts
te negeren, omdat dit een 'flex item' is: een element dat een direct kind is van een met display: flex;
gemaakte flex container, hier div#voor-flex
. Daarom kan position: relative;
hier niet worden gebruikt: verticaal centreren binnen een element dat geen hoogte heeft, is tamelijk zinloos.
Blijft over position: absolute;
voor de binnenste <div>. Dan geldt top: 50%;
ten opzichte van de eerste voorouder die zelf een positie heeft. Je zou div#rechts
met position: relative;
een positie kunnen geven, maar ook dat is hier geen goed idee. In browsers die flexbox niet kennen, heeft div#rechts
namelijk helemaal geen hoogte. En 50% van een hoogte van 0 px is weliswaar formeel halverwege, maar leidt in dit geval toch niet tot wilde volksfeesten.
Maar als position: relative;
bij div#voor-flex
wordt gezet, blijkt de absolute positie bij de binnenste <div> wel te werken, want div#voor-flex
heeft wel in alle browsers een hoogte. Daardoor kan de binnenste <div> nu in alle browsers halverwege div#voor-flex
worden gepositioneerd. In dit geval heeft div#voor-flex
(min of meer toevallig) de goede hoogte, maar soms zul je het nog hogerop moeten zoeken bij eerdere voorouders.
Hèhè. En dat is nog maar de helft van het verhaal. Maar het is wel weer een aardige illustratie, waarom uitgebreid testen echt nodig is. Als dit voorbeeld alleen in Firefox, Chrome, Internet Explorer en Edge op de desktop was getest, was dit probleem nooit aan het licht gekomen.
Goed, de binnenste <div> staat halverwege de hoogte. Gelukkig is het tweede deel simpeler: met transform: translateY(-50%);
wordt de binnenste <div> met de helft van z'n eigen hoogte terug omhoog gezet. Waardoor de helft van de binnenste <div> boven het midden van div#voor-flex
staat, en de helft eronder. Het maakt hierbij niet uit hoe hoog de binnenste <div> is, de browser berekent dit automatisch bij het opbouwen van de pagina. Als er meer of minder inhoud in de binnenste <div> komt te staan, wordt de hoogte automatisch aangepast.
Welke methode is het beste?
Dat is niet heel simpel te zeggen.
Voor het centreren van de hele pagina, als je dat beslist wilt, is alleen de tabel-methode geschikt, omdat bij de andere methodes de kans te groot is dat aan de bovenkant een deel van de pagina wegvalt. De methode met de tabel is ook de enige methode, die op dit moment in alle geteste browsers werkt.
Met de tabel-methode kun je eventueel meerdere elementen centreren, door meerdere elementen in een css-tabelcel te veranderen en in dezelfde css-tabel op te nemen.
Voor één enkel element is de combinatie position: relative; top: 50%; transform: translateY(-50%);
met stip het simpelste. Maar als je absoluut moet gaan positioneren, zoals in dit voorbeeld, wordt het al 'n stuk lastiger.
Bovendien loop je altijd het risico dat gegevens verdwijnen. Als het te centreren element hoger is dan z'n ouder, kunnen er aan de bovenkant van de ouder gegevens verdwijnen. Dit ligt ook aan de instelling van overflow
bij de ouder. Je hebt hier niet volledig controle over, want gebruikers kunnen bijvoorbeeld ook hun lettergrootte verhogen. Maar als de ouder voldoende hoger is dan het te centreren element, is dit een uiterst bruikbare methode.
Voor het centreren van de hele pagina is translateY()
niet geschikt, omdat in een deel van de pagina aan de bovenkant van het browservenster wegvalt, als de pagina hoger is dan het venster. Over de hoogte van de pagina heb je nooit volledige controle, want bezoekers kunnen bijvoorbeeld de lettergrootte verhogen of inzoomen.
De methode met de meeste mogelijkheden is flexbox. Dat is, als je eraan gewend bent, ook de makkelijkste. Je kunt met flexbox de elementen horizontaal verdelen op allerlei mogelijke manieren. In de flex container kun je css opgeven voor álle flex items, en vervolgens kun je bij de flex items zelf dat weer veranderen voor één of meer flex items. Alle elementen verticaal centreren, maar eentje bovenaan zetten. Alle elementen even hoog, maar twee niet. Noem maar op. Flexbox is speciaal voor dit soort problemen bedacht, dus het is niet vreemd dat het het beste werkt.
Voor het centreren van de hele pagina is flexbox niet geschikt, omdat in meerdere browsers een deel van de pagina aan de bovenkant van het browservenster wegvalt, als de pagina hoger is dan het venster. Bij inzoomen (vergroten) gebeurt dit zelfs in de meeste browsers. Over de hoogte van de pagina heb je nooit volledige controle, want bezoekers kunnen bijvoorbeeld de lettergrootte verhogen.
(Waarom dat mallotige verticale centreren van een pagina hier is opgenomen, terwijl ik het 398 keer afraadt? Omdat de vraag op forums regelmatig terugkwam. En áls je dan echt denkt dat je bezoekers in gejubel uitbarsten bij een verticaal gecentreerde pagina, kun je het beter op de minst slechte manier doen.)
Helaas werkt flexbox nog niet in alle browsers. In Internet Explorer 11 werkt het wel, maar stikt het van de bugs. Als het geen onoverkomelijke problemen oplevert in browsers, waarin het niet werkt, kun je het best flexbox gebruiken. In dit voorbeeld wordt, als flexbox niet wordt ondersteund, het middelste witte blokje niet verticaal gecentreerd, maar bovenaan gezet. Verder heeft div#rechts
geen hoogte, waardoor de witte achtergrond te kort is en de border als een streepje helemaal bovenaan staat. In dit geval is dat allemaal niet zo erg, dus zou flexbox gewoon gebruikt kunnen worden. (Bij Bekende problemen (en oplossingen) staat een afbeelding, hoe het er zonder ondersteuning voor flexbox uitziet.)
(Voor de volledigheid: ook in UC browser op Android en Android browser kun je flexbox aan de praat krijgen, maar dat is een zwaar verouderde versie. Bovendien wonen daarin niet slechts 'n paar schattige buggetjes met hoge aaibaarheidsfactor, maar blijkt er 'n compleet regiment beroepsartiesten uit een professioneel vlooiencircus in te wonen. Reden voor de Werkgroep Overspannenheid van de Nederlandse Vereniging van Therapeuten om het gebruik van flexbox in deze browsers te verbieden. Waarmee ik maar wil zeggen: dat is echt volledig onbruikbaar door de onvolledige en foutieve implementatie.)
De voorvoegsels -moz-, -ms- en -webkit-
Voordat een nieuwe css-eigenschap wordt ingevoerd, is er in de regel een experimentele fase. Browsers passen het dan al toe, maar met een aangepaste naam. Tijdens deze fase kunnen problemen worden opgelost en worden veldslagen uitgevochten, over hoe de standaard precies moet worden toegepast.
Als iedereen het overal over eens is en alle problemen zijn opgelost, wordt de officiële naam uit de standaard gebruikt.
De belangrijkste browsers hebben elk een eigen voorvoegsel:
Firefox: -moz-
, naar de maker: Mozilla.
Op webkit gebaseerde browsers, zoals Google Chrome, Opera, Safari en Android browser: -webkit-
.
(Google Chrome is van webkit overgestapt op een eigen weergave-machine: Blink. Blink gaat geen voorvoegsels gebruiken. Het is echter een aftakking van webkit, dus het zal nog wel even duren voor -webkit-
hier helemaal uit is verdwenen. Ook Opera gebruikt Blink.)
Internet Explorer: -ms-
, naar de maker: Microsoft. (Edge gebruikt geen voorvoegsels, maar vanwege compatibiliteit met oudere sites kunnen er nog wat aanwezig zijn.)
Zodra de experimentele fase voorbij is, wordt het voorvoegsel weggelaten. Omdat dat moment niet bij alle browsers hetzelfde is, zet je nu ook al de officiële naam erbij. Deze wordt als laatste opgegeven. Bijvoorbeeld Android browser herkent -webkit-linear-gradient
. Zodra Android browser linear-gradient
gaat herkennen, zal dit -webkit-linear-gradient
overrulen, omdat het er later in staat. Dat ze er beide in staan, is dus geen enkel probleem.
In dit voorbeeld wordt transform
gebruikt.
transform
Op dit moment moet je nog het volgende schrijven:
{-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.
Vanwege alle problemen met 'vendor prefixes' worden deze door steeds meer browsers niet meer gebruikt. Nieuwe, experimentele css-eigenschappen zitten inmiddels in bijvoorbeeld Firefox, Google Chrome en Safari achter een zogenaamde vlag: de gebruiker moet iets veranderen in de instellingen, waarna de eigenschap gebruikt (en getest) kan worden. Als alles werkt, zoals het hoort te werken, schakelt de browsermaker de vlag standaard in.
Voorlopig zijn we echter nog niet van deze voorvoegsels af. Als je ze gebruikt, gebruik dan álle varianten, en eindig met de variant zonder voorvoegsel, zoals die uiteindelijk ooit gebruikt gaat worden. Als je alleen de -webkit-
variant gebruikt, ben je in feite 'n onbetaalde reclamemaker voor Apple.
De code aanpassen aan je eigen ontwerp
- Als je dit voorbeeld gaat aanpassen voor je eigen site, houd het dan in eerste instantie zo eenvoudig mogelijk. Ga vooral geen details invullen.
-
Gebruik vooral geen FrontPage, Publisher of Word (alle drie van Microsoft). Deze programma's maken niet-standaard code die alleen goed te bekijken is in Internet Explorer. In alle andere browsers zie je grotendeels bagger, áls je al iets ziet.
Publisher en Word zijn niet bedoeld om websites mee te maken. FrontPage is zwaar verouderd en wordt niet meer onderhouden door Microsoft.
Ook OpenOffice en LibreOffice leveren een uiterst beroerd soort html af. Tekstverwerkers met al hun toeters en bellen zijn gewoon niet geschikt om websites mee te bouwen.
Je kunt natuurlijk ook een goed gratis programma gebruiken. Links naar dat soort programma's vind je op de pagina met links onder Gereedschap → wysiwyg-editor.
Maar het allerbeste is om gewoon zelf html, css, enzovoort te leren, omdat zelfs het allerbeste programma het nog steeds zwaar verliest van 'n op de juiste manier met de hand gemaakte pagina.
-
Als je in een desktopbrowser met behulp van zoomen het beeld vergroot, heeft dit hetzelfde effect, als wanneer de pagina in een kleiner browservenster wordt getoond. Je kunt hiermee dus kleinere apparaten zoals een tablet of een smartphone simuleren. Maar het blijft natuurlijk wel een simulatie: het is nooit hetzelfde als testen op een écht apparaat. Zo kun je bijvoorbeeld aanrakingen alleen echt testen op een echt touchscreen.
Inmiddels hebben veel browsers mogelijkheden voor het simuleren van weergave op een kleiner scherm in de ontwikkelgereedschappen ingebouwd. Ook dit blijft een simulatie, maar geeft vaak wel een beter beeld dan zoomen.
-
Als je 'n site maakt in Firefox, Opera, Safari, Google Chrome of Edge, is er 'n hele grote kans dat hij in alle browsers werkt. Ik geef de voorkeur aan Firefox, omdat het de enige grote browser is die niet bij een bedrijf hoort dat vooral op je centen of je data uit is.
Google Chrome wordt ook door veel mensen gebruikt, maar ik heb dus wat moeite met hoe Google je hele surfgedrag, je schoenmaat en de kleur van je onderbroek vastlegt. Daarom gebruik ik Google Chrome zelf alleen om in te testen.
-
Het allereerste dat je moet invoeren, is het doctype, vóór welke andere code dan ook. Een lay-out met een missend of onvolledig doctype ziet er totaal anders uit dan een lay-out met een geldig doctype. Wát er anders is, verschilt ook nog 'ns tussen de diverse browsers. Als je klaar bent en dan nog 'ns 'n doctype gaat invoeren, weet je vrijwel zeker dat je van voren af aan kunt beginnen met de lay-out.
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.
-
Gebruik een 'strict' doctype of (beter!) het doctype voor html5. Deze zijn bedoeld voor nieuwe sites. Het transitional doctype is bedoeld voor al bestaande sites, niet voor nieuwe.
Het transitional doctype staat talloze tags toe, die in html5 zijn verboden. Deze tags worden al zo'n tien jaar afgeraden. Het transitional doctype is echt alleen bedoeld om de puinhoop van vroeger, toen niet volgens standaarden werd gewerkt, enigszins te herstellen.
Het strict doctype staat verouderde tags niet toe. Daardoor kan met 'n strict doctype, of het nu html of xhtml is, probleemloos worden overgestapt naar html5. Met een transitional doctype en het gebruik van afgekeurde tags kun je niet overstappen naar html5. Je moet dan eerst alle verouderde tags verwijderen, wat echt ontzettend veel werk kan zijn.
Het doctype voor html5 is uiterst simpel:
<!DOCTYPE html>
. Omdat het doctype voor html5 in alle browsers werkt, zelfs in de gelukkig vrijwel uitgestorven nachtmerrie Internet Explorer 6, is er geen enkele reden dit uiterst simpele doctype niet te gebruiken. - Als tweede voer je de charset in. Dit vertelt de browser, welke tekenset er gebruikt moet worden, zodat letters met accenten en dergelijke overal goed worden weergegeven. Het beste kun je utf-8 nemen. Als je later van charset verandert, loop je 'n grote kans dat je alle aparte tekens als letters met accenten weer opnieuw moet gaan invoeren. In html5 is het simpele
<meta charset="utf-8">
voldoende. - Test vanaf het allereerste begin in zoveel mogelijk verschillende browsers in 'n aantal resoluties (schermgroottes). Onder het kopje Getest in kun je in deze uitleg vinden, waar dit voorbeeld in is getest. Ook van Internet Explorer kun je meerdere versies naast elkaar draaien. Op de pagina met links staan onder de kopjes Gereedschap → Meerdere versies van Internet Explorer draaien en Gereedschap → Weergave testen 'n aantal links die daarbij kunnen helpen. De compatibiliteitsweergave in Internet Explorer is niet geschikt om in te testen, omdat deze enigszins verschilt van de weergave in échte browsers.
- Voor alle voorbeelden geldt: breng veranderingen stapsgewijs aan. Als je bijvoorbeeld foto's wilt laten weergeven, begin dan met het alleen veranderen van de namen van de foto's, zodat je eigen foto's worden weergegeven. Maakt niet uit als de maten niet kloppen en de teksten fout zijn. Als dat werkt, ga dan bijvoorbeeld de maten aanpassen. Dan de teksten. En controleer steeds, of alles nog goed werkt.
-
Als het om een lay-out of iets dergelijks gaat: zorg eerst dat header, kolommen, footer, menu, en dergelijke staan en bewegen, zoals je wilt. Ga daarna pas details binnen die blokken invullen. In eerste instantie gebruik je dus bijvoorbeeld 'n leeg blok op de plaats, waar uiteindelijk het menu komt te staan.
Als je begint met allerlei details, is er 'n heel grote kans dat die de werking van de blokken gaan verstoren. Bouw eerst het huis, en ga dan pas de kamers inrichten. Zorg eerst dat de blokken werken, zoals je wilt. Dan zul je het daarna gelijk merken, als 'n toegevoegd detail als tekst of 'n afbeelding iets gaat verstoren. Daarvoor moet je natuurlijk wel regelmatig controleren in verschillende browsers, of alles nog wel goed werkt.
Je kunt de blokken tijdens het aanpassen opvullen met bijvoorbeeld <br>1<br>2<br>3 enzovoort, tot ze de juiste hoogte hebben. Het is handig om aan het einde even iets toe te voegen als 'laatste', zodat je zeker weet dat er niet ongemerkt drie regels onderaan naar 't virtuele walhalla zijn verhuisd.
Om de breedte te vullen, kun je het best 'n kort woord als 'huis' duizend keer of zo herhalen. Ook hier is het handig om aan 't eind (en hier ook aan 't begin) 'n herkenningsteken te maken, zodat je zeker weet dat je de hele tekst ziet.
- Zolang je in grotere dingen zoals 'n lay-out aan 't wijzigen bent, zou ik je aanraden de verschillende delen een achtergrondkleur te geven. Je ziet dan goed, waar 'n deel precies staat. Een achtergrondkleur heeft – anders dan bijvoorbeeld een border – verder geen invloed op de lay-out, dus die is hier heel geschikt voor.
- Als je instellingen verandert in de style, verander er dan maar één, hooguit twee tegelijk. Als je er zeventien tegelijk verandert, is de kans groot dat je niet meer weet, wat je hebt gedaan. En dat je 't dus niet meer terug kunt draaien.
-
margin, padding en border worden bij de hoogte en breedte van het element opgeteld. Hier worden vaak fouten mee gemaakt. Als je bijvoorbeeld in een lay-out 'n border toevoegt aan een van de 'hoofdvakken' (header, footer, kolommen), dan wordt deze er bij opgeteld. Bij 'n border van 2 px rondom de linkerkolom wordt deze dus plotseling 4 px breder (2 aan beide kanten), en 4 px hoger. Zoiets kan je hele lay-out verstoren, omdat iets net te breed of te hoog wordt. Je moet dan elders iets 4 px kleiner maken. Dat zal vaak zo zijn: als je één maat verandert, zul je vaak ook 'n andere moeten aanpassen.
Css geeft de mogelijkheid om met behulp van
box-sizing
padding en border bínnen de breedte en hoogte van de inhoud te zetten, als je dat handiger vindt. -
In plaats van een absolute eenheid als
px
kun je ook een relatieve eenheid gebruiken, met nameem
. Voordeel vanem
is dat een lettergrootte, regelhoogte, en dergelijke inem
in alle browsers kan worden veranderd. Nadeel is dat het de lay-out sneller kan verstoren dan bijvoorbeeldpx
. Dit moet je gewoon van geval tot geval bekijken. Voor weergave in mobiele apparaten zijn relatieve eenheden alsem
vrijwel altijd beter dan vaste eenheden alspx
.Zoomen kan trouwens altijd, ongeacht welke eenheid je gebruikt.
-
Valideren, valideren, valideren en dan voor 't slapen gaan nog 'ns valideren.
Valiwie???
Valideren is het controleren van je html en css op 'n hele serie fouten. Computers zijn daar vaak veel beter in dan mensen. Als je 300 keer <h2> hebt gebruikt en 299 keer </h2> vindt 'n computer die ene missende </h2> zonder enig probleem. Jij ook wel, maar daarna ben je misschien wel aan vakantie toe.
Valideren kan helpen om gekmakende fouten te vinden. Valide code garandeert ook dat de weergave in verschillende browsers (vrijwel) hetzelfde is. En valide code is over twintig jaar ook nog te bekijken.
Valideren moet trouwens ook niet worden overdreven. Het is een hulpmiddel om echte fouten te vinden, meer niet. Het gaat erom dat je site goed werkt, niet dat je het braafste kind van de klas bent. Als de code niet valideert, maar daar is een goede reden voor, is daar niets op tegen.
Op deze site is alle css en html gevalideerd. Als de code niet helemaal valide is (wat regelmatig voorkomt), staat daar onder Bekende problemen (en oplossingen) de reden van.
Je kunt je css en html valideren als 't online staat, maar ook als het nog in je computer staat.
html kun je valideren op: validator.w3.org/nu.
css kun je valideren op: jigsaw.w3.org/css-validator.
Toegankelijkheid en zoekmachines
Het eerste deel van deze tekst is voor alle voorbeelden hetzelfde. Eventueel specifiek voor dit voorbeeld geldende dingen staan verderop onder het kopje Specifiek voor dit voorbeeld.
Toegankelijkheid (in het Engels 'accessibility') is belangrijk voor bijvoorbeeld blinden die een schermlezer gebruiken, of voor motorisch gehandicapte mensen die moeite hebben met het bedienen van een muis. Een spider van een zoekmachine (dat is het programmaatje dat de site indexeert voor de zoekmachine) is te vergelijken met een blinde. Als je je site goed toegankelijk maakt voor gehandicapten, is dat gelijk goed voor een hogere plaats in een zoekmachine. Dus als je 't niet uit sociale motieven wilt doen, kun je 't uit egoïstische motieven doen.
(Op die plaats in de zoekmachine heb je maar beperkt invloed. De toegankelijkheid van je site is maar één van de factoren, maar zeker niet onbelangrijk.)
Als je bij het maken van je site al rekening houdt met toegankelijkheid, is dat nauwelijks extra werk. 't Is ongeveer te vergelijken met inbraakbescherming: doe dat bij 'n nieuw huis en 't is nauwelijks extra werk, doe 't bij 'n bestaand huis en 't is al snel 'n enorme klus.
Enkele tips die helpen bij toegankelijkheid:
-
Gebruik altijd een alt-beschrijving bij een afbeelding. De alt-tekst wordt gebruikt, als afbeeldingen niet kunnen worden getoond of gezien (dat geldt dus ook voor zoekmachines). Als je iets wilt laten zien, als je over de afbeelding hovert, gebruik daar dan het title-attribuut voor, niet de alt-beschrijving.
Als een afbeelding alleen maar voor de sier wordt gebruikt, zet je daarbij
alt=""
, om aan te geven dat de afbeelding niet belangrijk is voor het begrijpen van de tekst of zo. Dat kun je ook doen, als uit de tekst bij de afbeelding al duidelijk wordt, wat de afbeelding is. Een alt-tekst zou dan 'n beetje dubbelop zijn. - Als uit de tekst bij een link niet duidelijk blijkt, waar de link naartoe leidt, gebruik dan een title bij de link. Een tekst als 'pagina met externe links' is waarschijnlijk duidelijk genoeg, een tekst als alleen 'links' mogelijk niet. Een duidelijke zwart-witregel is niet te geven, omdat dit ook van tekst en dergelijke in de omgeving van de link afhangt.
-
Accesskeys (sneltoetsen) kun je beter niet gebruiken, deze geven te veel problemen, omdat ze vaak dubbelop zijn met sneltoetsen voor de browser of andere al gebruikte sneltoetsen. Bovendien is voor de gebruiker meestal niet duidelijk, welke toetsen het zijn.
Op zichzelf zijn accesskeys een heel goed idee. Maar helaas zijn ze ook in html5 volstrekt onvoldoende gedefinieerd. Er is nog steeds geen standaard voor de meest gebruikelijke accesskeys, zoals Zoek of Home.
Er is nog steeds niet vastgelegd, hoe accesskeys zichtbaar gemaakt kunnen worden. Voor de makers van browsers zou dit 'n relatief kleine moeite zijn, voor de makers van 'n site is het bergen extra werk.
Voor mij redenen om accesskeys (vrijwel) niet te gebruiken. Ik kan me wel voorstellen dat ze, op sites die gericht zijn op 'n specifieke groep gebruikers, nog enig nut kunnen hebben. Maar voor algemene sites zou ik zeggen: normaal genomen niet gebruiken.
-
Met behulp van de Tab-toets (of op 'n soortgelijke manier) kun je in de meeste browsers door links, invoervelden, en dergelijke lopen. Elke tab brengt je één link, invoerveld, en dergelijke verder, Shift+Tab één plaats terug. Met behulp van het attribuut
tabindex
kun je de volgorde aangeven, waarin de Tab-toets werkt. Zondertabindex
wordt de volgorde van de html aangehouden bij gebruik van de Tab-toets, maar soms is een andere volgorde logischer.In principe is het beter, als
tabindex
niet nodig is, maar gewoon de volgorde van de html wordt aangehouden. Bij verkeerd gebruik kantabindex
heel verwarrend zijn. Het is niet bedoeld om van de pagina een hindernisbaan voor kangoeroes te maken, waarop van beneden via links over rechts naar boven wordt gesprongen. - Als, zoals hierboven beschreven, een gebruiker van de Tab-toets bij een link, invoerveld, en dergelijke is aangekomen, wordt dit aangegeven door de link, invoerveld, en dergelijke extra te markeren met een kadertje. Dat kadertje mag je alleen weghalen, als op een andere manier wordt duidelijk gemaakt, welk element 'focus' heeft. Een gebruiker van de Tab-toets kan anders niet zien, waar zij of hij zit, en welk element gaat reageren op bijvoorbeeld een Enter.
- In het verleden werd vaak aangeraden de volgorde van de code aan te passen. Een menu bijvoorbeeld kon in de html onderaan worden gezet, terwijl het op het scherm met behulp van css bovenaan werd gezet. Inmiddels zijn schermlezers en dergelijke zo sterk verbeterd dat dit niet meer wordt aangeraden. De volgorde in de html kan tegenwoordig beter hetzelfde zijn als die op het scherm, omdat het anders juist verwarrend kan werken.
-
Een zogenaamde skip-link is wel vaak nog zinvol. Dat is een link die je buiten het scherm parkeert met behulp van css, zodat hij normaal genomen niet te zien is. Zo'n link is wel gewoon zichtbaar in speciale programma's zoals tekstbrowsers en schermlezers, want die kijken gewoon naar wat er in de broncode staat.
Een skip-link staat boven menu, header, en dergelijke en linkt naar de eigenlijke inhoud van de pagina, zodat mensen met één toetsaanslag naar de eigenlijke inhoud van de pagina kunnen gaan.
Een skip-link is vooral nuttig voor gebruikers van de Tab-toets. Zodra de normaal genomen onzichtbare link door het indrukken van de Tab-toets focus krijgt, kun je hem op het scherm plaatsen, waardoor hij zichtbaar wordt. Bij een volgende tab wordt hij dan weer buiten het scherm geplaatst en is dus niet meer zichtbaar, zodat de lay-out niet wordt verstoord.
Op pagina's en in voorbeelden waar dat nuttig is, wordt op deze site een skip-link gebruikt. (Althans: nog niet in alle voorbeelden die daarvoor in aanmerking komen, zit een skip-link. Maar geleidelijk aan worden dat er steeds meer.)
-
Van oorsprong is html een taal om wetenschappelijke documenten weer te geven, pas later is hij gebruikt voor lay-out. Maar daar is hij dus eigenlijk nooit voor bedoeld geweest. Het gebruiken van html voor lay-out leidt tot enorme problemen voor gehandicapten en tot een lage plaats in zoekmachines.
De html hoort alleen inhoud te bevatten, lay-out doe je met behulp van css. Die css moet in een externe stylesheet staan of, als hij alleen voor één bepaalde pagina van toepassing is, in de <head> van die pagina.
-
Breng een logische structuur aan in je document. Gebruik een <h1> voor de belangrijkste kop, een <h2> voor een subkop, enzovoort. Schermlezers en dergelijke kunnen van kop naar kop springen. En een zoekmachine gaat ervan uit dat <h1> belangrijke tekst bevat.
Dit geldt voor al dit soort structuurbepalende tags.
Als een <h1> te grote letters geeft, maak daar dan met behulp van je css 'n kleinere letter van, maar blijf die <h1> gewoon gebruiken. Op dezelfde manier kun je al dit soort dingen oplossen.
- <table> is fantastisch, maar alleen als die wordt gebruikt om een echte tabel weer te geven, niet als hij voor opmaak wordt misbruikt. In het verleden is dat op grote schaal gebeurd bij gebrek aan andere mogelijkheden. Een tabel is, als je niet heel erg goed oplet, volstrekt ontoegankelijk voor gehandicapten en zoekmachines. Het lezen van een tabel is ongeveer te vergelijken met het lezen van een krant van links naar rechts: niet per kolom, maar per regel. Dat gaat dus alleen maar goed bij een echte tabel, zoals een spreadsheet. In alle andere gevallen garandeert 'n tabel volstrekte ontoegankelijkheid voor schermlezers en dergelijke en als extra bonus vaak 'n lagere plaats in een zoekmachine.
-
Frames horen bij een volstrekt verouderde techniek, die heel veel nadelen met zich meebrengt. <iframe>'s hebben voor een deel dezelfde nadelen. Eén van die nadelen is dat de verschillende frames voor zoekmachines, schermlezers, en dergelijke als los zand aan elkaar hangen, omdat ze los van elkaar worden weergegeven. Ze staan wel naast elkaar op het scherm, maar er zit intern geen verband tussen.
Als je 'n stuk code vaker wilt gebruiken, zoals 'n menu dat op elke pagina hetzelfde is, voeg dat dan in met PHP of SSI. Dan wordt de pagina niet pas in de browser, maar al op de server samengesteld. Hierdoor zien zoekmachines, schermlezers, en dergelijke één pagina, net zoals wanneer je maar één pagina met html zou hebben geschreven.
(Je kunt beter PHP dan SSI gebruiken, omdat SSI min of meer aan het uitsterven is en PHP veel meer mogelijkheden heeft. Op deze site wordt in enkele voorbeelden nog SSI gebruikt, maar zodra die worden bijgewerkt, gaat dat vervangen worden door PHP.)
- Geef de taal van het document aan, en bij woorden en dergelijke die afwijken van die taal de afwijkende taal met behulp van
lang="..."
. Op deze site gebeurt dat maar af en toe, omdat de tekst (en vooral de code) een mengsel is van Engels, Nederlands en eigengemaakte namen. Dat soort teksten is gewoon niet goed in te delen in een taal. Maar bij enigszins 'normale' teksten hoor je een taalwisseling aan te geven. - Gebruik de tag <abbr> bij afkortingen. Doe dat de eerste keer op een pagina samen met de title-eigenschap:
<abbr title="ten opzichte van">t.o.v.</abbr>
. Daarna kun je op dezelfde pagina volstaan met<abbr>t.o.v.</abbr>
. Doe je dit niet, dan is er 'n grote kans dat 'n schermlezer 't.o.v.' uit gaat spreken als 'tof', en 'n zoekmachine kan er ook geen chocola van maken. -
De spider van 'n zoekmachine, schermlezers, en dergelijke kunnen geen plaatjes 'lezen'. Het is soms verbazingwekkend om te zien hoe veel, of eigenlijk: hoe weinig tekst er overblijft op een pagina, als de plaatjes worden weggehaald. Hetzelfde geldt voor die fantastisch mooie flash-pagina's, als daarbij geen voorzieningen voor dit soort programma's zijn aangebracht.
Op Linux kun je met Lynx kijken, hoe je pagina eruitziet zonder plaatjes en dergelijke, als echt alleen de tekst overblijft. Een installatie-programma voor Lynx op Windows is te vinden op invisible-island.net/lynx.
Ook kun je in Windows het gratis programma WebbIE installeren. WebbIE laat de pagina zien, zoals een tekstbrowser en dergelijke hem zien. WebbIE is te downloaden vanaf www.webbie.org.uk.
-
Ten slotte kun je je pagina nog online laten controleren op 'n behoorlijk aantal sites, zoals:
lowvision.support Laat zien hoe een kleurenblinde de site ziet. Engelstalig.
wave.webaim.org Deze laat grafisch zien hoe de toegankelijkheid is. Engelstalig.
Op de pagina met links kun je onder Toegankelijkheid links naar testen en dergelijke vinden.
Specifiek voor dit voorbeeld
Deze constructie heeft geen invloed op de toegankelijkheid. Zonder css zie je gewoon de tekst zonder opmaak. Schermlezers lezen gewoon de tekst voor in de volgorde, zoals deze in de html staat.
Getest in
Laatst gecontroleerd op 6 juni 2017.
Onder dit kopje staat alleen maar, hoe en waarin is getest. Eventuele problemen, ook die met betrekking tot zoomen en lettergroottes, staan hieronder bij Bekende problemen (en oplossingen). Het is belangrijk dat deel te lezen, want uit een test kan ook prima blijken dat iets totaal niet werkt!
Eventuele opmerkingen over de toegankelijkheid specifiek voor dit voorbeeld staan hierboven bij Toegankelijkheid en zoekmachines onder het kopje Specifiek voor dit voorbeeld.
Dit voorbeeld is getest op de volgende systemen:
Desktopcomputers
Windows 7 (1280 x 1024 px, resolution: 96 dpi):
Firefox, UC Browser, Google Chrome en Internet Explorer 11, in grotere en kleinere browservensters.
OS X 10.11.6 ('El Capitan') (1680 x 1050 px, resolution: 96: dpi, device-pixel-ratio: 1):
Firefox, Safari en Google Chrome, in grotere en kleinere browservensters.
Linux (Kubuntu 14.04 LTS, 'Trusty Tahr') (1280 x 1024 px, resolution: 96 dpi):
Firefox en Google Chrome, in grotere en kleinere browservensters.
Laptops
Windows 8.1 (1366 x 768 px, resolution: 96 dpi):
Bureaublad-versie: Firefox, UC Browser, Google Chrome en Internet Explorer 11, in grotere en kleinere browservensters.
Startscherm-versie: Internet Explorer 11.
Windows 10 (1600 x 900 px, resolution: 96 dpi):
Firefox, UC Browser, Google Chrome, Internet Explorer 11, Edge, in grotere en kleinere browservensters.
Tablets
iPad met iOS 9.3.5 (1024 x768 px, device-pixel-ratio: 1):
Safari, Chrome for iOS, UC Browser, Firefox (alle portret en landschap).
Opera Mini (turbo mode) portret en landschap.
iPad met iOS 10.3.2 (2048 x 1536 px, device-pixel-ratio: 2 ('retina'):
Safari, Chrome for iOS, UC browser, Firefox (alle portret en landschap).
Opera Mini (turbo mode) portret en landschap.
Android 4.4.2 ('Kitkat') (1280 x 800 px, resolution: 96 dpi):
Android browser, UC Browser, Firefox en Chrome (alle portret en landschap).
Opera Mini (besparingen uitgeschakeld) portret en landschap.
Android 4.4.2 ('Kitkat') (2560 x 1600 px, resolution: 192 dpi):
Android browser, UC Browser, Firefox en Chrome (alle portret en landschap).
Opera Mini (besparingen uitgeschakeld) portret en landschap.
Android 5.0.1 ('Lollipop') (1920 x 1200 px, resolution: 144 dpi):
Dolphin, UC Browser, Firefox en Chrome (alle portret en landschap).
Opera Mini (besparingen uitgeschakeld) portret en landschap.
Android 7.0 ('Nougat') (1920 x 1200 px, resolution: 144 dpi):
Dolphin, Samsung Internet, UC Browser, Firefox en Chrome (alle portret en landschap).
Opera Mini (besparingen uitgeschakeld) portret en landschap.
Smartphones
Windows Phone 8.1 (800 x 480 px, resolution: 136 dpi):
Internet Explorer en UC browser (portret en landschap).
Windows 10 Mobile (1280 x 720 px, resolution: 192 dpi):
Edge en UC browser (portret en landschap).
Android 4.1.2 ('Jelly Bean') (800 x 480 px, resolution: 144 dpi):
Chrome, Android browser, UC Browser en Firefox (alle portret en landschap).
Opera Mini (besparingen uitgeschakeld) portret en landschap.
Android 7.0 ('Nougat') (1280 x 720 px, resolution: 192 dpi):
Dolphin, Samsung Internet, UC Browser, Firefox en Chrome (alle portret en landschap).
Opera Mini (besparingen uitgeschakeld) portret en landschap.
Er is op de aan het begin van dit hoofdstukje genoemde controledatum getest in de meest recente versie van de browser, die op het betreffende besturingssysteem kon draaien. Het aantal geteste browsers en systemen is al tamelijk fors, en als ook nog rekening gehouden moet worden met (zwaar) verouderde browsers, is het gewoon niet meer te doen. Surfen met een verouderde browser is trouwens vragen om ellende, want updates van browsers hebben heel vaak met beveiligingsproblemen te maken.
In- en uitzoomen en – voor zover de browser dat kan – een kleinere en grotere letter zijn ook getest. Er is ingezoomd en vergroot tot zover de browser kan, maar niet verder dan 200%.
Er is getest met behulp van muis en toetsenbord, behalve op de iPad, Android, Windows Phone en Windows 10 Mobile, waar een touchscreen is gebruikt. Op Windows 8.1 en 10 is getest met een touchscreen, met een combinatie van toetsenbord en touchpad, en met een combinatie van toetsenbord en muis.
Als dat relevant is, is op de desktop ook getest, als JavaScript uitstaat. Eventuele problemen staan hierboven bij Toegankelijkheid en zoekmachines onder het kopje Specifiek voor dit voorbeeld. (Op iOS, Android, Windows Phone en Windows 10 Mobile is niet getest zonder JavaScript, omdat je JavaScript in een toenemend aantal mobiele browsers niet uit kunt zetten. Bovendien is een mobiel apparaat zonder JavaScript niet veel meer dan een duur en groot uitgevallen horloge.)
Naast deze 'gewone' browsers is ook getest in Lynx, WebbIE, NVDA, TalkBack, VoiceOver en ChromeVox.
Lynx is een browser die alleen tekst laat zien en geen css gebruikt. Er is getest op Linux.
WebbIE is een browser die gericht is op mensen met een handicap. Er is getest op Windows 7.
NVDA is een schermlezer, zoals die door blinden wordt gebruikt. Er is getest in combinatie met Firefox op Windows 7 en Firefox op Windows 10.
TalkBack is een in Android ingebouwde schermlezer. Er is getest in combinatie met Chrome.
VoiceOver is een in iOS en OS X ingebouwde schermlezer. Er is getest in combinatie met Safari op iOS en OS X.
ChromeVox is een schermlezer in de vorm van een extensie bij Google Chrome. Er is getest op een systeem met Kubuntu Linux.
Als het voorbeeld in deze programma's toegankelijk is, zou het in principe toegankelijk moeten zijn in alle aangepaste browsers en dergelijke. En dus ook voor zoekmachines, want een zoekmachine is redelijk vergelijkbaar met een blinde. Eventuele opmerkingen over de toegankelijkheid specifiek voor dit voorbeeld staan hierboven bij Toegankelijkheid en zoekmachines onder het kopje Specifiek voor dit voorbeeld.
Alleen op de hierboven genoemde systemen en browsers is getest. Er is dus niet getest op bijvoorbeeld 'n Blackberry. De kans is (heel erg) groot dat dit voorbeeld niet (volledig) werkt op niet-geteste systemen en apparaten. Om het wel (volledig) werkend te krijgen, zul je vaak (kleine) wijzigingen en/of (kleine) aanvullingen moeten aanbrengen, bijvoorbeeld met JavaScript.
Er is ook geen enkele garantie dat iets werkt in een andere tablet of smartphone dan hierboven genoemd, omdat fabrikanten in principe de software kunnen veranderen. Dit is anders dan op de desktop, waar browsers altijd (vrijwel) hetzelfde werken, zelfs op verschillende besturingssystemen. Iets wat in Android browser werkt, zal in de regel overal werken in die browser, maar een garantie is er niet. De enige garantie is het daadwerkelijk testen op een fysiek apparaat. En aangezien er duizenden mobiele apparaten zijn, is daar eigenlijk geen beginnen aan.
De html is gevalideerd met de validator van w3c, de css ook. Als om een of andere reden niet volledig gevalideerd kon worden, wordt dat bij Bekende problemen (en oplossingen) vermeld.
Nieuwe browsers worden pas getest, als ze uit het bèta-stadium zijn, omdat er anders 'n redelijke kans is dat je tegen 'n bug zit te vechten, die voor de uiteindelijke versie nog gerepareerd wordt. Dit voorbeeld is alleen getest in de hierboven met name genoemde browsers. Vragen over niet-geteste browsers kunnen niet worden beantwoord, en het melden van fouten in niet-geteste browsers heeft ook geen enkel nut. (Melden van fouten, problemen, enzovoort in wel geteste browsers: graag!)
Bekende problemen (en oplossingen)
Waarop en hoe is getest, kun je gelijk hierboven vinden bij Getest in.
Als je hieronder geen oplossing vindt voor een probleem dat met dit voorbeeld te maken heeft, kun je op het forum proberen een oplossing te vinden voor je probleem. Om forumspam te voorkomen, moet je je helaas wel registreren, voordat je op het forum een probleem kunt aankaarten.
Alle browsers
Bij het centreren van de pagina met flexbox verdwijnt de bovenkant
Flexbox is niet geschikt om een hele pagina verticaal mee te centreren.
Als de pagina hoger wordt dan het venster van de browser, verdwijnt in Internet Explorer (alle versies) en Dolphin een deel van de pagina aan de bovenkant van het venster. De pagina staat nog steeds verticaal gecentreerd, maar juist daardoor staat een deel boven het venster. Aan de onderkant is dat geen probleem, omdat gescrold kan worden, maar aan de bovenkant verdwijnt een deel echt volledig.
Als wordt ingezoomd (vergroot) en de pagina wordt daardoor hoger dan het venster van de browser, gebeurt dit in een groot deel van de browsers.
Omdat gebruikers kunnen inzoomen, de lettergrootte kunnen verhogen, en dergelijke, heb je nooit volledig controle over de hoogte van de pagina. Daarom is alleen de methode met de css-tabel geschikt voor het verticaal centreren van de hele pagina, want daarin speelt dit probleem niet.
Bij het centreren van de pagina met translateY() verdwijnt de bovenkant
De transform
-functie translateY()
is niet geschikt om een hele pagina verticaal mee te centreren.
Als je deze methode gebruikt, wordt de pagina eerst halverwege de hoogte van het browservenster gezet. Daarna wordt de pagina de helft van de hoogte van de pagina terug naar boven gezet. Als de pagina hoger is dan het venster, verdwijnt hierdoor in alle browsers een deel van de pagina aan de bovenkant van het venster.
Aan de onderkant steekt de pagina ook uit, maar dat is geen probleem, omdat daar kan worden gescrold. Boven het browservenster kan echter niet worden gescrold: wat daar verdwijnt, is echt weg.
Omdat gebruikers kunnen inzoomen, de lettergrootte kunnen verhogen, en dergelijke, heb je nooit volledig controle over de hoogte van de pagina. Daarom is alleen de methode met de css-tabel geschikt voor het verticaal centreren van de hele pagina, want daarin speelt dit probleem niet.
Bij het centreren van een element met translateY() verdwijnt de bovenkant
Dit is precies hetzelfde probleem dat gelijk hierboven bij het centreren van de pagina wordt beschreven. Als je met deze methode iets verticaal wilt centreren, zorg dan dat de tekst minstens twee keer zo groot kan worden gemaakt, voordat het niet meer in de ouder van het te centreren element past.
Als je de methode met flexbox of de css-tabel gebruikt, is er geen risico dat er iets verdwijnt. Bij die methodes komt het te centreren element nooit boven de ouder uit, maar wordt de ouder eventueel hoger gemaakt, als dat nodig is.
Bij gebruik van translateY() verdwijnen erop volgende elementen
Iets kan alleen verdwijnen, als het op dezelfde plaats op het scherm staat. Dus op een of andere manier staan er dan twee (of meer) elementen op dezelfde plaats.
Normaal genomen bepaalt de volgorde van de html, welk element bovenaan komt te staan en dus volledig zichtbaar is. Wat het laatst in de html staat, komt bovenaan te staan.
Bij gebruik van een transform
-functie werkt dat echter anders. Als je een van de transform
-functies gebruikt, is dat vergelijkbaar met het gebruik van bijvoorbeeld position: relative;
. Een gepositioneerd element komt vaak boven een niet-gepositioneerd element te staan, ongeacht de volgorde in de html.
Het element dat op dezelfde plaats staat als het met translateY()
verplaatste element, zal daardoor verdwijnen. Door aan het verdwenen element in de css position: relative;
toe te voegen, krijgt het verdwenen element zelf ook een positie en zal het weer bovenaan staan.
Als je position
niet kunt gebruiken, kun je ook opacity: 0.99;
gebruiken. Dat heeft hetzelfde effect als position: relative;
. Omdat de doorzichtigheid maar 0,01 is, is dat verder met het blote oog niet te zien.
UC browser op Android en Android browser
Flexbox wordt niet ondersteund
Dit is niet helemaal correct. Flexbox wordt wel ondersteund, maar dan een oudere versie. Die is bovendien zo onvolledig en foutief geïmplementeerd, dat flexbox in deze browsers feitelijk onbruikbaar is. Als het geen onoverkomelijke problemen oplevert, zou je flexbox gewoon kunnen gebruiken en deze browsers negeren. In deze browsers ziet het er dan anders uit, maar alles is gewoon aanwezig. Dat is in dit voorbeeld gebeurd.
De rechterhelft van de pagina ziet er in dit voorbeeld in deze browsers anders uit. Op de afbeelding hieronder is links te zien, hoe het er in UC browser op Android en Android browser uitziet. Rechts is te zien, hoe het eruit zou moeten zien (en hoe het er in alle andere browsers ook echt uitziet).
De middelste witte <div> staat niet verticaal gecentreerd, maar bovenaan. Bij de <div> rechts mist een deel van de witte achtergrond, en de border staat niet rondom de <div>, maar is in elkaar geklopt tot een lijntje bovenaan. Er verdwijnt echter geen tekst of zo, dus in dit geval zou is flexbox gewoon gebruikt. Dat het er anders uitziet: jammer dan.
Overigens wordt UC browser regelmatig geüpdatet en Android browser wordt al tijden niet meer geleverd en verdwijnt in rap tempo, dus binnen niet al te lange tijd zou dit probleem vanzelf moeten zijn verdwenen.
Wijzigingen
Alleen grotere wijzigingen worden hier vermeld, geen dingen als een link die is geüpdatet.
:
Nieuw opgenomen.
6 juni 2017:
Omdat de code volledig is gewijzigd, zijn eerdere wijzigingen verwijderd. Die wijzigingen zijn inmiddels zelf ook weer gewijzigde wijzigingen die gewijzigd zijn, of helemaal verdwenen, vandaar. Hieronder staan de belangrijkste verschillen met vorige versies.
- Alle aanpassingen voor Internet Explorer 10 en eerder zijn verdwenen.
- Documenttype veranderd van xhtml naar html5.
- In browservensters smaller dan 760 px en/of lager dan 500 px wordt niet gecentreerd.
- Manieren om met flexbox en
transform: translateY()
verticaal te centreren toegevoegd.
Inhoud van de download en licenties
De inhoud van deze download kan vrij worden gebruikt, met drie beperkingen:
* Sommige onderdelen die van 'n andere site of zo afkomstig zijn, vallen mogelijk onder een of andere licentie. Dat is hieronder bij het betreffende onderdeel te vinden.
* Je gebruikt het materiaal uit deze download volledig op eigen risico. Het kan prima zijn dat er fouten in de hier verstrekte code en dergelijke zitten. Voor eventuele schade die door gebruik van materiaal uit deze download ontstaat, in welke vorm dan ook, zijn www.css-voorbeelden.nl en medewerkers daarvan op geen enkele manier verantwoordelijk.
* Dit voorbeeld (en de bijbehorende uitleg en dergelijke) wordt regelmatig bijgewerkt. Het is daarom niet toegestaan dit voorbeeld (en de bijbehorende uitleg en dergelijke) op welke manier dan ook te verspreiden, zonder daarbij duidelijk te vermelden dat voorbeeld, uitleg, en dergelijke afkomstig zijn van www.css-voorbeelden.nl en dat daar altijd de nieuwste versie is te vinden. Dit is om te voorkomen dat er verouderde versies worden verspreid.
Een link naar www.css-voorbeelden.nl wordt trouwens altijd op prijs gesteld.
positioneren-007-118-dl.html: de pagina met het voorbeeld.
positioneren-007.pdf: deze uitleg (aangepast aan de inhoud van de download).
positioneren-007-inhoud-download-en-licenties.txt: een kopie van de tekst onder dit kopje (Inhoud van de download en licenties).
007-css-dl:
positioneren-007-dl.css: stylesheet voor positioneren-007.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.
Deze uitleg hoort bij het voorbeeld dat in de download zit. Het voorbeeld uit de download verschilt iets van het voorbeeld hier op de site. In de download ontbreekt bijvoorbeeld de navigatie voor de site. Ook in de kopregels zit vaak wat verschil. Daarnaast kunnen er nog andere (meestal kleine) verschillen zijn.
Als je deze uitleg leest naast de broncode van het voorbeeld op de site, kan het dus bijvoorbeeld zijn dat 'n <h1> uit de css bij 'n <h2> uit de html hoort. Maar het gaat niet om hele grote, fundamentele afwijkingen.
Als je dit lastig vindt, kun je bovenaan de pagina de hele handel downloaden. In de download zit 'n voorbeeld dat wel naadloos aansluit op de uitleg in de download.
<!DOCTYPE html>
Een document moet met een doctype beginnen om weergaveverschillen tussen browsers te voorkomen. Zonder doctype is de kans op verschillende (en soms volkomen verkeerde) weergave tussen verschillende browsers heel erg groot.
Geldige doctypes vind je op www.w3.org/QA/2002/04/valid-dtd-list.
Gebruik het volledige doctype, inclusief de eventuele url, anders werkt het niet goed.
Het hier gebruikte doctype is dat van html5. Dit kan zonder enig probleem worden gebruikt: het werkt zelfs in Internet Explorer 6.
<html lang="nl">
De toevoeging lang="nl"
bij <html> geeft aan dat de pagina in het Nederlands is. De taal is van belang voor schermlezers, automatisch afbreken, automatisch genereren van aanhalingstekens, juist gebruik van decimale punt of komma, en dergelijke.
<meta charset="utf-8">
Zorgt dat de browser letters met accenten en dergelijke goed kan weergeven.
utf-8 is de beste charset (tekenset), omdat deze alle talen van de wereld (en nog heel veel andere extra tekens) bestrijkt, maar toch niet meer ruimte inneemt voor de code, dan nodig is. Als je utf-8 gebruikt, hoef je veel minder entiteiten (ä
en dergelijke) te gebruiken, maar kun je bijvoorbeeld gewoon ä gebruiken.
Deze regel moet zo hoog mogelijk komen te staan, als eerste regel binnen de head, omdat hij anders door sommige browsers niet wordt gelezen.
In html5 hoeft deze regel niet langer te zijn, dan wat hier staat.
<meta name="viewport" content="width=device-width, initial-scale=1">
Mobiele apparaten variëren enorm in breedte. En dat is een probleem. Sites waren, in ieder geval tot voor kort, gemaakt voor desktopbrowsers. En die hebben, in vergelijking met bijvoorbeeld een smartphone, heel brede browservensters. Hoe moet je op 'n smartphone een pagina weergeven, die is gemaakt voor de breedte van een desktop? Je kunt natuurlijk wachten tot álle sites zijn omgebouwd voor smartphones, tablets, enzovoort, maar dan moet je waarschijnlijk heel erg lang wachten.
Mobiele browsers gokken erop dat een pagina een bepaalde breedte heeft. Safari voor mobiel bijvoorbeeld gaat ervan uit dat een pagina 980 px breed is. De pagina wordt vervolgens zoveel versmald dat hij binnen het venster van het apparaat past. Op een iPhone wordt de pagina dus veel smaller dan op een iPad. Vervolgens kan de gebruiker inzoomen op het deel van de pagina dat hij of zij wil zien.
Dit betekent ook dat bij het openen van de pagina de tekst meestal heel erg klein wordt weergegeven. (Meestal, want niet alle browsers en apparaten doen het op dezelfde manier.) Niet erg fraai, maar bedenk maar 'ns 'n betere oplossing voor bestaande sites.
Nieuwe sites of pagina's kunnen echter wel rekening houden met de veel kleinere vensters van mobiele apparaten. In dit voorbeeld wordt in kleinere vensters niet verticaal gecentreerd. Maar die stomme mobiele browser weet dat niet, dus die gaat ervan uit dat ook de al aangepaste pagina 980 px breed is, en verkleint die dan. Dat is ongeveer even behulpzaam als de gedienstige kelner die behulpzaam de stoel naar achteren trekt, net als jij wilt gaan zitten.
Om de door de browser aangeboden hulp vriendelijk maar beslist te weigeren, wordt deze tag gebruikt. Hiermee geef je aan dat de pagina is geoptimaliseerd voor mobiele apparaten.
Een iPad in portretstand bijvoorbeeld is 768 px breed. De kreet width=device-width
zegt tegen de mobiele browser dat de breedte van de weer te geven pagina gelijk is aan de breedte van het apparaat. Voor een iPad in portretstand dus 768 px.
Simpeler gezegd: je zegt tegen het mobiele apparaat dat de pagina geen vaste breedte heeft, en dat het dus niet nodig is om de weergave aan te passen.
Er staat nog een tweede deel in de tag: initial-scale=1
. Sommige mobiele apparaten zoomen een pagina gelijk in of uit. Ook weer in een poging behulpzaam te zijn. Ook dat is hier niet nodig, want de pagina past zich aan het apparaat aan. Er is ook een instructie om zoomen helemaal onmogelijk te maken, maar die wordt niet gebruikt. De bezoeker kan zelf nog gewoon zoomen, wat belangrijk is voor mensen die wat slechter zien.
<link rel="stylesheet" href="007-css-dl/positioneren-007-dl.css">
Dit is een koppeling naar een externe stylesheet (stijlbestand), waarin de css staat. In html5 is de toevoeging type="text/css"
niet meer nodig, omdat dit standaard al zo staat ingesteld. Je moet uiteraard de naam van en het pad naar de stylesheet aanpassen aan de naam en plaats, waar je eigen stylesheet staat.
Voordeel van een externe stylesheet is onder andere dat deze geldig is voor alle pagina's, waaraan deze is gelinkt. 'n Verandering in de lay-out hoef je dan maar in één enkele stylesheet aan te brengen, in plaats van in elke pagina apart. Op een grotere site kan dit ontzettend veel werk schelen. Bovendien hoeft de browser zo'n externe stylesheet maar één keer te downloaden, ongeacht hoeveel pagina's er gebruik van maken. Zou je de css in elke pagina opnieuw aanbrengen, dan worden de te downloaden bestanden veel groter.
In dit voorbeeld heeft een extern stylesheet eigenlijk geen nut, omdat er maar één pagina is die dit stylesheet gebruikt. In dit geval kun je de css beter in de <head> van de html-pagina zelf zetten. Voor de omvang maakt het hier niets uit, want de css wordt hoe dan ook altijd precies één keer gedownload, en nooit vaker. Voor het onderhoud maakt het ook geen verschil, want ook hier hoef je de css maar op één plaats te wijzigen. Maar het scheelt wel een extra aanroep naar de server, omdat geen apart stylesheet hoeft te worden gedownload.
Dat opnemen in de <head> gaat heel simpel: je kopieert gewoon het hele stylesheet en zet die bovenin de <head>, tussen <style> en </style>:
<style>
body {color: black;}
(...) rest van de css (...)
div {color: red;}
</style>
Maar zodra een stylesheet op meerdere pagina's wordt gebruikt, wat meestal het geval zal zijn, is een extern stylesheet beter.
(De reden dat er toch een extern stylesheet is, terwijl hierboven omstandig wordt beweerd dat dat in dit voorbeeld eigenlijk geen nut heeft: overzichtelijkheid. Nu kun je html en css los van elkaar bekijken.)
CSS
De code is geschreven in een afwijkende
lettersoort. De code die te maken heeft met de basis van dit voorbeeld (essentiële code) is in de hele uitleg onderstippeld blauw
. Alle niet-essentiële code is bruin
. (In de inhoudsopgave staat alles in een gewone letter vanwege de leesbaarheid.)
Deze uitleg hoort bij het voorbeeld dat in de download zit. Het voorbeeld uit de download verschilt iets van het voorbeeld hier op de site. In de download ontbreekt bijvoorbeeld de navigatie voor de site. Ook in de kopregels zit vaak wat verschil. Daarnaast kunnen er nog andere (meestal kleine) verschillen zijn.
Als je deze uitleg leest naast de broncode van het voorbeeld op de site, kan het dus bijvoorbeeld zijn dat 'n <h1> uit de css bij 'n <h2> uit de html hoort. Maar het gaat niet om hele grote, fundamentele afwijkingen.
Als je dit lastig vindt, kun je bovenaan de pagina de hele handel downloaden. In de download zit 'n voorbeeld dat wel naadloos aansluit op de uitleg in de download.
Technisch gezien is er geen enkel bezwaar om de css in de stylesheet allemaal achter elkaar op één regel te zetten:
div#header-buiten {position: absolute; right: 16px; width: 100%; height: 120px; background: yellow;} div p {margin-left 16px; height: 120px; text-align: center;}
Maar als je dat doet, garandeer ik je hele grote problemen, omdat het volstrekt onoverzichtelijk is. Beter is het om de css netjes in te laten springen:
div#header-buiten {
position: absolute;
right: 16px;
width: 100%;
height: 120px;
background: yellow;
}
div p {
margin-left: 16px;
height: 120px;
text-align: center;
}
Hiernaast is het heel belangrijk voldoende commentaar (uitleg) in de stylesheet te schrijven. Op dit moment weet je waarschijnlijk (hopelijk...), waarom je iets doet. Maar over vijf jaar kan dat volstrekt onduidelijk zijn. Op deze site vind je nauwelijks commentaar in de stylesheets, maar dat heeft een simpele reden: deze uitleg is in feite één groot commentaar.
Op internet zelf is het goed, als de stylesheet juist zo klein mogelijk is. Dus voor het uploaden kun je normaal genomen het beste het commentaar weer verwijderen. Veel mensen halen zelfs alles wat overbodig is weg, voordat ze de stylesheet uploaden. Inspringingen bijvoorbeeld zijn voor mensen handig, een computer heeft ze niet nodig.
Je hebt dan eigenlijk twee stylesheets. De uitgebreide versie waarin je dingen uitprobeert, verandert, enzovoort, met commentaar, inspringingen, en dergelijke. Dat is de mensvriendelijke versie. Daarnaast is er dan een stylesheet die je op de echte site gebruikt: een gecomprimeerde versie.
Dat comprimeren kun je met de hand doen, maar er bestaan ook hulpmiddelen voor. Op de pagina met links kun je onder Gereedschap → Snelheid, testen, gzip, comprimeren links naar sites vinden, waar je bestanden kunt comprimeren.
(Stylesheets op deze site zijn niet gecomprimeerd. Omdat het vaak juist om de css gaat, kunnen mensen dan zonder al te veel moeite de css bekijken.)
css voor alle vensters
/* positioneren-007-dl.css */
Om vergissingen te voorkomen is het een goede gewoonte bovenaan het stijlbestand even de naam neer te zetten. Voor je het weet, zit je anders in het verkeerde bestand te werken.
body
Het element waarbinnen de hele pagina staat. Veel instellingen die hier worden opgegeven, worden geërfd door de nakomelingen van <body>. Ze gelden voor de hele pagina, tenzij ze later worden gewijzigd. Dit geldt bijvoorbeeld voor de lettersoort, de lettergrootte en de voorgrondkleur.
background: #ff9;
Achtergrondkleurtje.
color: black;
Voorgrondkleur zwart. Dit is onder andere de kleur van de tekst.
Hoewel dit de standaardkleur is, wordt deze toch specifiek opgegeven. Hierboven is een achtergrondkleur opgegeven. Sommige mensen hebben zelf de voor-‑ en/of achtergrondkleur veranderd, bijvoorbeeld omdat ze slecht kleuren kunnen onderscheiden. Als nu de achtergrondkleur wordt veranderd, maar niet de voorgrondkleur, loop je het risico dat tekstkleur en achtergrondkleur te veel op elkaar gaan lijken.
Door beide op te geven, is redelijk zeker dat achtergrond- en tekstkleur genoeg van elkaar blijven verschillen. Als de gebruiker !important
heeft gebruikt in een eigen stylesheet, is er nog niets aan de hand, want dan veranderen achtergrond- en voorgrondkleur geen van beide.
font-family: Arial, Helvetica, sans-serif;
Als Arial is geïnstalleerd op de machine van de bezoeker, wordt deze gebruikt, anders Helvetica. Als die ook niet wordt gevonden, wordt in ieder geval een schreefloze letter (zonder dwarsstreepjes) gebruikt.
margin: 0; padding: 0;
Slim om te doen vanwege verschillen tussen browsers.
#voor-flex
Het element met id="voor-flex". De hele pagina staat binnen <main>. div#voor-flex
is het enige kind van <main>.
Deze <div> is alleen nodig voor grotere browservensters, waarin de pagina met behulp van flexbox verticaal wordt gecentreerd. Om dit te kunnen doen, moet de pagina binnen een zogenaamde 'flex container' staan. Bij #voor-flex wordt deze <div> in zo'n container veranderd. Voor kleinere vensters is deze <div> overbodig. De hieronder staande css zou in kleinere vensters vrij makkelijk aan andere elementen kunnen worden gegeven.
background: yellow;
Gele achtergrond.
color: black;
Voorgrondkleur zwart. Dit is onder andere de kleur van de tekst.
Hoewel dit de standaardkleur is, wordt deze toch specifiek opgegeven. Hierboven is een achtergrondkleur opgegeven. Sommige mensen hebben zelf de voorgrond‑ en/of achtergrondkleur veranderd, bijvoorbeeld omdat ze slecht kleuren kunnen onderscheiden. Als nu de achtergrondkleur wordt veranderd, maar niet de voorgrondkleur, loop je het risico dat tekstkleur en achtergrondkleur te veel op elkaar gaan lijken.
Door beide op te geven, is redelijk zeker dat achtergrond- en tekstkleur genoeg van elkaar blijven verschillen. Als de gebruiker !important
heeft gebruikt in een eigen stylesheet, is er nog niets aan de hand, want dan veranderen achtergrond- en voorgrondkleur geen van beide.
Dit is ook al bij <body> opgegeven, maar sommige mensen hebben bij álle elementen de kleuren veranderd. Het heeft immers weinig zin, als ze dat alleen bij de body doen, terwijl de sitebouwer de kleuren ook bij bijvoorbeeld de paragrafen heeft aangepast.
#links, #midden, #rechts div
De elementen met id="links", id="midden" en de <div>'s binnen het element met id="rechts".
Binnen div#links
zitten tekst en groene blok aan de linkerkant.
Binnen div#midden
zit het kleine witte blokje in het midden met 'Verticaal gecentreerd'.
Binnen div#rechts
zit slechts één <div> met daarin de tekst in het rechter witte blok.
padding: 5px;
Kleine afstand tussen tekst in en rand van de elementen.
h1
Alle <h1>'s. Dat is er maar één: de belangrijkste kop van de pagina.
font-size: 1.3em;
Een <h1> heeft van zichzelf een nogal grote letter, die wordt hier iets kleiner gemaakt.
Als eenheid wordt de relatieve eenheid em
gebruikt, omdat bij gebruik van een absolute eenheid zoals px
niet alle browsers de lettergrootte kunnen veranderen. Zoomen kan wel altijd, ongeacht welke eenheid voor de lettergrootte wordt gebruikt.
#links div
Alle <div>'s binnen het element met id="links". Dat is maar één <div>, de <div> met het blauwe blokje linksonder.
background: #0ff;
Blauwe achtergrondkleur.
color: black;
Voorgrondkleur zwart. Dit is onder andere de kleur van de tekst.
Hoewel dit de standaardkleur is, wordt deze toch specifiek opgegeven. Hierboven is een achtergrondkleur opgegeven. Sommige mensen hebben zelf de voorgrond‑ en/of achtergrondkleur veranderd, bijvoorbeeld omdat ze slecht kleuren kunnen onderscheiden. Als nu de achtergrondkleur wordt veranderd, maar niet de voorgrondkleur, loop je het risico dat tekstkleur en achtergrondkleur te veel op elkaar gaan lijken.
Door beide op te geven, is redelijk zeker dat achtergrond- en tekstkleur genoeg van elkaar blijven verschillen. Als de gebruiker !important
heeft gebruikt in een eigen stylesheet, is er nog niets aan de hand, want dan veranderen achtergrond- en voorgrondkleur geen van beide.
Dit is ook al bij <body> opgegeven, maar sommige mensen hebben bij álle elementen de kleuren veranderd. Het heeft immers weinig zin, als ze dat alleen bij de body doen, terwijl de sitebouwer de kleuren ook bij bijvoorbeeld de paragrafen heeft aangepast.
padding: 5px;
Kleine afstand tussen tekst in en buitenkant van de <div>.
#midden, #rechts
Voor een deel van deze elementen is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat.
#links, #midden, #rechts div {padding: 5px;}
background: white;
Witte achtergrond.
color: black;
Voorgrondkleur zwart. Dit is onder andere de kleur van de tekst.
Hoewel dit de standaardkleur is, wordt deze toch specifiek opgegeven. Hierboven is een achtergrondkleur opgegeven. Sommige mensen hebben zelf de voorgrond‑ en/of achtergrondkleur veranderd, bijvoorbeeld omdat ze slecht kleuren kunnen onderscheiden. Als nu de achtergrondkleur wordt veranderd, maar niet de voorgrondkleur, loop je het risico dat tekstkleur en achtergrondkleur te veel op elkaar gaan lijken.
Door beide op te geven, is redelijk zeker dat achtergrond- en tekstkleur genoeg van elkaar blijven verschillen. Als de gebruiker !important
heeft gebruikt in een eigen stylesheet, is er nog niets aan de hand, want dan veranderen achtergrond- en voorgrondkleur geen van beide.
Dit is ook al bij <body> opgegeven, maar sommige mensen hebben bij álle elementen de kleuren veranderd. Het heeft immers weinig zin, als ze dat alleen bij de body doen, terwijl de sitebouwer de kleuren ook bij bijvoorbeeld de paragrafen heeft aangepast.
width: 180px;
Breedte.
margin: 20px auto 0;
Omdat voor links geen waarde is opgegeven, krijgt links automatisch dezelfde waarde als rechts. Hier staat dus eigenlijk 20px auto 0 auto
in de volgorde boven – rechts – onder – links.
In kleinere browservensters staan div#links
, div#midden
en div#rechts
niet naast, maar onder elkaar. Een marge van 20 px aan de bovenkant voorkomt dat ze tegen elkaar aan komen te staan.
Links en rechts auto
, wat hier hetzelfde betekent als evenveel. Ongeacht hoe breed de ouder is, de <div>'s staan altijd horizontaal gecentreerd binnen hun ouder. Die ouder is hier div#voor-flex
. Omdat div#voor-flex
een blok-element is, wordt dit normaal genomen even breed als z'n ouder <main>, ook een blok-element. Als blok-element wordt ook <main> normaal genomen even breed als z'n ouder <body>, ook weer een blok-element. Ook <body> wordt normaal genomen even breed als z'n ouder <html>. Omdat <html> het buitenste element is, wordt dit normaal genomen even breed als het venster van de browser.
Als je dit hele verhaal in omgekeerde richting volgt, staan div#midden
en div#rechts
hierdoor horizontaal gecentreerd binnen het venster van de browser.
border: black solid 1px;
Zwart randje.
h2
Alle <h2>'s. Dat is er hier maar eentje: het begin van de tekst rechts: 'Met translate gecentreerde tekst'.
display: inline;
Een <h2> is een blok-element. De <h2> komt daardoor normaal genomen op een eigen regel te staan. Door van de <h2> een blok-element te maken, komt de erop volgende tekst op dezelfde regel te staan.
font-size: 1.3em;
Lettergrootte iets kleiner maken dan de standaardlettergrootte van een <h2>.
Als eenheid wordt de relatieve eenheid em
gebruikt, omdat bij gebruik van een absolute eenheid zoals px
niet alle browsers de lettergrootte kunnen veranderen. Zoomen kan wel altijd, ongeacht welke eenheid voor de lettergrootte wordt gebruikt.
css voor vensters minimaal 760 px breed en minimaal 500 px hoog
@media screen and (min-width: 760px) and (min-height: 500px)
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 760 px breed én minimaal 500 px hoog zijn. In deze grotere vensters worden de pagina en enkele <div>'s verticaal gecentreerd.
@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: 760px)
: het venster moet minimaal 760 px breed zijn. Is het venster smaller, dan wordt de css die binnen deze media-regel staat genegeerd.
and
: er komt nog een voorwaarde, waaraan moet worden voldaan.
(min-height: 500px)
: het venster moet minimaal 500 px hoog zijn. Is het venster lager, 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: 760px) and (min-height: 500px) {
body {color: silver;}
(...) rest van de css voor deze @media-regel (...)
footer {color: gold;}
}
Voor de eerste css binnen deze media-regel staat dus een extra {
, en aan het eind staat een extra }
.
Als je nou 'n mobieltje hebt met een resolutie van – ik roep maar wat – 1024 x 768 px, dan geldt deze media query toch niet voor dat mobieltje. Terwijl dat toch echt meer dan 760 px breed en meer dan 500 px hoog is. Een vuig complot van gewetenloze multinationals? Voordat je je gaat beklagen bij Radar, zou ik eerst even verder lezen.
Steeds meer mobiele apparaten, maar ook steeds meer gewone beeldschermen, hebben een hogere resolutiedichtheid. Dat wil zeggen dat ze kleinere pixels hebben, die dichter bij elkaar staan. Daardoor zijn foto's, tekst, en dergelijke veel scherper weer te geven. Hoe kleiner de puntjes (de pixels) zijn, waaruit een afbeelding is opgebouwd, hoe duidelijker het wordt.
Er ontstaat alleen één probleem: als je de pixels twee keer zo klein maakt, wordt ook wat je ziet twee keer zo klein. En inmiddels zijn er al apparaten met pixels die meer dan vier keer zo klein zijn. Een lijntje van 1 px breed zou op die apparaten minder dan 'n kwart van de oorspronkelijke breedte krijgen en vrijwel onzichtbaar zijn. Een normale foto zou in een thumbnail veranderen. Kolommen zouden heel smal worden. Tekst zou onleesbaar klein worden. Allemaal fantastisch scherp, maar je hebt 'n vergrootglas nodig om 't te kunnen zien.
Om dit te voorkomen wordt een verschil gemaakt tussen css-pixels en schermpixels (in het Engels 'device pixels'). De css-pixels zijn gebaseerd op de – tot voor kort – normale beeldschermen van de desktop. 1 css-pixel is op zo'n beeldscherm 1 pixel. Het aantal schermpixels is het werkelijk op het apparaat aanwezige aantal pixels (dat is het aantal pixels, waarvoor je hebt betaald).
Dat eerder genoemde mobieltje van 1024 x 768 px heeft wel degelijk het aantal pixels, waarvoor je hebt betaald. Maar die zitten dichter bij elkaar. Op een gewoon beeldscherm zitten 96 pixels per inch, wat wordt uitgedrukt met de eenheid dpi ('dots per inch'). Als dat mobieltje een resolutie van 192 dpi heeft, 192 pixels per inch, zijn de pixels ervan twee keer zo klein als op een origineel beeldscherm. Er zijn per inch twee keer zoveel schermpixels aanwezig.
Om nu te voorkomen dat alles op dat mobieltje twee keer zo klein wordt, geeft het mobieltje niet het echte aantal schermpixels (1024 x 768), maar een lager aantal css-pixels door bij een media query. De 192 dpi van het mobieltje is twee keer zo veel als de 96 dpi van een normaal beeldscherm. Het aantal css-pixels is dan het aantal schermpixels gedeeld door 2. 1024 x 768 gedeeld door 2 is 512 x 384 px. Het aantal css-pixels is 512 x 384 px en zit daarmee dus ruim onder de 760 px breedte én onder de 500 px hoogte van deze media query.
Je bent dus niet opgelicht, of in ieder geval niet wat betreft het aantal pixel.
Door deze truc is een lijn van 1 px breed op een normaal beeldscherm ook op het mobieltje nog steeds 1 px breed, alleen wordt die ene (css‑)pixel opgebouwd uit twee schermpixels (feitelijk vier, want het verhaal geldt voor breedte én hoogte). De dikte van het lijntje is hetzelfde, maar het is veel fijner opgebouwd. Bij lijntjes is dat verschil bijvoorbeeld in bochten goed te zien.
Hetzelfde verhaal geldt voor hogere resoluties, Een tablet met een breedte van 4096 schermpixels en een dpi van 384 (vier keer de originele dichtheid) geeft 4096 gedeeld door 4 = 1024 css-pixel door. Het lijntje van 1 px breedte op de originele monitor is nog steeds 1 css-pixel breed op de tablet, maar die ene css-pixel is nu opgebouwd uit zestien schermpixel.
(Overigens kun je met behulp van media query's ook testen op de resolutie met gebruik van het sleutelwoord 'resolution'. Apple gebruikt het niet-standaard 'device-pixel-ratio', maar het idee is hetzelfde. Dit kan bijvoorbeeld handig zijn om te bepalen, hoe groot een foto moet zijn.)
Kort samengevat: omdat niet het aantal schermpixels (waarvoor je hebt betaald), maar het aantal css-pixels (de door de ontwerper bedoelde afmeting) wordt doorgegeven, wordt voorkomen dat een hogeresolutiescherm onleesbaar klein wordt.
html
Het buitenste element.
height: 100%;
Een hoogte in procenten geldt normaal genomen ten opzichte van de ouder van het element. Omdat <html> het buitenste element is, geldt de hoogte ten opzichte van het venster van de browser. Hiermee wordt <html> even hoog gemaakt als het venster.
Normaal genomen zou <html> niet hoger worden dan nodig is om de pagina weer te kunnen geven, maar nu wordt <html> even hoog als het venster.
Hier gelijk onder wordt <body> even hoog gemaakt als <html>. Als je nu iets verticaal centreert <body>, staat het ook verticaal gecentreerd binnen het browservenster, want <body> en <html> zijn even hoog als dat venster.
body
Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)
body {background: #ff9; color: black; font-family: Arial, Helvetica, sans-serif; margin: 0; padding: 0;}
display: table;
<body> wordt hiermee van een gewoon blok-element veranderen in een css-tabel. Het enige kind van <body> is <main>, dat bij main wordt veranderd in een css-tabelcel. (De rest van de pagina staat allemaal binnen <main>). Dan heb je dus eigenlijk dit:
<body>(gedraagt zich als <table>)
<main>(gedraagt zich als <td>)
(...) rest van de pagina (...)
</main>
</body>
Missende elementen van de tabel, zoals de <tr> rondom de <td>, worden automatisch door de browser aangemaakt.
Anders dan bij een html-tabel, waarbij je daadwerkelijk elementen als <table> gebruikt, levert een css-tabel geen problemen op wat betreft zoekmachines, toegankelijkheid, en dergelijke. De html bestaat nog steeds uit volstrekt gangbare <div>'s en dergelijke. Alleen voor de weergave, voor het uiterlijk, wordt gedaan alsof <body> een tabel en <main> een tabelcel is.
Het voordeel hiervan: de inhoud van een tabelcel kan makkelijk verticaal worden gecentreerd met vertical-align: middle;
, ook als de hoogte van de inhoud van de tabelcel onbekend is.
Deze methode met behulp van een tabel is de enige veilige manier om een hele pagina verticaal te centreren. Bij gebruik van flexbox of translateY()
kan een deel van de pagina aan de bovenkant van het browservenster verdwijnen, waarover meer bij Bekende problemen (en oplossingen) is te vinden. Bij deze methode loop je dat risico niet, want de tabel komt nooit boven het venster uit. Als de pagina hoger is dan het venster, komt het te hoge deel gewoon onder het venster te staan en kan worden bereikt door te scrollen.
width: 750px;
Breedte. Zonder 'n breedte kan de pagina in bredere browservensters wanstaltig breed worden, waardoor tekst veel te breed en daardoor slecht leesbaar kan worden.
height: 100%;
Een hoogte in procenten is normaal genomen ten opzichte van de ouder. Die ouder is hier <html>, die hierboven bij html even hoog als het venster van de browser is gemaakt. Normaal genomen wordt <body> precies hoog genoeg om de pagina weer te kunnen geven, maar nu wordt <body> even hoog als <html> en daarmee ook even hoog als het venster.
De rest van de pagina staat allemaal binnen <main>. Als <main> verticaal wordt gecentreerd binnen <body>, staat daarmee de hele pagina verticaal gecentreerd binnen het venster van de browser, omdat <body> even hoog is als het venster.
font-size: 110%;
Iets groter dan standaard. 't Zal de leeftijd zijn, maar ik vind de standaardgrootte wat te klein.
Als eenheid wordt de relatieve eenheid % gebruikt, omdat bij gebruik van een absolute eenheid zoals px niet alle browsers de lettergrootte kunnen veranderen. Zoomen kan wel altijd, ongeacht welke eenheid voor de lettergrootte wordt gebruikt.
margin: 0 auto;
Omdat voor onder en links geen waarden zijn 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 <body> altijd horizontaal gecentreerd binnen z'n ouder, ongeacht de breedte van die ouder. Die ouder is hier <html>, het buitenste element en daarom normaal genomen even breed als het venster van de browser. Uiteindelijk staat <body> hierdoor horizontaal gecentreerd binnen het venster.
main
Het element waarin de belangrijkste inhoud van de pagina staat. In het voorbeeld is dat de hele pagina.
display: table-cell;
Verander <main> van een blok-element in een css-tabelcel. Dit heeft verder geen enkele invloed op zoekmachines, toegankelijkheid, en dergelijke, omdat het alleen om de weergave gaat. Een iets uitgebreider verhaal hierover staat iets hierover bij display: table; waar <body> wat betreft de weergave in een css-tabel wordt veranderd.
vertical-align: middle;
Een tabelcel is heel simpel verticaal te centreren binnen de tabel, ook als de hoogte onbekend is. De ouder van <main> is <body>. Die is bij body wat betreft de weergave veranderd in een tabel die even hoog is als het venster van de browser. Door de in een tabelcel veranderde <main> verticaal te centreren binnen <body> staat <main> – en daarmee de hele zichtbare inhoud van de pagina – verticaal gecentreerd binnen het venster.
#voor-flex
Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)
voor-flex {background: yellow; color: black; max-width: 98%; border: black solid 1px;}
Het element met id="voor-flex". Deze <div> is nodig om flexbox te kunnen gebruiken.
display: flex;
Hiermee wordt van div#voor-flex
een zogenaamde 'flex container' gemaakt. Binnen een flex container gelden voor de directe kinderen, de zogenaamde 'flex items', aparte regels voor dingen als hoogte, positie, marges, en dergelijke.
Normaal genomen zou deze <div> overbodig zijn, omdat display: flex;
ook bij <main> zou kunnen worden gezet. De andere css hieronder is ook wel elders onder te brengen. Maar bij <main> staat al display: table-cell;
, dus display: flex;
kan daar niet meer worden gebruikt.
Alleen de directe kinderen van een flex container zijn flex items. Alleen daarvoor gelden de speciale regels. Hieronder staat de ingekorte html van dit voorbeeld, die binnen div#voor-flex
staat:
<div id="voor-flex">
<div id="links">
<h1>Verticaal gecentreerde (...) </h1>
<p>De pagina (...) </p>
<div>Ik ben (...) </div>
</div>
<div id="midden">Verticaal (...) </div>
<div id="rechts">
<div>
<h2>Met (...) tekst</h2> binnen een (...) achtergrond.
</div>
</div>
</div>
Van de elementen hierboven zijn alleen div#links
, div#midden
en div#rechts
directe kinderen van div#voor-flex
. Alleen deze drie <div>'s zijn dus flex items. Alle andere elementen hierboven zijn een nakomeling van een van deze drie <div>'s. Het zijn geen directe kinderen van div#voor-flex
en daarom geen flex items.
align-items: center;
Hiermee worden de directe kinderen van flex container div#voor-flex
, de flex items, verticaal gecentreerd. Ook als de hoogte daarvan onbekend is. Meer is niet nodig. Die directe kinderen zijn hier div#links
, div#midden
en div#rechts
.
Omdat flexbox speciaal voor dit soort dingen is bedoeld, is het echt uiterst handig in gebruik. Zonder enig gedoe kun je elementen met onbekende hoogte verticaal centreren. Dit kun je trouwens desgewenst per element weer overrulen, door bij het betreffende flex item zelf iets anders op te geven.
Dat div#voor-flex
, de flex container, ook geen hoogte heeft, is geen enkel probleem. Op het moment van weergave weet de browser de hoogte, resolutie, en dergelijke van browservenster en scherm. Daardoor kan de browser de hoogte van div#voor-flex
en de flex items berekenen en de flex items verticaal centreren. Ook al heeft geen van de elementen een vaste hoogte.
Omdat div#links
, de <div> met de tekst links en het blauwe blok, de hoogste is van de drie flex items, bepaalt deze <div> de hoogte van de flex container, van div#voor-flex
. Deze <div> is daardoor per definitie even hoog als div#voor-flex
en kan dus niet verticaal worden gecentreerd. Althans: formeel theoretisch is div#links
verticaal gecentreerd, maar dat kun je niet zien.
div#midden
, het middelste witte blokje, wordt wel verticaal gecentreerd door deze regel.
div#rechts
, het witte blok rechts wordt ook niet echt verticaal gecentreerd door deze regel. Bij #rechts wordt dit flex item namelijk met align-self: stretch;
even hoog gemaakt als <main>, de flex container. Normaal genomen zou deze <div> niet hoger worden dan nodig is voor de weergave van de erin zittende tekst.
Dat de <div> toch gecentreerd lijkt, komt door een marge aan boven- en onderkant van div#rechts
.
overflow: hidden;
Browsers die flexbox niet ondersteunen, zetten div#rechts
, div#midden
en div#links
gewoon op een nieuwe regel:
Ook allerlei andere dingen gaan mis, zoals de breedte bij div#midden
. Om flexbox zoveel mogelijk te imiteren voor deze oudere browsers, worden div#links
en div#midden
daarom naar links en div#rechts
naar rechts gefloat.
Dat levert het volgende resultaat op:
We zien hier in al z'n glorie één van de problemen die door flexbox worden opgelost. div#voor-flex
heeft drie kinderen, die alle drie worden gefloat. Normaal genomen zou div#voor-flex
precies hoog genoeg worden om de inhoud ervan weer te geven. Maar als die inhoud alleen uit gefloate elementen bestaat, gebeurt dat niet. div#voor-flex
heeft geen enkele hoogte. De border staat daardoor bovenaan div#voor-flex
als 'n dubbel streepje. Het rechter witte blok wordt absoluut gepositioneerd ten opzichte van div#voor-flex
. Omdat div#voor-flex
geen hoogte heeft, gaat ook dat mis.
Door overflow: hidden;
bij div#voor-flex
te zetten, wordt #voor-flex
toch hoog genoeg om de inhoud weer te geven. Hierdoor wordt niet alles opgelost, maar het kader rondom #voor-flex staat weer goed, er is een achtergrondkleur en het rechter witte blokje staat niet meer te hoog.
Normaal genomen moet je voorzichtig zijn met overflow: hidden;
, want als de inhoud niet in het element past, kan niet worden gescrold. Het teveel verdwijnt gewoon aan de onderkant. Hier kan het echter veilig worden gebruikt, want div#voor-flex
heeft geen hoogte gekregen. Als de inhoud van #voor-flex hoger wordt, kan #voor-flex hierdoor gewoon ook hoger worden.
Als een browser flexbox wel ondersteunt, heeft deze regel geen enkele invloed. Een float wordt binnen flexbox volledig genegeerd. In browsers die flexbox ondersteunen, levert floaten dus geen enkel probleem op.
border: black solid 1px;
Zwart randje.
position: relative;
Om een nakomeling van een element te kunnen positioneren ten opzichte van dat element, moet het element zelf een positie hebben. Omdat er verder niets wordt opgegeven bij top
en dergelijke, heeft dit geen invloed op het element zelf.
De nakomeling die gepositioneerd moet worden is #rechts div
, de <div> binnen div#rechts
. Normaal genomen zou je dan div#rechts
een relatieve positieve geven en de binnen #rechts div
positioneren ten opzichte van z'n ouder div#rechts
. Dat kan hier echter niet.
De <div> binnen div#rechts
moet halverwege de hoogte van div#rechts
komen te staan. Bij #rechts wordt div#rechts
, een flex item, met align-self: stretch;
even hoog gemaakt als de flex container div#voor-flex
. Maar dit werkt niet in browsers die flexbox niet kennen. Daarin heeft div#rechts
helemaal geen hoogte, dus er kan ook niets halverwege de hoogte van div#rechts
worden gezet.
Bovendien werkt align-self: stretch;
bij div#rechts
niet goed in alle browsers die flexbox wel ondersteunen. Weliswaar krijgt div#rechts
overal de goede hoogte, maar als je vervolgens de <div> in div#rechts
op de halve hoogte van div#rechts positioneert, blijken veel browsers toch te denken, dat div#rechts
geen hoogte heeft.
Door te positioneren ten opzichte van div#voor-flex
, werkt het overal goed.
#links
Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)
#links, #midden, #rechts div {padding: 5px;}
Het element met id="links". De <div> waarbinnen de tekst links en het blauwe vlak zitten.
Normaal genomen wordt een <div> op een eigen regel gezet, maar omdat de ouder div#voor-flex
met display: flex;
bij #voor-flex in een zogenaamde 'flex container' is veranderd, is div#links
in een zogenaamd 'flex item' veranderd. Daardoor kunnen, als je dat wilt, <div>'s op dezelfde regel blijven staan. Hier is dat het geval.
width: 400px;
Breedte.
float: left;
Browsers die flexbox niet ondersteunen, zouden de <div> gewoon op een eigen regel zetten. Door de <div> naar links te floaten, wordt dat voorkomen. Browsers die flexbox kennen, negeren een float bij een flex item.
#links div
Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)
#links div {background: #0ff; color: black; padding: 5px;}
De <div>'s binnen het element met id="links". Dat is er hier maar eentje: de <div> met het blauwe blok.
width: 87%;
Breedte. Een breedte in procenten is normaal genomen ten opzichte van de ouder van het element, dat is hier div#links
.
Waarom 87%? Daar is geen reden voor, vrees ik. Mocht ik ooit nog, na grondig zelfonderzoek, een diep verborgen reden vinden, dan zal ik dat alsnog onmiddellijk melden. Als je geluksgetal 83 of 93 is, dan kun je ook dat percentage veilig gebruiken.
#midden
Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)
#links, #midden, #rechts div {padding: 5px;}
#midden, #rechts {background: white; color: black; width: 180px; margin: 20px auto 0; border: black solid 1px;}
Het element met id="midden". De <div> met het kleine witte blokje in het midden.
Normaal genomen wordt een <div> op een eigen regel gezet, maar omdat de ouder div#voor-flex
met display: flex;
bij #voor-flex in een zogenaamde 'flex container' is veranderd, is div#midden
in een zogenaamd 'flex item' veranderd. Daardoor kunnen, als je dat wilt, <div>'s op dezelfde regel blijven staan. Hier is dat het geval.
Met align-items: center;
is bij #voor-flex opgegeven dat de flex items, waaronder deze <div>, verticaal gecentreerd moeten worden binnen de flex container. Dit werkt ook als, zoals hier, de hoogte van de <div> onbekend is.
width: auto;
Voor kleinere browservensters is eerder bij #midden, #rechts een breedte van 180 px opgegeven. Die wordt hier weggehaald. Normaal genomen wordt een <div> dan even breed als z'n ouder, maar niet als het een flex item is. Nu wordt de <div> niet breder, dan nodig is om de inhoud weer te kunnen geven.
De breedte van flex items kan op allerlei manieren worden gestuurd. In dit geval is voor de meest luie oplossing gekozen: een <br> tussen de woorden 'Verticaal' en 'gecentreerd'.
float: left;
Browsers die flexbox niet ondersteunen, zouden de <div> gewoon op een eigen regel zetten. Door de <div> naar links te floaten, wordt dat voorkomen. Browsers die flexbox kennen, negeren een float bij een flex item.
#rechts
Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)
#midden, #rechts {background: white; color: black; width: 180px; margin: 20px auto 0; border: black solid 1px;}
Het element met id="rechts". De <div> waarin het witte blokje rechts zit.
Normaal genomen wordt een <div> op een eigen regel gezet, maar omdat de ouder div#voor-flex
met display: flex;
bij #voor-flex in een zogenaamde 'flex container' is veranderd, is div#rechts
in een zogenaamd 'flex item' veranderd. Daardoor kunnen, als je dat wilt, <div>'s op dezelfde regel blijven staan. Hier is dat het geval.
align-self: stretch;

Met align-items: center;
is bij #voor-flex opgegeven dat de flex items, waaronder deze <div>, verticaal gecentreerd moeten worden binnen de flex container. De <div> wordt daarbij niet hoger, dan nodig is om de inhoud ervan weer te kunnen geven. Dat zou er uitzien als op de afbeelding hiernaast: de <div> is niet hoger dan nodig en netjes verticaal gecentreerd binnen div#voor-flex
, de flex container.
In dit geval moet div#rechts
hoger worden dan de erin zittende tekst, omdat de erin zittende tekst later met translateY()
verticaal gecentreerd wordt binnen div#rechts
. En verticaal centreren kan uiteraard alleen, als div#rechts
hoger is dan de erin zittende tekst.
Met behulp van align-self: stretch;
wordt div#rechts
, even hoog gemaakt als div#voor-flex
, de flex container.
Met flexbox kun je bij de flex container (hier div#voor-flex
) css opgeven voor álle flex items. Vervolgens kun je bij de afzonderlijke items die css weer overrulen. Wat flexbox inderdaad ongelooflijk flexibel maakt. In dit geval wordt het flex item div#rechts
als enige flex item even hoog gemaakt als div#voor-flex
.
(Om de afbeelding te maken moest ook even position: absolute;
weg bij de in div#rechts
zittende <div>, omdat div#rechts
anders helemaal geen hoogte had gekregen. Absolute gepositioneerde elementen tellen niet mee voor de hoogte van hun ouder, vandaar.)
Browsers die flexbox niet ondersteunen, negeren deze regel. In die browsers krijgt div#rechts
helemaal geen hoogte, omdat er alleen een absoluut gepositioneerde <div> in zit. Bij Bekende problemen (en oplossingen) is te zien, hoe dat eruitziet.
float: right;
Browsers die flexbox niet ondersteunen, zouden de <div> gewoon op een eigen regel zetten. Door de <div> naar rechts te floaten, wordt dat voorkomen. Browsers die flexbox kennen, negeren een float bij een flex item.
margin: 30px 10px 30px auto;
Met behulp van align-self: stretch;
is div#rechts
iets hierboven even hoog gemaakt als div#voor-flex
, de flex container. Hier wordt aan boven- en onderkant een marge van 30 px aan div#rechts
gegeven, waardoor boven en onder div#rechts
een lege ruimte ontstaat. In die ruimte is de gele achtergrond van div#voor-flex
te zien. Hoewel div#rechts
verticaal gecentreerd lijkt, is dat dus niet het geval. div#rechts
vult, met de marge erboven en eronder, de volle hoogte van div#voor-flex
.
Rechts een kleine marge van 10 px voor wat afstand tussen div#rechts
en de rechterkant van div#voor-flex
.
Links auto
als marge. Dit werkt binnen een flex container anders erbuiten. Binnen flexbox betekent margin-left: auto;
: zover mogelijk naar rechts zetten. Het heeft hetzelfde effect als float: left;
, maar dan zonder de nadelen die 'n float soms kan hebben.
#rechts div
Voor dit element is eerder css opgegeven. Deze wordt binnen dit blokje herhaald in de volgorde, waarin deze in de stylesheet staat, zodat alles hier overzichtelijk bij elkaar staat. (Alleen wat binnen deze media query geldig is, wordt binnen dit blokje herhaald.)
#links, #midden, #rechts div {padding: 5px;}
Alle <div>'s binnen het element met id="rechts". Dat is er hier maar eentje: de <div> waarbinnen de tekst in het witte blok rechts zit. Deze <div> is alleen maar nodig om translateY()
te kunnen demonstreren. Met behulp daarvan wordt deze <div>, en daarmee de erin zittende tekst, verticaal gecentreerd binnen div#rechts
.
background: white;
Witte achtergrond.
Bij #midden, #rechts is al een witte achtergrond gegeven aan div#rechts
. Deze <div> staat binnen div#rechts
, dus dit lijkt dubbelop. Dat is ook zo voor browsers die flexbox ondersteunen, want in die browsers wordt bij #rechts div#rechts
met align-self: stretch;
even hoog gemaakt als div#voor-flex
. In browsers die flexbox niet ondersteunen, werkt dit niet. Normaal genomen zou div#rechts
dan precies hoog genoeg worden om de inhoud ervan weer te geven, maar ook dat werkt hier niet. Alle inhoud van div#rechts
zit in deze <div>, en die wordt iets hieronder absoluut gepositioneerd. En absoluut gepositioneerde elementen tellen niet mee voor de hoogte van de ouder. Kortom: div#rechts
heeft geen hoogte in browsers die flexbox niet ondersteunen en kan dus ook geen witte achtergrond hebben.
Door aan deze <div> met de tekst ook een witte achtergrond te geven, staat er in ieder geval in deze browsers een witte achtergrond onder de tekst.
color: black;
Voorgrondkleur zwart. Dit is onder andere de kleur van de tekst.
Hoewel dit de standaardkleur is, wordt deze toch specifiek opgegeven. Hierboven is een achtergrondkleur opgegeven. Sommige mensen hebben zelf de voorgrond‑ en/of achtergrondkleur veranderd, bijvoorbeeld omdat ze slecht kleuren kunnen onderscheiden. Als nu de achtergrondkleur wordt veranderd, maar niet de voorgrondkleur, loop je het risico dat tekstkleur en achtergrondkleur te veel op elkaar gaan lijken.
Door beide op te geven, is redelijk zeker dat achtergrond- en tekstkleur genoeg van elkaar blijven verschillen. Als de gebruiker !important
heeft gebruikt in een eigen stylesheet, is er nog niets aan de hand, want dan veranderen achtergrond- en voorgrondkleur geen van beide.
Dit is ook al bij <body> opgegeven, maar sommige mensen hebben bij álle elementen de kleuren veranderd. Het heeft immers weinig zin, als ze dat alleen bij de body doen, terwijl de sitebouwer de kleuren ook bij bijvoorbeeld de paragrafen heeft aangepast.
width: 170px;
Breedte.
position: absolute;
Om de <div> absoluut te positioneren. Er wordt gepositioneerd ten opzichte van de eerste voorouder die zelf een positie heeft. Dat is hier div#voor-flex
, die bij #voor-flex een relatieve positie heeft gekregen.
Hier gelijk onder wordt de <div> met tekst met top: 50%;
halverwege de hoogte van div#voor-flex
neergezet. Iets verderop wordt de <div> met transform: translateY(-50%);
weer met de helft van z'n eigen hoogte terug naar boven gezet. Nu staat de helft van de <div> met tekst beneden en de helft boven het verticale midden van div#voor-flex
.
Speciaal om deze <div> met tekst te kunnen positioneren is aan div#voor-flex
een relatieve positie gegeven. Normaal genomen zou je die relatieve positie aan de directe ouder div#rechts
van deze <div> geven. Maar in browsers die flexbox niet ondersteunen, heeft div#rechts
geen hoogte. De <div> met tekst zou dan halverwege de hoogte van 0 px van div#rechts
komen te staan, en dat schiet niet op.
Min of meer toevallig heeft div#voor-flex
dezelfde hoogte als div#rechts
. Omdat div#voor-flex
die hoogte in álle browsers heeft, ook in browsers die flexbox niet ondersteunen, kan worden gepositioneerd ten opzichte van div#voor-flex
. En dat werkt in alle browsers.
In dit specifieke geval is er nog een andere reden om te positioneren ten opzichte van div#voor-flex
. Met align-self: stretch;
is div#rechts
bij #rechts even hoog gemaakt als div#voor-flex
. Dit werkt echter niet goed in alle browsers. Weliswaar krijgt div#rechts
overal de goede hoogte, maar als je vervolgens de <div> met tekst in div#rechts
op de halve hoogte van div#rechts
positioneert, blijken veel browsers toch nog te denken dat div#rechts
geen hoogte heeft. Door te positioneren ten opzichte van div#voor-flex
, wordt dit opgelost.
(Dit soort dingen zijn ook de reden dat ik nog steeds zeer terughoudend ben met het gebruik van flexbox. Op internet zie je dat tal van mensen zich halsoverkop volledig op flexbox – en inmiddels ook grid
– hebben gestort, maar zodra je iets ingewikkelder dingen wilt gaan doen, blijken er nog enorme verschillen tussen browsers te bestaan. Veel voorbeelden blijken, als je ze in 'n groot aantal browsers test, gewoon niet goed te werken in sommige browsers. Bovendien ondersteunen nog niet alle browsers flexbox, en grid
al helemaal nog niet. Maar over – hopelijk – niet al te lange tijd is flexbox gewoon zonder meer te gebruiken, en dan is het fantastisch.)
top: 50%;
Een waarde in procenten bij top
is ten opzichte van de hoogte van de eerste voorouder die zelf een positie heeft. Dat is hier div#voor-flex
, die bij #voor-flex relatief is gepositioneerd. Hier gelijk onder wordt de <div> met tekst weer de helft van z'n eigen hoogte terug naar boven gezet. Nu staat de <div>, en daarmee de erin zittende tekst, verticaal gecentreerd bonnen div#voor-flex
.
-webkit-transform: translateY(-50%); transform: translateY(-50%);
Hier staat in feite twee keer hetzelfde: transform: translateY(-50%);
. Waarom dat zo is, staat bij De voorvoegsels -moz-, -ms- en -webkit-.
Met behulp van translateY()
wordt een element ten opzichte van zichzelf verplaatst. Bij een positieve waarde naar beneden, bij een negatieve waarde naar boven.
Ook als procenten worden gebruikt, zoals hier het geval is, geldt de verplaatsing ten opzichte van het element zelf. Meestal worden procenten als een percentage van de ouder genomen, maar hier is dat niet het geval. translateY(-50%)
betekent hier: zet de <div> de helft van z'n eigen hoogte terug naar boven. Dat die hoogte onbekend is, maakt niets uit. Bij het weergeven van de pagina kent de browser grootte, resolutie, en dergelijke van browservenster en scherm, dus de browser kan dan de precieze verplaatsing berekenen.
Hier gelijk boven is de <div> met top: 50%;
halverwege de hoogte van div#voor-flex
neergezet. Door de <div> de helft van z'n eigen hoogte terug naar boven te verplaatsen, staat de helft van de <div> nu boven het verticale midden van div#voor-flex
, en de helft staat eronder. Oftewel: de <div> is verticaal gecentreerd binnen div#voor-flex
. En daarmee ook de in de <div> zittende tekst.