Skip links en inhoudsopgave

Uitleg flexibele lay-out met header, menu en footer. Past zich aan breedte van venster aan

Laatst aangepast: .

Afbeelding 1: de lay-out in vensters van verschillende grootte

Korte omschrijving

Een-, twee of driekoloms lay-out met (vaste) header, (vast) menu en (vaste) footer. De precieze indeling is afhankelijk van de breedte van het venster van de browser.

Deze lay-out vult altijd het hele venster van de browser, zowel in de hoogte als in de breedte. Alleen bij heel weinig inhoud kan in vensters smaller dan 810 px en op alle touchscreens ruimte aan de onderkant van het venster leeg blijven.

Header (geel)

Altijd even breed als het venster.

Vensters smaller dan 810 px en alle touchscreens: de header scrolt mee met de rest van de pagina. Niet hoger dan nodig om de inhoud van de header weer te kunnen geven.

Vensters breder dan 810 px, behalve touchscreens: staat altijd bovenaan het venster, scrolt niet mee. Hoogte afhankelijk van lettergrootte.

Menu (grijs/zwart op groen)

Vensters smaller dan 600 px: het menu staat onderaan de pagina, gelijk boven de footer en scrolt mee met de rest van de pagina. De links staan in rijen onder elkaar. Elke rij bevat twee links in de vorm van twee knoppen, die elk de halve breedte van het venster vullen.

Een link in de header bovenin brengt je naar dit menu. Een link in het menu brengt je weer terug naar boven. Deze twee links zijn alleen zichtbaar in deze smalle vensters.

Vensters tussen 600 en 810 px breed en op alle touchscreens breder dan 600 px: het menu staat gelijk onder de header en scrolt mee met de rest van de pagina. De links staan naast elkaar in de vorm van acht naast elkaar staande knoppen.

Vensters breder dan 810 px, behalve touchscreens: het menu staat altijd aan de linkerkant van het venster en scrolt niet mee. De breedte is afhankelijk van de breedte van het venster. De links staan onder elkaar in de vorm van acht onder elkaar staande knoppen.

Linkerkolom (tekst, oranje)

Als er genoeg tekst en dergelijke aanwezig is, kan deze kolom worden gescrold.

Als er genoeg ruimte is, komen rechts van de tekst foto's te staan.

Vensters smaller dan 810 px: de tekst wordt even breed als het venster.

Vensters met een breedte van 810 px tot 1400px: de tekst wordt 73% breed.

Vensters breder dan 1400 px: de tekst wordt 58% breed.

Vensters breder dan 1600px: de tekst wordt 48% breed.

Vensters breder dan 1800px: de tekst wordt maximaal 50 em breed om lange, slecht leesbare regels te voorkomen.

Rechterkolom (foto's, roze)

Als er genoeg ruimte is, komen rechts van de tekst foto's te staan. De foto's waarvoor op die plaats geen ruimte is, komen onder de tekst te staan.

Vensters smaller dan 810 px: alle foto's komen onder de tekst te staan. Afhankelijk van de breedte van het venster en de browser staan de foto's in één tot vier kolommen onder de tekst.

Vensters met een breedte van 810 tot 1400 px: er komt naast de tekst één kolom foto's te staan.

Vensters breder dan 1400 px: er komen naast de tekst twee kolommen foto's te staan.

Vensters breder dan 1600 px: er komen naast de tekst drie kolommen foto's te staan.

Vensters breder dan 1800 px: er komen naast de tekst zoveel kolommen foto's te staan, als er in het venster passen.

Footer (blauw)

Altijd even breed als het venster.

Vensters smaller dan 810 px en alle touchscreens: de footer scrolt mee met de rest van de pagina. Niet hoger dan nodig om de inhoud van de footer weer te kunnen geven.

Vensters breder dan 810 px, behalve touchscreens: staat altijd onderaan het venster, scrolt niet mee. Hoogte afhankelijk van lettergrootte.

BELANGRIJK

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

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

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

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

Opmerkingen

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

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

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

Achterliggend idee

Tot niet zo heel lang geleden kon je bij het maken van 'n website enigszins uitgaan van een bepaalde maat. Dat is steeds minder zo. Op de desktop verschijnen steeds meer brede schermen en bij mobiele apparaten is er helemaal een totale wildgroei aan maten, waaronder heel kleine.

Deze lay-out past zich min of meer aan de breedte van het venster van de browser aan. Om dat mogelijk te maken, zijn vrijwel alle maten niet opgegeven in een absolute eenheid als px, maar in relatieve eenheden als % en em. Dit maakt het mogelijk om onderdelen een breedte te geven, die relatief is ten opzichte van de breedte van het browservenster.

Door met behulp van css3 de breedte van het venster van de browser op te vragen, kan de lay-out worden aangepast aan de breedte van het venster.

Boven een bepaalde breedte heeft deze lay-out in principe een vaste header, menu en footer: ze scrollen niet mee met de pagina. Maar in veel mobiele browsers levert dit (grote) problemen op. Nieuwere browsers kunnen hier vaak wel mee overweg, maar het zal nog wel even duren voordat iedereen zo'n nieuwere browser heeft.

Daarom wordt met behulp van JavaScript geprobeerd vast te stellen, of de browser 'touch events' herkent: aanrakingen van een touchscreen. Als dat zo is, wordt waarschijnlijk een mobiele browser gebruikt en scrollen header, menu en footer mee met de rest van de pagina. Deze methode is niet waterdicht, maar de meeste mobiele browsers worden hier wel mee herkend.

Heel simpele mobiele apparaten, of heel oude mobiele browsers, kunnen de breedte van het venster niet doorgeven. Daarom wordt er, om aan de veilige kant te blijven, standaard vanuit gegaan dat het om een heel smal venster gaat. Pas als door de browser een grotere breedte wordt doorgegeven, wordt de lay-out aangepast aan die grotere breedte.

Niet alle mobiele apparaten kunnen goed met JavaScript uit de voeten. Daarom wordt er standaard vanuit gegaan dat het om een mobiele browser gaat. Pas als de browser meldt dat touch events niet worden ondersteund, worden - in bredere vensters - header, menu en footer op een vaste positie gezet.

Deze volgorde zorgt ervoor dat ook de simpelste mobiele apparaten met de lay-out overweg kunnen: pas als er daadwerkelijk meer mogelijkheden aanwezig zijn, worden die gebruikt.

Het opvragen van bijvoorbeeld de breedte van het venster kan met behulp van de zogenaamde 'media queries' uit css3: een regel die begint met @media. Met zo'n regel kun je css schrijven, die bijvoorbeeld alleen voor vensters met een bepaalde breedte geldt. Op tablets en dergelijke is de breedte van het venster van de browser normaal genomen ook de breedte van het scherm.

Door het gebruik van media queries kun je bij een bepaalde breedte de lay-out aanpassen. Ik meet niet op de specifieke breedte van één of meer apparaten, maar gewoon 'hoe het er uitziet'. Als iets te klein wordt, moet het anders worden weergegeven. Specifieke breedtes zijn meestal gericht op één fabrikant (Apple), terwijl er tientallen verschillende resoluties zijn.

De nieuwste mobiele apparaten hebben vaak een hogere resolutie dan oudere apparaten of monitors voor de desktop: de pixels staan dichter op elkaar, tot wel vier keer zo dicht. Dat zou betekenen dat een lijn van 4 px breedte op zo'n nieuwer scherm maar 1 px breed zou worden. Dat is echter niet zo, want deze apparaten doen net alsof ze 'n 'normale' pixeldichtheid hebben. Alles wordt alleen veel mooier weergegeven, omdat de pixels kleiner zijn.

(Alles? Nou, nee. Bij afbeeldingen werkt dit alleen maar als je de afbeeldingen hebt aangepast voor zo'n hoge pixeldichtheid. Als de pixels gewoon niet in de afbeelding zitten, kunnen ze ook niet worden weergegeven. Maar voor bijvoorbeeld tekst werkt het fantastisch. In dit voorbeeld zijn de afbeeldingen niet aangepast voor een eventuele hogere pixeldichtheid.)

Met behulp van media queries wordt de breedte van het venster opgevraagd en kan de lay-out worden aangepast. Daarnaast wordt geprobeerd mobiele browsers te onderscheiden van desktopbrowsers.

Een mobiele browser wordt in de regel gebruikt op een touchscreen. Een mobiele browser moet daarom zogenaamde 'touch events', aanrakingen van het scherm, herkennen. Door te kijken of een browser touch events herkent, kun je met vrij grote zekerheid vaststellen, of een browser een mobiele browser is of niet.

Om te kijken of een browser touch events herkent, wordt gebruik gemaakt van modernizr. Dat is een JavaScript, waarmee je kunt vaststellen of een browser bepaalde nieuwere eigenschappen wel of niet ondersteunt. In deze lay-out wordt alleen gekeken of touch events worden ondersteund, maar je kunt nog veel meer met dit script.

Als de browser touch events ondersteunt, wordt door modernizr aan het <html>-element de class "touch" toegevoegd. Als de browser touch events niet ondersteunt, wordt de class "no-touch" toegevoegd.

Door nu in de css bepaalde selectors te beginnen met .touch of .no-touch, kan verschil worden gemaakt tussen browsers die wel en die geen touch events ondersteunen. Browsers die touch events niet ondersteunen zijn in principe ook de browsers die geen problemen hebben met een vaste header, menu en footer. Die kunnen er nu met behulp van de class "no-touch" uitgefilterd worden, waardoor andere browsers deze css niet krijgen.

De css bestaat uit twee delen: algemene css, die de basis vormt voor de pagina en overal het zelfde is. Daarnaast css voor de verschillende breedtes, en voor mobiele en desktopbrowsers. Je zou voor elke breedte een eigen stylesheet kunnen maken, maar normaal genomen is dat niet zo handig. Als je aparte stylesheets maakt voor elke breedte, moet voor elke breedte een extra aanroep naar de server worden gedaan. Omdat het maar om kleine stukjes aparte css gaat, is het efficiënter alles in één stylesheet te zetten. Er wordt dan wel wat meer gedownload dan strikt noodzakelijk is, maar dat is nog altijd efficiënter dan de extra aanroep.

Ogenschijnlijk lijkt deze lay-out een samenhangend geheel: het venster wordt volledig gevuld door header, menu, tekst, foto's en footer. In werkelijkheid gaat het om vier totaal van elkaar losstaande vlakken, die toevallig enigszins samenhangend op het scherm worden gezet.

Toevallig? Nou ja, de plaats waar ze staan, is natuurlijk niet toevallig. Maar ze hebben verder niets met elkaar te maken. Zonder enig probleem zou je de header links kunnen neerzetten, of de footer bovenaan. Wat voor het oog een samenhangend geheel is, bestaat in werkelijkheid uit vier losse blokken.

Omdat de pagina in werkelijkheid uit losse blokken bestaat, geeft dat de mogelijkheid de weergave van die blokken met behulp van css aan te passen. En af te laten hangen van de breedte van het venster.

Het eerste blok is de header aan de bovenkant van het venster, die ook in de html helemaal bovenaan staat. Voor de herkenbaarheid is de achtergrond van de header geel gemaakt. De header staat in de tag <header>, wat eigenlijk een doodgewone div is, maar met een speciale semantische betekenis: de header zit erin. Omdat <header> een blok-element is, vult het normaal genomen automatisch de volle breedte van het venster van de browser.

Standaard scrolt de header gewoon mee met de rest van de pagina. De hoogte is niet meer, dan nodig is om de inhoud van de header weer te kunnen geven.

Pas als wordt vastgesteld dat het venster breder is dan 810 px en dat de browser geen touch events herkent, scrolt de header niet meer mee, maar blijft altijd bovenin het venster staan. Dit ontstaat niet door iets aan de header te veranderen, maar door het deel gelijk onder de header absoluut te positioneren. Binnen dat deel kan worden gescrold, maar de pagina in z'n geheel scrolt niet. Dus de header scrolt ook niet en blijft altijd op z'n plaats bovenin het venster staan.

Om alle onderdelen goed ten opzichte van elkaar te kunnen plaatsen, krijgt <header> nu een vaste hoogte. Bij een heel grote letter zou de inhoud van <header> daardoor onder de header kunnen komen te staan. Om dat te voorkomen, wordt overflow op auto gezet: als de inhoud niet in <header> past, verschijnt rechts van de header een verticale scrollbalk.

Voor de footer geldt ongeveer hetzelfde verhaal als voor de header. De footer staat in een blok-element <footer>. Ook <footer> is eigenlijk 'n doodgewone div met een speciale semantische betekenis. Voor de herkenbaarheid is de achtergrond van de footer blauw gekleurd.

Standaard staat de footer onderaan de pagina en scrolt mee met de rest van de pagina. De hoogte van <footer> is niet meer, dan nodig is om de inhoud ervan weer te kunnen geven.

Pas als wordt vastgesteld dat het venster breder is dan 810 px en dat de browser geen touch events herkent, wordt de footer absoluut aan de onderkant van het venster gepositioneerd. De footer scrolt nu niet meer mee met de rest van de pagina, maar blijft altijd aan de onderkant van het venster staan.

Om alle onderdelen goed ten opzichte van elkaar te kunnen plaatsen, krijgt <footer> nu een vaste hoogte. Bij een heel grote letter zou de inhoud van <footer> daardoor boven de footer kunnen komen te staan. Om dat te voorkomen, wordt overflow op auto gezet: als de inhoud niet in <footer> past, verschijnt rechts van de footer een verticale scrollbalk.

Normaal genomen wordt een blok-element als <footer> automatisch even breed als z'n ouder. Dat is hier <body>. Maar omdat <footer> absoluut gepositioneerd is, is dat hier niet het geval. Daarom moet <footer> een breedte van 100% krijgen, dan wordt hij wel even breed als <body> en dus de pagina.

Dan houden we het middendeel tussen header en footer nog over.

<header> en <footer> kunnen relatief simpel een breedte krijgen, omdat ze gewoon altijd even breed als het venster moeten zijn. Voor het middendeel ligt het iets ingewikkelder, omdat de plaatsing van menu, tekst en foto's afhankelijk is van de breedte van het venster en van of de browser touch events herkent of niet. En dan moet het geheel er ook nog 'n beetje netjes uitgelijnd en zo uitzien.

Ook hier wordt weer uitgegaan van het smalste venster in een browser die touch events herkent. Pas als daadwerkelijk wordt vastgesteld dat het venster breder is, en dat de browser touch events niet herkent, wordt de lay-out aangepast.

De kleinste lay-out is bedoeld voor vensters smaller dan 600 px. Zulke kleine vensters zijn (vrijwel) altijd touchscreens. Dus het menu moet worden bediend met de vingers, en niet iedereen heeft lieflijke kleutervingertjes, waarmee je heerlijk kunt priegelen in voor bouwvakkersklauwen onbereikbare hoekjes.

(Ik wil ooit nog eens openhartig mijn diepste gevoelens uitwisselen met de gediplomeerde gek die meende op m'n test-Samsung van 320x240 een virtueel toetsenbord te moeten aanbrengen. Dat alleen op vingers reageert. Enthousiast reageert. Met één aanraking bedien je soms wel vijf toetsen tegelijk. Wauw. Zo bezoek je echt spontaan de meest exotische sites. Als je ooit iemand ziet die z'n vingers heeft bijgepunt: dat is de bezitter van 'n Samsung smartphone.)

Kortom: het menu heeft op hele kleine vensters relatief veel ruimte nodig. Zoveel, dat het al snel het hele venster vult. Daarom wordt het menu onderaan de pagina neergezet, gelijk boven de footer. Het vult daar inderdaad (vrijwel) het hele venster, maar dat is op die plaats niet erg. Zou het gelijk bovenaan de pagina staan, dan zou je bij openen van de pagina in eerste instantie alleen het menu zien.

Afbeelding 2
Afbeelding 2: extra link naar menu aan onderkant van pagina in een venster smaller dan 600 px.
Afbeelding 3
Afbeelding 3: menu staat onderaan pagina in een venster smaller dan 600 px.

De links uit het menu zijn elk even breed als het halve venster. Ze kunnen nu makkelijk met de vingers worden bediend, ook door bouwvakkers. Om snel weer terug naar boven te kunnen verschijnt een extra link: 'Top'. Dit menu scrolt gewoon mee met de pagina, net als de footer. De knoppen in het menu zijn zo simpel mogelijk gehouden: rechthoekige grijze vlakken.

Bovenaan de pagina verschijnt linksboven in de de header een extra link 'Menu', die je in één keer naar het menu onderaan brengt.

Dit is ook de reden dat het menu in de html onder de tekst en de afbeeldingen staat, gelijk boven de footer: om er 'n link naartoe te kunnen maken, moet het menu een id krijgen. Je kunt dan naar dat id linken, een zogenaamd 'anker'. Dat anker komt uit op de plaats waar die id staat. Als ik naar de onderkant van de pagina wil gaan, moet die id dus onderaan de pagina staan. En omdat de id in het menu staat, moet ook het menu onderaan staan.

In deze vensters smaller dan 600 px vult de tekst de volle breedte van het venster. De foto's staan in één lange kolom onder de tekst.

Als het venster van de browser breder dan 600 px is, is er (iets) meer ruimte. De knoppen uit het menu kunnen naast elkaar worden gezet en zijn toch nog goed met de vingers te bedienen. Omdat de knoppen nu niet meer onder elkaar, maar naast elkaar staan, kunnen ze absoluut bovenaan worden gepositioneerd, gelijk onder de header. Ze vullen nu niet meer het hele venster, en bovenaan is een logischer plaats dan helemaal onderaan.

De extra link bovenin de header naar het menu aan de onderkant, en de link vanuit het menu terug naar de bovenkant van de pagina, zijn nu niet meer nodig en worden verborgen.

Het menu scrolt nog steeds mee met de rest van de pagina. Er is nog steeds relatief weinig ruimte in het venster, en mensen zullen niet dol van geluk worden als die weinige ruimte dan ook nog 'ns schuilgaat achter header, menu en footer. Zelfs de subtiele, gevoelige, kunstzinnige samenstelling van de achtergrondkleuren verhelpt daar niets aan.

Afbeelding 4: in bredere vensters staat het menu aan de bovenkant van de pagina

De kleine stukjes groen die je achter het menu ziet, zijn de achter­grond­kleur van het menu. De knoppen in het menu zijn hier iets verfraaid met een achtergrond-gradiënt en ronde hoeken.

De tekst vult de volle breedte van het venster van de browser. De foto's staan in vier kolommen onder de tekst, waarbij elke kolom 25% van de breedte van het venster vult. In smallere vensters zijn de foto's iets kleiner dan in bredere vensters.

In vensters breder dan 810 px worden de regels met tekst veel te lang. Daardoor worden ze lastig te lezen. Daarom wordt de breedte van de div met de tekst begrensd tot 73%. 73 is een minder willekeurig getal dan het lijkt. Met wat padding en zo wordt het 75, driekwart.

Er blijft nu rechts een lege ruimte over. Die kun je leeg laten, maar je kunt hem ook vullen met iets anders dan tekst de tekst op de oranje achtergrond. In het voorbeeld zijn hier afbeeldingen neergezet, maar je kunt er ook 'n tweede kolom met tekst neerzetten, of noten, of 'n tweede menu, of wat dan ook.

Afbeelding 5: één kolom met foto's naast tekst op touchscreen

De tekst wordt naar links gefloat, en de afbeel­dingen ook. Door een breedte aan de elementen met de afbeel­dingen te geven, wordt gezorgd dat tekst en afbeel­ding naast elkaar passen. Nu wordt de tekst niet te breed, terwijl toch het hele venster wordt gebruikt. De foto's die niet naast de tekst passen, komen weer gewoon onder de tekst te staan, in vier kolommen.

Hoewel het bij de tekst en de foto's om twee kolommen lijkt te gaan, is het in werkelijkheid één kolom, die in twee delen is gesplitst: eentje met de tekst, en eentje met de foto's.

Ook op deze breedte scrollen header, menu en footer mee met de rest van de pagina. Als de letters heel sterk vergroot zouden worden, zouden sommige links op twee regels komen te staan, omdat de tekst niet meer binnen de knop past. Daarom is tussen de woorden binnen een link een vaste spatie   gebruikt. Nu komt de tekst mogelijk aan de rechterkant iets buiten de knop te staan, maar dat is beter dan dat de tekst onder de knop komt te staan, want dan komt hij over de inhoud van de pagina te staan.

In vensters breder dan 810 px is het eigenlijk de bedoeling dat header, menu en footer blijven staan en alleen de tekst en afbeeldingen kunnen scrollen. Maar omdat dat in mobiele browsers tot (grote) problemen kan leiden, is daarvoor een aanvullende voorwaarde nodig. Als met behulp van het JavaScript modernizr is vastgesteld dat de browser touch events niet herkent, is het vermoedelijk geen mobiele browser. Vermoedelijk gaat het dan om een desktop of soortgelijk apparaat. Pas in dat geval scrollen header, menu en footer niet mee.

Tekst en afbeeldingen staan binnen <article>. Dat is in feite een gewone div, bedoeld voor de een min of meer samenhangend geheel. Hier is maar één <article>, dat absoluut wordt gepositioneerd tussen header en footer. Aan de linkerkant wordt ruimte overgelaten voor een absoluut gepositioneerde kolom, waarin het menu komt.

De footer wordt absoluut onderaan het venster van de browser gepositioneerd. Als er heel weinig inhoud op de pagina staat en er niet gescrold hoeft te worden, staat de footer toch onderaan het venster.

Afbeelding 6: één kolom met foto's naast tekst op desktop

Op de desktop komt de lay-out er nu heel anders uit te zien.

Header en footer hebben een vaste hoogte met overflow op auto, omdat anders bij grote letters de inhoud buiten footer en header kan komen te staan. Als de inhoud nu niet in footer of header past, verschijnt naast footer en header een verticale scrollbalk.

Ook het menu heeft om dezelfde reden overflow op auto, maar zonder vaste hoogte. Dat is niet nodig, omdat het menu absoluut is gepositioneerd tussen header en footer.

Het uiterlijk van het menu is ook anders. De knoppen staan onder elkaar. Bij hoveren over de knoppen verandert de kleur. Hoveren werkt nauwelijks of niet op touchscreens, daarom wordt het alleen ingeschakeld als de browser geen touch events herkent. Je mag aannemen dat er dan sprake is van 'n muis of iets soortgelijks, waarmee je wel kunt hoveren.

Met JavaScript uit kan niet worden getest, of de browser touch events herkent of niet. Daardoor wordt de standaard-css gebruikt, waarbij er vanuit wordt gegaan dat de browser touch events niet herkent. Het ziet er dan op de desktop net zo uit als in een mobiele browser.

In vensters breder dan 1400 px is ruimte voor twee kolommen met afbeeldingen rechts van de tekst. In vensters breder dan 1600 px passen drie kolommen. En in vensters breder dan 1800 px komen zoveel foto's naast de tekst te staan, als er in de lege ruimte passen. Bij deze hele brede vensters zijn de foto's niet meer volledig uitgelijnd, omdat de precieze breedte daar onbekend is.

Bij floaten wordt niet meer naast elkaar gezet, dan op dezelfde regel past. Als het venster breder is dan 810 px, wordt de tekst 73% breed gemaakt. In de resterende ruimte past één foto. Door de tekst en de elementen waarin de foto's staan smaller te maken, passen er meer foto's op dezelfde regel naast de tekst. Hoe smaller de tekst en hoe smaller de elementen met de foto's, hoe meer er op dezelfde regel naast elkaar past.

De breedte van het browservenster wordt weer met behulp van een @media-regel opgevraagd. De breekpunten van 1400, 1600 en 1800 px zijn min of meer willekeurig gekozen. Op deze afstanden bleek het er netjes uit te zien en zo.

Afbeelding 7: tekst met drie kolommen foto's ernaast op touchscreen
Tekst met drie kolommen foto's ernaast. Header, menu en footer scrollen mee.
Afbeelding 8: tekst met drie kolommen foto's ernaast op desktop
Tekst met drie kolommen foto's ernaast. Header, menu en footer scrollen niet mee.

Op de afbeel­dingen hiernaast staat een screen­shot van de lay-out, zoals deze er op een venster tussen 1600 en 1800 px breed uitziet: drie kolommen met foto's naast de tekst.

Op de bovenste afbeelding ziet het eruit zoals in een browser die touch events herkent. Dat zal meestal een touch­screen zijn, maar het kan ook een desk­top­browser zijn, waar JavaScript uitstaat.

Op de onderste afbeel­ding ziet het eruit, zoals in een browser die touch­screens niet herkent, en waarin Java­Script aan staat.

Dit zal meestal een desk­top­browser zijn.

Los van de belangrijkste onderdelen zijn nog wat extra's aangebracht voor het uiterlijk, zoals een overgang tussen oranje en roze. De tekst staat op een oranje achtergrond, de afbeeldingen op een roze. Hoewel dit volgens mijn kleurgevoel een fantastisch harmonieuze kleurenkeuze is, blijkt de browser daar iets anders over te denken en is de overgang van oranje naar roze onderaan de tekst ietwat, eh, z'n tijd te ver vooruit. Omdat er op die overgang ook nog foto's staan, wordt het effect nog 'ns versterkt. Daarom is daar een gradiënt aangebracht, die de overgang verzacht.

Zo is er nog een aantal van dat soort niet-essentiële dingen.

Voor Internet Explorer 7, 8 en 9 is vanzelfsprekend een heel scala aan extra's nodig. Dat is een van de weinige echte zekerheden in het leven: Microsoft maakt geen browsers, maar gehaktmolens.

Gehaktmolens? Microsoft? Maakt die gehaktmolens? Ja. Zonder die extra's wordt de pagina namelijk in gehakt veranderd in Internet Explorer 7 en 8. In Internet Explorer 9 valt dat mee, daar is alleen hogere wiskunde nodig voor de gradiënt in het menu, want zo'n verlopende kleur maken met alleen css was kennelijk te hoog gegrepen voor Microsoft.

Voor Internet Explorer 7 en 8 is extra JavaScript nodig om de nieuwe html5-elementen te herkennen. Voor Internet Explorer 8 is ook nog extra JavaScript nodig om @media-regels te herkennen. Internet Explorer 7 lukt dat helemaal niet, dus die heeft ook nog 'n berg aparte css nodig.

De voorvoegsels -moz-, -ms-, -o- 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.

Google Chrome en Safari: -webkit-, naar de gebruikte weergave-machine: webkit.

Opera: -o-, je mag zelf bedenken waar de letter o vandaan komt (hint: Opera wordt door Opera Software gemaakt).

Internet Explorer: -ms-, naar de maker: Microsoft. Traditiegetrouw heeft Microsoft zich hier jarenlang niets van aangetrokken, pas bij Internet Explorer 8 is Microsoft -ms- gaan gebruiken. Omdat het ook zonder -ms- werkt en de speciale css voor Internet Explorer toch in een aparte stylesheet staat, gebruik ik -ms- nooit voor oudere versies dan Internet Explorer 9.

Als je css valideert met de w3c css-validator, moet je even instellen dat je geen foutmelding krijgt voor het gebruik van deze voorvoegsels.

In dit voorbeeld wordt linear-gradient gebruikt. Dit werkt in nog geen enkele browser zonder voorvoegsel. In Internet Explorer werkt het nog helemaal niet, maar het lijkt te worden opgenomen in Internet Explorer 10. Vooruitlopend daarop gebruik ik ook al het voorvoegsel -ms-. Onduidelijk is namelijk nog of Microsoft het met of zonder dit voorvoegsel gaat implementeren.

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 linear-gradient erbij. Deze wordt als laatste opgegeven. Bijvoorbeeld Firefox herkent -moz-linear-gradient. Zodra Firefox linear-gradient gaat herkennen, zal dit -moz-linear-gradient overrulen, omdat het er later in staat. Dat ze er beide in staan, is dus geen enkel probleem.

Op dit moment moet je nog het volgende schrijven:

{-moz-linear-gradient: ...; -ms-linear-gradient: ...; -o-linear-gradient: ...; -webkit-linear-gradient: ...; linear-gradient: ...;}

In de toekomst kun je volstaan met:

{linear-gradient: ...;}

Internet Explorer 7, 8 en 9 kennen linear-gradient helemaal niet, die krijgen eigen css.

Semantische elementen en WAI-ARIA

Ik heb deze twee onderwerpen samengevoegd, omdat ze veel met elkaar te maken hebben.

Semantische elementen

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

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

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

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

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

html5 heeft een aantal nieuwe elementen, die speciaal zijn bedoeld om de opbouw van een pagina aan te geven. In dit voorbeeld worden hiervan <header>, <nav>, <article>, <section> en <footer> gebruikt. Alle vijf gedragen zich als een gewone <div>, maar dan een <div> met een semantische betekenis. Hierdoor kunnen screenreaders, zoekmachines, en dergelijke beter zien hoe de pagina is samengesteld.

<header>: bedoeld om een header in te zetten.

<nav>: bedoeld om een serie links voor navigeren in te zetten.

<article>: tekst en dergelijke die als een zelfstandig geheel kan worden gezien. In dit voorbeeld is de tekst in de rechterkolom samen met de afbeeldingen een <article>.

<section>: deel van een tekst. In dit voorbeeld is <article> in de rechterkolom onderverdeeld in een aantal <section>'s.

<article>'s en <section>'s kunnen worden genest. Het gaat er alleen om dat een <article> een afgerond geheel is, en ook een deel van een <article> of <section> kan dat zijn.

Een pagina van een krant kan binnen een <article> staan. Binnen dat <article> kan een <section> Sport staan. Binnen die <section> Sport kan weer een <article> met een wedstrijdverslag staan. Binnen een <article>, want zo'n verslag is een afgerond geheel. En binnen dat verslag zouden weer <section>'s kunnen staan voor het deel voor de rust, het deel na de rust, enz.:

<article id="krant"> <section id="sport"> <article id="verslag-1"> <section id="voor-de-rust">tekst</section> <section id="na-de-rust">tekst</section> </article> <article id="verslag-2"> <section id="voor-de-rust">tekst</section> <section id="het-doelpunt">tekst</section> <section id="de-rellen">tekst</section> </article> </section> </section id="economie"> <article id="de-grootgraaiers">tekst</article> </section> </article>

<footer>: bedoeld om een footer in te zetten.

Ook <header> en <footer> mogen vaker op één pagina worden gebruikt. Een <article> zou bijvoorbeeld een eigen <header> en <footer> kunnen hebben, naast de <header> en <footer> voor de hele pagina.

Het is nog niet helemaal duidelijk of dit wel op grote schaal gaat gebeuren, want er zitten fors wat haken en ogen aan, bijvoorbeeld voor zoekmachines. Daar ga ik hier dus verder niet op in. Persoonlijk denk ik vooralsnog dat één <header> en <footer> per pagina het beste is.

Met behulp van dit soort nieuwe semantische elementen kan bijvoorbeeld een screenreader in één keer een hele <header> of <nav> passeren. Alleen hebben deze nieuwe elementen één probleem: ze hebben in de praktijk nog weinig nut, omdat screenreaders en dergelijke ze nog niet herkennen. En voordat alle screenreaders en dergelijke ze herkennen, zijn we jaren verder, want screenreaders zijn peperduur (behalve het uitstekende open source NVDA).

Maar er is niets op tegen om ze nu vast te gaan gebruiken. Op het moment dat screenreaders, zoekmachines, enz. ze gaan herkennen, is de pagina dan al hierop voorbereid. Extra werk is het eigenlijk niet. Het intypen van <nav> gaat even snel als het intypen van <div>, en het intypen van <header> gaat zelfs nog sneller dan <div id="header">, zoals nu vaak gebeurt.

WAI-ARIA

Los van semantische elementen is er nog een hulpmiddel om pagina's beter toegankelijk te maken voor screenreaders en dergelijke: WAI-ARIA-ondersteuning. WAI-ARIA staat voor Web Accessibility Initiative - Accessible Rich Internet Applications.

WAI-ARIA is een hele serie codes die bijvoorbeeld aangeven, welk deel van een pagina een menu, een header, een footer, enz. is. Daarnaast kan WAI-ARIA bij bijvoorbeeld een formulier aangeven of iets is aangevinkt of niet. Voor blinden zijn dit soort zaken uiterst belangrijk (en dus ook voor zoekmachines).

Screenreaders en dergelijke kunnen al jaren WAI-ARIA-codes herkennen. Dat is nog niet het geval met de nieuwe semantische elementen uit html5, en dat zal ook nog wel even duren, want screenreaders zijn peperduur (behalve het uitstekende NVDA).

Een van de groepen met codes binnen WAI-ARIA bestaat uit de zogenaamde landmarks. Daarmee worden belangrijke onderdelen van een pagina gemarkeerd. De landmarks komen gedeeltelijk overeen met de nieuwe semantische html5-elementen. Omdat screenreaders deze landmarks al wel herkennen, zet ik ze bij de corresponderende html-elementen. In de toekomst zijn ze niet meer nodig, maar dat zal nog wel even duren.

Op deze pagina is dit enigszins van belang, omdat de volgorde op het scherm iets afwijkt van de volgorde in de html, en dat kan knap verwarrend zijn. Een screenreader kan niet alleen van kop naar kop, maar ook van landmark naar landmark springen. Daardoor kan bijvoorbeeld het menu toch snel worden gevonden.

In dit voorbeeld gebruik ik de landmarks banner, navigation, contentinfo en main. Elke landmark wordt voorafgegaan door role=, op dezelfde manier als dat bij classes of id's gebeurt:

<header role="banner"> <nav role="navigation"> <article role="main"> <footer role="contentinfo">

De namen zijn wat eigenaardig, maar dat is historisch zo gegroeid. 'main' geeft aan dat daar de belangrijkste content van de pagina begint, de andere roles spreken voor zich.

Op de pagina met links vind je onder het kopje Toegankelijkheid → Forums, richtlijnen, links, artikelen en dergelijke meer info over WAI-ARIA.

Alleen :hover of :hover, :focus en :active?

Het eerste deel van deze tekst is voor alle voorbeelden met links en dergelijke hetzelfde, het laatste deel (onder het kopje Speciaal bij dit voorbeeld) is speciaal voor dit voorbeeld.

De meeste mensen openen 'n link door erop te klikken of door de link met de vinger aan te raken. Bij gebruik van een toetsenbord is er echter 'n tweede manier: met behulp van de Tab-toets (sommige browsers gebruiken andere toetsen, maar het principe is hetzelfde). Met behulp van de Tab-toets kun je van link naar link 'springen'. Op welke link je staat, wordt door alle browsers aangegeven met een of ander kadertje rondom de link.

De link met het kadertje eromheen heeft focus. Dat wil zeggen dat je die link volgt als je op de enter-toets drukt. In principe werkt dit precies hetzelfde als gewoon klikken op de link.

Als iemand geen muis wil of kan gebruiken, bijvoorbeeld door 'n handicap, is deze manier om 'n link te openen erg handig. Als de volgorde van de links in de code niet logisch is, kun je eventueel met behulp van tabindex 'n afwijkende volgorde van de links opgeven. De Tab-toets volgt dan die afwijkende volgorde.

Tot zover is er nauwelijks verschil tussen het gebruik van de Tab-toets of van de muis.

Als je echter extra dingen onder de link hebt gestopt, die pas gaan werken als je over de link hovert, is er wel 'n verschil. Je geeft dat aan met :hover: als je over de link hovert. Met de Tab-toets alleen kun je niet over 'n link hoveren. Dus als er bijvoorbeeld 'n pop-up wordt geopend, zul je die niet zien als je de Tab-toets gebruik om naar 'n link te gaan.

Om dit op te lossen kun je op dezelfde manier als je :hover gebruikt :focus gebruiken: als de link focus heeft. Dat is dus als er 'n kadertje rondom de link staat en de link wordt gevolgd bij het indrukken van enter.

Door dus a:hover, a:focus {...} te gebruiken, opent bijvoorbeeld 'n pop-up ook als je de Tab-toets gebruikt. Maar er zitten 'n paar adders onder het gras.

* Naast :hover en :focus is er nog :active. Deze laatste zou horen te werken als de muis wordt ingedrukt op de link. Dat werkt ook zo in alle browsers, behalve in Internet Explorer vóór versie 8. In haar onmetelijke wijsheid heeft Microsoft besloten af te wijken van de standaard: :active werkt in oudere versies zoals :focus hoort te werken, en :focus werkt gewoon helemaal niet vóór versie 8. In alle andere browsers werken :focus en :active dus wel volgens de standaard, en met ingang van versie 8 van Internet Explorer houdt Microsoft zich ook eindelijk aan de standaard.

Dit betekent dat je niet kunt volstaan met a:hover, a:focus {...}, maar dat je a:hover, a:focus, a:active {...} moet gebruiken, want anders werkt het niet in oudere versies van Internet Explorer. Het zal nog jaren duren voor deze oude versies niet meer worden gebruikt, maar omdat Microsoft zich nu eindelijk ook aan de standaard houdt op dit punt, wordt :active nu ook langzaamaan bruikbaar voor waar het voor is bedoeld.

* Belangrijke informatie moet je niet geven via :focus of :active, omdat dit niet werkt als css uit staat. En op 'n touchscreen is de kans dat het helemaal niet werkt heel erg groot.

* Een pop-up of zoiets kan gruwelijk in de weg komen te staan, bijvoorbeeld door de rest van de pagina af te dekken. Iemand die gewoon de muis kan gebruiken, verplaatst deze even en de pagina is weer zichtbaar. Iemand die moeite heeft met het gebruik van de muis, heeft deze mogelijkheid niet of minder. Als je buiten de link en de daarbij horende pop-up en dergelijke klikt, sluit deze weliswaar, maar dat is nu juist het probleem: mensen die de muis niet goed kunnen gebruiken, hebben nou net daar problemen mee.

Als je via de Terug-toets teruggaat naar de vorige pagina, heeft de link waar je vandaan kwam nog steeds focus, en dus staan pop-up en dergelijke ook nog open. Wat ook heel storend kan zijn als andere delen van de pagina daardoor niet te zien zijn. Op het moment dat ik dit schreef, werkte de Terug-toets bij alle browsers zo, met uitzondering van Google Chrome. Maar 't kan best zijn dat Google Chrome het inmiddels ook doet, of 'n andere juist weer niet, want dit schijnt nogal te veranderen.

* Bij een touchscreen wordt geen muis gebruikt, dus je kunt ook niet over een link hoveren. In sommige browsers is er wel 'n soort imitatie van :hover, maar bij lange na niet in allemaal, dus de werking van :hover (en ook :active) is op mobiel volstrekt onbetrouwbaar.

Om al deze redenen is het goed je even af te vragen of de voordelen van 'n pop-up en dergelijke wel opwegen tegen de nadelen. Ik zet zelf mijn eigen overwegingen bij elk voorbeeld steeds even erbij. Wat natuurlijk niet wil zeggen dat je daar geen andere mening over zou kunnen hebben.

Speciaal bij dit voorbeeld

:focus en :hover werken in dit voorbeeld alleen als de browser touch events niet herkent, dus niet op touchscreens. Dat is ook precies de bedoeling, want op touchscreens kun je niet hoveren, en :focus werkt ook niet of niet goed, omdat het samenwerkt met een toetsenbord. Het hier onderstaande geldt dus niet voor touchscreens. Verder moet het venster van de browser minstens 810 px breed zijn.

In dit geval verkleurt alleen de link, als erover wordt gehoverd of als deze focus heeft. Dit is op geen enkele manier hinderlijk. Daarom gebruik ik hier :focus en :hover beide.

Internet Explorer 7 heeft grotendeels eigen css. Voor dit tranentrekkende satansjong worden in die eigen css :hover en :active gebruikt.

Beschrijving van code en css

De code die te maken heeft met de basis van dit voorbeeld is onderstippeld blauw. Alle voor dit voorbeeld niet-essentiële code is bruin.

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 ontbreken bijvoorbeeld de knoppen voor navigeren op 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>

<html lang="nl">

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.

<meta charset="utf-8">

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

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

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

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

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

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

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

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

Nieuwe sites of pagina's kunnen echter wel rekening houden met de veel kleinere vensters van mobiele apparaten. Deze lay-out bijvoorbeeld past zich aan de breedte van het venster aan, ook bij heel smalle vensters. Maar die stomme mobiele browser weet dat niet, dus die gaat ervan uit dat ook de heel smalle lay-out 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. En dat klopt, want de weer te geven pagina past zich automatisch aan de breedte van het apparaat aan, omdat de pagina altijd 100% breed is. Als het apparaat 300 px breed is, is de pagina ook 300 px breed, maar nog altijd 100%.

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.

Steeds meer mobiele apparaten krijgen een hogere resolutiedichtheid: er staan meer pixels in een inch dan bij een monitor voor de desktop het geval is. Als een lijn 4 px breed is, en de pixels staan vier keer zo dicht op elkaar als op de desktop, zou de lijn maar 1 px breed zijn op een mobiel apparaat. Het is wel een supermooie en strakke lijn, omdat je met vier dicht bij elkaar staande pixels fantastisch scherp kunt weergeven. Alleen is de lijn helaas nauwelijks te zien, omdat hij in al z'n pracht maar 1 px breed is.

Ook niet echt geweldig. Daarom geven ook deze apparaten de breedte weer, alsof de resolutie een standaarddichtheid heeft. Een retina-scherm (een scherm met een hoge resolutiedichtheid) jokt een beetje. Ook een venster van 2048 of 4096 px breed beweert 1024 px breed te zijn. Hierdoor ziet een lijn van 4 px breed er ook op zo'n scherm als 4 px breed uit, en niet als 1 of 2 px breed.

Die hoge resolutiedichtheid heeft wel zin, maar dan op een andere manier. Letters bijvoorbeeld worden al jaren getekend aan de hand van wiskundige formules, het zijn allang geen statische afbeeldingen meer. Die formules kunnen prima met die hoge resolutiedichtheid uit de voeten: een ronding in een letter is veel fijner dan op de desktop. Ook voor hoge kwaliteit afbeeldingen is een hoge resolutiedichtheid zinvol. Het enige waar het niet zinvol is, is bij het aangeven van een maat. Een lijn van 4 px breed moet 4 px breed zijn, en niet 1 px breed in superkwaliteit.

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

<link rel="stylesheet" href="../../css/naam-van-stylesheet.css"> <!-- Instellingen voor Internet Explorer --> <!--[if IE]> <link rel="stylesheet" href="../../css/naam-van-ie-stylesheet.css"> <![endif]-->

Dit stukje code heeft in dit voorbeeldbestand geen enkel nut. Normaal genomen is het een verwijzing naar een extern stylesheet, waarin de style staat. In dit voorbeeld verwijst de href naar een niet bestaand bestand. In html5 is de toevoeging type="text/css" niet meer nodig, omdat dit standaard al zo staat ingesteld.

De bedoeling is dat je bovenstaande regels aanpast voor je eigen bestand. De hele style, die onder deze regels in de <head> staat, wordt dan in het externe bestand geplaatst, waar de href naar verwijst. In dat bestand komt de style precies zo te staan, zoals die nu in de <head> staat. Het bestand moet eindigen op .css.

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 op één enkele centrale plek te aan te brengen.

In die externe stylesheet zet je alles dat in dit voorbeeld tussen <style> en </style> staat (zonder deze begin- en eindregel).

De bovenste regel is voor de algemene stylesheet, geldig voor alle browsers. Dit is gewoon 'n link die naar 'n bestand elders verwijst, waar de css in staat. Op de plaats van "../../css/naam-van-stylesheet.css" moet je pad naar en naam van jouw stylesheet invullen.

Het eigenaardige stukje code daaronder heet een 'conditional comment' en wordt door alle browsers gezien als commentaar, omdat het tussen <!-- en --> staat. Maar Internet Explorer herkent het, door de extra toevoegingen, als speciaal voor Internet Explorer bedoeld en zal het dus uitvoeren. Het is veiliger dan een zogenaamde 'hack', waarbij vaak gebruik wordt gemaakt van 'n fout (bug) in de browser. Dit is opzettelijk aangebracht door Microsoft en zal dus blijven bestaan, terwijl 'n bug gerepareerd kan worden. Op deze manier kun je 'n stylesheet alleen voor Internet Explorer opnemen.

Dit stukje geldt voor alle versies van Internet Explorer, maar je kunt het ook per versie aangeven.

De link verwijst naar een aparte stylesheet voor Internet Explorer, waarin je css speciaal voor die browser zet. Op de plaats van "../../naam-van-ie-stylesheet.css" moet je pad naar en naam van je stylesheet voor Internet Explorer invullen.

De link naar het aparte stylesheet voor Internet Explorer moet ná de link naar het algemene stylesheet komen, omdat de opdrachten voor Internet Explorer die uit de algemene stylesheet dan in principe overrulen.

<style>

In html5 is de toevoeging type="text/css" niet meer nodig.

Voor de duidelijkheid staat de style hier in het bestand zelf, maar het is beter deze in een apart stylesheet te zetten, zoals hierboven beschreven. In die stylesheet komt alles wat tussen bovenstaande regel en </style> staat.

Technisch gezien is er geen enkel bezwaar om het in die stylesheet te zetten met dezelfde vreselijke lay-out, zoals ik die in dit voorbeeld gebruik. Maar als je dat doet, garandeer ik je hele grote problemen, omdat het volstrekt onoverzichtelijk is. Ik gebruik deze lay-out alleen, omdat het anders veel te veel regels worden.

Voorbeeld van 'n goede lay-out in je css:


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

	div#header-binnen {
	    margin-left: 16px;
	    height: 120px;
	    text-align: center;
	}

css voor alle breedtes

body

Het element waarbinnen de hele pagina staat. Veel instellingen die hier worden opgegeven, worden geërfd door de kinderen 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: #fcc;

Dit is de roze achtergrondkleur achter de afbeeldingen. In dit geval is het simpeler om die kleur gewoon aan de hele pagina te geven. Als je aan alle andere onderdelen een andere kleur geeft, blijft alleen de achtergrond achter de afbeeldingen roze.

Omdat er nogal veel met float wordt gewerkt, kan deze achtergrondkleur niet aan <article> worden gegeven. <article> is door al het gefloat niet altijd even hoog als de erin zittende afbeeldingen. De <body> is dat per definitie wel.

color: black;

Voorgrondkleur zwart. Dit is onder andere de kleur van de tekst.

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

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

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

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

font-size: 110%;

Iets groter dan standaard. 't Zal de leeftijd zijn, maar ik vind de standaardgrootte wat te klein.

Ik gebruik hier % als eenheid, en voor alle andere lettergroottes gebruik ik em. Dat komt door Internet Explorer. Als ik als maateenheid iets als px neem, kunnen gebruikers van Internet Explorer de lettergrootte niet veranderen.

Maar als ik overal em neem als maateenheid, wat dan voor de hand zou liggen, kom ik in de problemen met versies van Internet Explorer ouder dan versie 8. De stappen van de verkleining of vergroting zijn in die browsers zo groot, dat 't gelijk onleesbaar klein of absurd groot is.

Als je nou echter bij body geen em gebruikt (font-size: 1.1em; zou hetzelfde moeten zijn als font-size: 110%;), dan is de lettergrootte in Internet Explorer te veranderen, en in oudere versies dan versie 8 zijn de tussenstappen teruggebracht tot normale grootte.

Dit werkt ook als je als lettergrootte 100% invult. Dat heeft geen enkele invloed op de lettergrootte, behalve dus dat de tussenstappen in oudere versies nu normaal werken.

In Internet Explorer 8 is deze bug eindelijk gerepareerd. Aangezien we waarschijnlijk nog vele jaren met oudere versies dan Internet Explorer 8 zitten opgescheept, zal deze truc ook nog jaren moeten worden toegepast.

margin: 0; padding: 0;

Verschillende browsers hebben verschillende standaard-instellingen hiervoor. Door ze gewoon op 0 te zetten, zijn ze overal hetzelfde. Bij deze lay-out is dat nog meer van belang dan normaal, omdat de pagina het hele venster van de browser vult. Als daar dan nog marges of padding bijkomen, kan dat soms overbodige horizontale scrollbalken opleveren, omdat het geheel net niet meer binnen het venster past.

header

Alle <header>'s. Dat is er hier maar een: het deel met de gele achtergrond.

background: yellow;

Gele achtergrond.

color: black;

Voorgrondkleur zwart. Dit is onder andere de kleur van de tekst.

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

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

Ik heb dit ook al bij <body> opgegeven, maar sommige mensen hebben bij álle elementen de kleuren veranderd. Het heeft immers weinig zin, als ze dat alleen bij de body doen, terwijl de sitebouwer de kleuren ook bij bijvoorbeeld de paragrafen heeft aangepast.

text-align: center;

Tekst horizontaal centreren.

padding: 0 4px;

Omdat voor onder en links geen waarden zijn opgegeven, krijgen die automatisch dezelfde waarde als boven en rechts. Hier staat dus eigenlijk 0 4px 0 4px in de volgorde boven - rechts - onder - links. Boven en onder geen padding, links en rechts 4 px padding.

Als eenheid neem ik de absolute eenheid px en geen procent of een andere relatieve eenheid, omdat de padding in een smal venster anders wel heel erg smal zou worden, en in een breed venster wel heel erg breed. Er staan ook geen andere dingen naast de header, waarvoor wat afstand nodig zou kunnen zijn.

Het gaat alleen maar om de afstand tussen de tekst en de rand van de header. Maar er is verder weinig op tegen, als je ook hier 'n relatieve eenheid als procent zou willen gebruiken.

#top

Het element met id="top". Dit is de link bovenin de header naar het menu onderin de pagina. Hij is alleen zichtbaar in vensters smaller dan 600 px, want alleen daar staat het menu onderaan de pagina.

background: black;

Zwarte achtergrond.

color: white;

Witte voorgrondkleur, waardoor ook de tekst wit wordt.

float: left;

Zo hoog mogelijk en dan zover mogelijk naar links zetten. Hierdoor komt hij helemaal in de linkerbovenhoek, links van de bovenste kop, te staan.

margin: 2px 0 0 2px;

Kleine marge aan boven- en linkerkant, zodat hij niet helemaal tegen de zijkant van het venster staat.

Als eenheid neem ik de absolute eenheid px en geen relatieve eenheid als procent of zo, omdat deze kleine afstand van 2 px altijd goed is.

padding: 3px 5px;

Omdat voor onder en links geen waarde is ingevuld, krijgen deze automatisch dezelfde waarde als boven en rechts. Hier staat dus eigenlijk 3px 5px 3px 5px in de volgorde boven - rechts - onder - links.

Dit is relatief vrij veel padding. Hierdoor wordt het zwarte vlak wat hoger en breder, want de zwarte achtergrondkleur loopt door onder de padding. Het valt hierdoor wat meer op, dan wanneer het niet groter zou zijn dan het woord 'Menu'. Bovendien is het nu makkelijker met de vinger te bedienen.

Als eenheid neem ik de absolute eenheid px en geen relatieve eenheid als procent, omdat de link een bepaalde maat moet hebben, groot genoeg om makkelijk met de vinger te bedienen, maar ook niet groter dan dat. Een absolute eenheid is daarvoor beter dan een relatieve.

h1

Belangrijkste kop van de pagina.

font-size: 1.2em;

Iets kleinere letter dan een <h1> standaard krijgt. Door de lettergrootte aan te passen met behulp van css, kan ik het uiterlijk aanpassen, terwijl voor zoekmachines, spraakbrowsers, en dergelijke toch duidelijk blijft dat het om de belangrijkste kop gaat.

Dit is een vrij kleine letter voor zo'n belangrijke kop. Voor grotere vensters wordt de lettergrootte later weer verhoogd.

Als eenheid neem ik em, zodat ook gebruikers van Internet Explorer de lettergrootte kunnen veranderen.

margin: 0;

Een <h> heeft standaard een marge aan boven- en onderkant. Die is hier niet welkom.

header p

De paragrafen binnen <header>.

margin: 0;

Een paragraaf heeft standaard een marge aan boven- en onderkant. Die wil ik hier niet hebben.

h2

Alle <h2>'s. Iets minder belangrijke kopjes dan de <h1>. Ze worden hier gebruikt om de verschillende onderdelen zoals header, footer en beschrijving aan te geven.

font-size: 1.1em;

Iets kleinere letter dan een <h2> standaard heeft. Door de lettergrootte aan te passen met behulp van css, kan ik het uiterlijk aanpassen, terwijl voor zoekmachines, spraakbrowsers, en dergelijke toch duidelijk blijft dat het om een belangrijk onderdeel gaat.

Als eenheid neem ik em, zodat ook gebruikers van Internet Explorer de lettergrootte kunnen veranderen.

margin: 0;

Een <h> heeft standaard een marge aan boven- en onderkant. Die is hier niet welkom.

#tekst

Het element met id="tekst". Dit is de div met de oranje achtergrond, waarbinnen de tekst staat.

background: orange;

Oranje achtergrond.

color: black;

Voorgrondkleur zwart. Dit is onder andere de kleur van de tekst.

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

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

Ik heb dit ook al bij <body> opgegeven, maar sommige mensen hebben bij álle elementen de kleuren veranderd. Het heeft immers weinig zin, als ze dat alleen bij de body doen, terwijl de sitebouwer de kleuren ook bij bijvoorbeeld de paragrafen heeft aangepast.

max-width: 50em;

In brede vensters zou de tekst heel breed kunnen worden, waardoor je heel lange regels krijgt. Te lange regels zijn bijzonder lastig te lezen. Door een maximumbreedte aan #tekst te geven, wordt dat voorkomen. Als eenheid neem ik em. Hierdoor wordt bij een grotere letter de regellengte ook langer, zodat het aantal tekens op een regel hetzelfde blijft, ongeacht de lettergrootte.

padding: 2% 1%;

Omdat voor onder en links geen waarde is ingevuld, krijgen die automatisch dezelfde waarde als boven en rechts. Hier staat dus eigenlijk 2% 1% 2% 1% in de volgorde boven - rechts - onder - links.

Als eenheid gebruik ik hier de relatieve eenheid procent, waardoor de padding in een breder venster groter is dan in een smaller venster. Dat is mooier dan een absolute eenheid, omdat er boven, onder en soms ook naast de tekst andere onderdelen van de pagina kunnen staan. In een groter venster wordt de padding nu ook groter, waardoor de verhoudingen beter bewaard blijven.

position: relative;

Onderaan div#tekst staat div#onderaan. Deze div wordt alleen gebruikt om de overgang van het oranje onder de tekst naar het roze onder de foto's te verzachten. div#onderaan wordt absoluut gepositioneerd ten opzichte van div#tekst. Om dat te kunnen doen, moet div#tekst zelf absoluut, fixed of relatief zijn gepositioneerd. Omdat ik verder niets opgeef, heeft dit verder geen enkele invloed op div#tekst zelf.

h3

Alle <h3>'s. Deze kopjes worden hier gebruikt boven de hoofdstukjes binnen de Beschrijving van de onderdelen.

font-size: 1em;

Normaal genomen heeft een <h3> een iets grotere letter. Hier verander ik de lettergrootte naar standaard. Door de lettergrootte aan te passen met behulp van css, kan ik het uiterlijk aanpassen, terwijl voor zoekmachines, spraakbrowsers, en dergelijke toch duidelijk blijft dat het om kopjes gaat.

Als eenheid neem ik em, zodat ook gebruikers van Internet Explorer de lettergrootte kunnen veranderen.

margin-bottom: 0;

Een <h> heeft standaard een marge aan boven- en onderkant. De marge aan de onderkant is hier niet welkom.

article p

De paragrafen binnen <article>. Op deze pagina is maar één <article>, waarbinnen de tekst met oranje achtergrond en de afbeeldingen staan.

text-indent: 1em;

Elke eerste regel 1 em laten inspringen.

margin: 0;

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

#onderaan

Afbeelding 9: div#onderaan zichtbaar gemaakt

Het element met id="onderaan". Dit is een div die alleen voor de sier wordt gebruikt. Door de idiote achtergrondkleuren die worden gebruikt om de diverse onderdelen van elkaar te kunnen onderscheiden, grenst aan de onderkant de oranje achtergrond onder de tekst aan de roze achtergrond onder de foto's. Daar staan dan ook nog 'ns de foto's doorheen. Zelfs ik, met mijn onderontwikkelde kleurgevoel, krijg daar schele migraine van.

Daarom is onderaan een extra div neergezet, waarin de achtergrondkleur geleidelijk verandert van oranje naar roze. Ik zal niet zeggen dat het nu 'n Rembrandt is, maar, in alle bescheidenheid, 'n Karel Appel zou er nu toch wel voor tekenen.

Op de afbeelding hierboven is div#onderaan doorzichtig gemaakt, boven de afbeeldingen gezet en van een blauwe border voorzien. Hierdoor is de omtrek zichtbaar geworden. Normaal genomen staat div#onderaan onder de foto's en zorgt alleen maar voor de overgang van oranje naar roze, zoals op de afbeelding op de stukken tussen de foto's nog is te zien.

background: -moz-linear-gradient(orange, #fcc); background: -ms-linear-gradient(orange, #fcc); background: -o-linear-gradient(orange, #fcc); background: -webkit-linear-gradient(orange, #fcc); background: linear-gradient(orange, #fcc);

Als je goed kijkt, zie je dat hier in feite vijf keer hetzelfde staat: background: linear-gradient (orange, #fcc);. Waarom dat zo is, staat bij De voorvoegsels -moz-, -ms-, -o- en -webkit-.

Tot de nieuwe eigenschappen van css3 horen gradiënten. Een gradiënt is een geleidelijk verlopende kleur. Een lineaire gradiënt is een in rechte lijn verlopende kleur. (Je hebt ook radiale gradiënten.)

In dit geval is aan de achtergrond van de div geen gewone kleur, maar een gradiënt gegeven. Omdat verder niets is opgegeven over de richting, verloopt deze gradiënt van boven naar onder, de standaardrichting. Bovenaan oranje, onderaan #fcc, wat de roze kleur onder de foto's is. Vóór css3 kon zoiets alleen maar met een extra afbeelding worden gedaan.

Je kunt een gradiënt zelf uitvogelen, maar makkelijker is het, om gebruik te maken van een gradiënt-editor. Ik heb gebruik gemaakt van de gradiënt-editor op colorzilla.com.

width: 100%;

Een blok-element zoals een div wordt normaal genomen automatisch even breed als z'n ouder, dat is hier div#tekst, dus dat komt prima uit. Helaas geldt dat niet als de div absoluut is gepositioneerd, zoals hier het geval is: hij wordt dan niet breder dan nodig is om de inhoud van de div weer te kunnen geven. div#onderaan heeft geen enkele inhoud, want een achtergrondkleur telt niet mee en verder staat er niets in. Dus zou de breedte van deze div 0 worden.

Dat schiet niet op, als je de div juist wilt gebruiken om een achtergrondkleur zichtbaar te maken. Daarom geef ik handmatig een breedte op. Een breedte in procenten wordt altijd genomen ten opzichte van z'n ouder, hier div#tekst. De verlopende achtergrondkleur beslaat nu dus de volle breedte van de div waar de tekst in zit: precies de bedoeling.

height: 100px;

Een blok-element zoals een div wordt normaal genomen precies zo hoog, als nodig is om de inhoud van de div weer te geven. Hier is geen inhoud, alleen een achtergrondkleur, en die telt niet mee als inhoud. De div zou dus een hoogte van 0 krijgen. Daarom geef ik met de hand een hoogte van 100 px op.

Ik gebruik hier de absolute eenheid px en geen relatieve eenheid als procent, omdat de overgang tussen de kleuren altijd even hoog mag zijn, ongeacht de hoogte van het venster van de browser.

Zonder css-gradiënt had ik een afbeelding moeten gebruiken om een verlopende kleur te krijgen. Dat is een extra aanroep naar de server. Bovendien zou die afbeelding moeten worden aangepast als de hoogte van div#onderaan verandert. Bij een css-gradiënt kun je probleemloos de hoogte veranderen: de gradiënt verandert automatisch mee.

position: absolute;

Er wordt gepositioneerd ten opzichte van de eerste ouder die zelf een relatieve, absolute of fixed positie heeft. Dat is hier div#tekst.

bottom: -100px;

De div is 100 px hoog. Als ik hem gewoon aan de onderkant binnen div#tekst zou zetten, zou ik aan de onderkant van div#tekst een lege ruimte van 100 px krijgen, omdat div#onderaan de onderkant van div#tekst 100 px omlaag duwt. Pas daaronder zouden dan de afbeeldingen komen te staan. Hierdoor zou er altijd een extra lege ruimte van 100 px tussen tekst en afbeeldingen ontstaan.

Daarom wordt div#onderaan absoluut gepositioneerd en 100 px naar beneden neergezet. Nu komt hij beneden div#tekst te staan en ontstaat er geen extra lege ruimte aan de onderkant van div#tekst.

(Dat de foto's toch af en toe toch onder div#onderaan komen te staan, heeft niets met div#onderaan te maken, maar met het floaten van de foto's in combinatie met de breedte van het venster van de browser. In een venster van bijvoorbeeld 1280 px breed worden, zonder zoomen en dergelijke, de foto's over div#onderaan gezet. Zonder absolute positie zou ook hier een extra ruimte van 100 px boven de foto's verschijnen.)

left: 0; Afbeelding 10: kier aan linkerkant van div#onderaan

Deze positie is ten opzichte van de eerste ouder die zelf een relatieve, fixed of absolute positie heeft. Dat is hier div#tekst, die een padding heeft aan onder andere de linkerkant. Door die padding zou div#onderaan iets te veel naar links komen te staan, waardoor je links door een 'kier' de roze achtergrondkleur achter de foto's te zien zou krijgen. Dat is op de afbeelding de roze baan tussen het groen en de verlopende kleur. Nu wordt div#onderaan helemaal links binnen div#tekst gezet en wordt deze roze streep voorkomen.

Omdat hierboven div#onderaan 100 % breed is gemaakt, is hij even breed als z'n ouder div#tekst. Aan de rechterkant speelt hierdoor deze kier niet. Maar als div#onderaan niet helemaal links zou worden neergezet, zou aan de rechterkant wel een stukje buiten div#tekst komen te staan. Als het beginpunt links te veel naar rechts staat en div#onderaan is even breed als div#tekst, dan móét er rechts wel 'n stukje buiten div#tekst uitsteken.

#foto

Het element met id="foto". Dit is de div waarbinnen de foto's staan.

position: relative;

div#foto komt in de html na div#tekst. Daardoor zou normaal genomen deze div, met de daarin zittende afbeeldingen, over div#tekst komen te staan. En dus ook over de in div#tekst zittende div#onderaan.

div#tekst heeft echter een relatieve positie gekregen. Daardoor krijgt div#tekst ook automatisch een z-index van 1. De z-index geeft de volgorde in de hoogte aan: als twee of meer elementen op dezelfde plaats op het scherm staan, bepaalt de z-index welk van de elementen zichtbaar is.

Afbeelding 11: div#onderaan staat over de foto's heen
Zonder z-index komt div#onderaan over de foto's te staan. div#onderaan heeft even 'n blauw randje gekregen om hem zichtbaar te maken. Alleen kinderhaters kunnen tevreden zijn met dit resultaat.

In dit geval kunnen div#onderaan en div#foto over elkaar heen komen te staan, op dezelfde plaats. div#onderaan staat binnen div#tekst, die een z-index van 1 heeft gekregen door z'n relatieve positie.

div#foto heeft geen z-index, omdat hij niet relatief, absoluut of fixed is gepositioneerd.

Daardoor komt div#foto, en dus ook de afbeeldingen en tekst daarbinnen, toch ónder div#onderaan te staan, ondanks dat div#foto in de volgorde van de html na div#onderaan staat. Door ook div#onderaan een relatieve positie te geven, krijgt ook div#foto een z-index van 1. En staat nu dus boven div#onderaan, want nu geldt de volgorde in de html gewoon weer.

#foto h2

De <h2>'s binnen het element met id="foto". Dat is er hier maar eentje: het kopje waar 'Foto's' in staat.

text-align: center;

Tekst horizontaal centreren.

Een <h2> is een blok-element en krijgt daardoor normaal genomen automatisch dezelfde breedte als z'n ouder. Als de afbeeldingen onder de tekst komen te staan, is de <h2> daardoor even breed als het venster en zal de tekst 'Foto's' dus horizontaal gecentreerd boven de foto's komen te staan.

Als de afbeeldingen naast de tekst komen te staan, staat het kopje horizontaal gecentreerd boven de ruimte naast de tekst. De <h2> wordt even breed als z'n ouder #foto, maar omdat div#tekst met de daarin zittende tekst nu naar links wordt gefloat, wordt bij het centreren alleen gekeken naar de lege ruimte rechts van de tekst. En staat het kopje dus weer gecentreerd boven de foto of foto's.

Het kopje staat dus altijd horizontaal gecentreerd boven de foto's, ongeacht de breedte van het venster van de browser.

#foto p

De paragrafen binnen het element met id="foto". Dat is er hier maar eentje. De tekst gelijk onder het kopje 'Foto's' staat erin.

text-align: center;

Tekst horizontaal centreren. Hiervoor geldt hetzelfde verhaal als gelijk hierboven bij #foto h2.

text-indent: 0;

Bij article p hebben de <p>'s binnen <article> een text-indent gekregen. Omdat div#foto binnen <article> staat, krijgen ook de <p>'s binnen div#foto die text-indent. Dat is niet handig als je ook wilt centreren, dus weg ermee.

margin-bottom: 5px;

Kleine ruimte tussen de onderkant van de tekst en de bovenst afbeelding(en).

padding: 0 5px;

Omdat voor onder en links geen waarde is opgegeven, krijgen die automatisch dezelfde waarde als boven en rechts. Hier staat dus eigenlijk 0 5px 0 5px in de volgorde boven - rechts - onder - links. Boven en onder geen padding, rechts en links 5 px.

figure

Alle <figure>'s. Binnen elk van deze elementen staat een <img> met een afbeelding en een <figcaption> met het bijbehorende onderschrift.

<figure> is een blok-element. Normaal genomen wordt een blok-element even breed als zijn ouder. Dat is hier div#foto. Omdat deze div geen breedte heeft, wordt die normaal genomen ook weer even breed als z'n ouder. Dat is <article>. Ook die heeft geen breedte. Het wordt eentonig: ook die wordt daarom weer even breed als z'n ouder. Dat is div#wrapper. En je raadt het al: die heeft ook weer geen breedte. De ouder van div#wrapper is <body>, de pagina. Daardoor wordt div#wrapper even breed als <body> en daarmee het venster van de browser. Via deze hele ketting terug wordt <figure> uiteindelijk ook even breed als het venster.

Voor bredere vensters is dit niet de bedoeling. Daarvoor volgt later aparte css. Maar voor smalle vensters is dit wel de bedoeling. De <figure> komt in smalle vensters beneden de tekst te staan en mag daar het hele venster in de breedte vullen.

text-align: center;

<figure> heeft een variabele breedte, afhankelijk van de breedte van het venster van de browser. Binnen <figure> staan <img>'s en <figcaption>'s met tekst, die altijd horizontaal gecentreerd moeten staan. Bovendien mogen die <img>'s en <figcaption>'s nooit breder zijn dan <figure>, maar de <figcaption>'s moeten wel altijd breed genoeg zijn om de onderschriften op één regel neer te kunnen zetten. Om het feest compleet te maken, blijkt Opera Mobiel op Android 4.0.3 dan ook nog 'ns spontaan de lettergrootte te verhogen.

Dan wordt ook nog van de <img> een blok-element gemaakt om van de ingebakken regelhoogte af te komen. En de <figcaption> heeft een witte achtergrond die netjes midden onder de afbeelding moet komen te staan.

Enig experimenteren met de combinatie <figure>, <img> en <figcaption> leerde dat dit de oplossing is voor een deel van het probleem. De onderschriften in de <figcaption>'s staan nu horizontaal gecentreerd.

Mogelijk had dit ook bij <figcaption> kunnen staan, maar dankzij een dreigende lichte overspannenheid, opgelopen bij het oplossen van dit raadsel, besloot ik het zo te laten. Het werkt. Overal. Punt.

margin: 0;

Een <figure> blijkt standaard een marge aan alle kanten te hebben. Dat is ongetwijfeld meestal fantastisch, maar hier even niet. Weg ermee.

figure img

De <img>'s binnen <figure>. Binnen elke <figure> staat één <img>: een thumbnail.

display: block;

In tegenstelling tot wat veel mensen denken, is een <img> een inline-element. Met wat aparte eigenschappen, maar het blijft een inline-element. Daardoor heeft een <img> een regelhoogte. Door die regelhoogte ontstaat ook wat ruimte onder de <img>, omdat staartletters als de 'g' en de 'p' iets onder de regel uitsteken.

Afbeelding 12: kier tussen foto en onderschrift

Dat veroorzaakt problemen, omdat er een opening ontstaat tussen de afbeelding en de witte achtergrond van het onderschrift. De roze kier onder de foto op de afbeelding hiernaast is de ruimte die wordt gereserveerd voor de staartletters. Heel vriendelijk, maar in dit geval is er helemaal geen tekst, dus die ruimte is niet nodig.

De <img> staat in een <figure>. <figure> heeft niet apart een regelhoogte gekregen, maar elk blok-element waar een inline-element in staat, heeft automatisch een regelhoogte. Als je geen regelhoogte opgeeft, krijgt <figure> gewoon de standaardregelhoogte van ongeveer 1,2 em.

Een <img> is een inline-element. Een inline-element kan nooit een kleinere regelhoogte krijgen dan het blok-element waar hij in staat. De <img> kan dus nooit een regelhoogte van minder dan 1,2 em krijgen. (Dit lijkt misschien vreemd, maar meestal is dit juist handig.)

Ik kan de regelhoogte bij <figure> op 0 zetten, maar dan geldt die ook voor <figcaption>, want dat zit ook binnen <figure>. En daar wil ik wel een regelhoogte hebben.

De simpelste manier is om gewoon van de <img> zelf een blok-element te maken. Omdat er in de tot blok-element gepromoveerde <img> verder niets staat, is de regelhoogte nu weg. (In een <img> kán niets staan, omdat het gewoon een gesloten afbeelding is. Behalve de src en de alt en zo staat er niets binnen de <img>, en die hebben geen invloed op de regelhoogte.)

width: 200px;

Alle afbeeldingen zijn 200 px breed. Daarom is het in dit geval efficiënter om die breedte hier centraal op één plaats te geven, dan apart bij elke afbeelding.

Bovendien wordt de breedte soms iets aangepast aan de breedte van het venster van de browser. Een breedte die wordt opgegeven in de css overrulet weliswaar een breedte die wordt opgegeven bij de <img> in de html, maar het is nogal verwarrend als je op twee plaatsen een breedte opgeeft.

Ik geef geen hoogte op. Daardoor wordt de hoogte automatisch evenveel aangepast als de breedte, waardoor je een lachspiegel-effect voorkomt.

margin: 0 auto;

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

Boven en onder geen marge.

Links en rechts auto, wat hier betekent: evenveel. De afbeelding staat nu altijd horizontaal gecentreerd binnen z'n ouder <figure>, ongeacht de breedte van <figure>.

Deze manier van horizontaal centreren van een blok-element (de <img> is hierboven veranderd in een blok-element) werkt alleen, als het te centreren blok-element een breedte heeft.

border:white solid 1px;

Klein wit randje rondom de afbeelding.

figcaption

Alle <figcaption>'s. Binnen elke <figure> staat één <figcaption>, waarbinnen het onderschrift onder de afbeelding staat.

background: white;

Witte achtergrond.

color: black;

Voorgrondkleur zwart. Dit is onder andere de kleur van de tekst.

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

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

Ik heb dit ook al bij <body> opgegeven, maar sommige mensen hebben bij álle elementen de kleuren veranderd. Het heeft immers weinig zin, als ze dat alleen bij de body doen, terwijl de sitebouwer de kleuren ook bij bijvoorbeeld de paragrafen heeft aangepast.

width: 60%;

Een percentage in breedte wordt altijd genomen ten opzichte van de ouder van het element. Die ouder is hier <figure>. Het onderschrift wordt dus niet breder dan 60 procent van de breedte van <figure>. Dit is smaller dan de afbeelding, maar breed genoeg om alle onderschriften op één regel weer te kunnen geven.

max-width: 190px;

Dat verhaal hier gelijk boven over die breedte is mooi, maar het gaat niet altijd op. Als er, in een smal venster, maar één rij foto's onder de tekst staat, dan wordt <figure> even breed als het venster. Maar de <img> wordt nooit breder dan 200 px. Een <figcaption> van 60% breedte kan dan breder worden dan de erboven staande foto, waardoor ook de witte achtergrond breder wordt dan de foto. En dat is foeilelijk. Voor dit soort situaties geef ik een maximumbreedte op, die net iets minder is dan de breedte van 200 px van de <img>.

font-size: 0.7em;

Kleinere letter. Als eenheid neem ik em, zodat ook gebruikers van Internet Explorer de lettergrootte kunnen veranderen.

font-style: italic;

Cursief.

margin: 0 auto 10px;

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

Aan de onderkant een marge van 10 px, waardoor er wat ruimte komt tussen het onderschrift en de afbeelding eronder.

Rechts en links auto, wat hier betekent: evenveel. Hierdoor staat de <figcaption> altijd horizontaal gecentreerd binnen <figure>. En omdat bij figure text-align: center; is opgegeven, staat de tekst weer horizontaal gecentreerd binnen <figcaption>.

Deze manier van horizontaal centreren van een blok-element (<figcaption> is een blok-element) werkt alleen, als het te centreren blok-element een breedte heeft.

Omdat bij figure img ook de <img>'s horizontaal gecentreerd zijn binnen <figure>, staan de onderschriften ook ten opzichte van de <img>'s horizontaal gecentreerd.

border: black solid;

Zwart randje. De breedte geef ik gelijk hieronder op.

border-width: 0 1px 1px;

De kleur en stijl heb ik gelijk hierboven al opgegeven.

Omdat voor links geen waarde is opgegeven, krijgt links automatisch dezelfde waarde als rechts. Hier staat dus eigenlijk 0 1px 1px 1px in de volgorde boven - rechts - onder - links. Aan alle kanten een border, behalve aan de bovenkant.

Deze manier van een border opgeven is simpeler dan het schrijven van css voor drie aparte borders.

nav

Alle <nav>'s. Dat is er hier maar eentje: de <nav> waar het menu in staat.

background: #0f0;

Groene achtergrond. Afhankelijk van waar het menu staat, zie je helemaal niets of juist heel veel van deze groene achtergrond.

color: black;

Voorgrondkleur zwart. Dit is onder andere de kleur van de tekst.

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

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

Ik heb dit ook al bij <body> opgegeven, maar sommige mensen hebben bij álle elementen de kleuren veranderd. Het heeft immers weinig zin, als ze dat alleen bij de body doen, terwijl de sitebouwer de kleuren ook bij bijvoorbeeld de paragrafen heeft aangepast.

font-size: 0.7em;

Iets kleinere letter. Als eenheid neem ik em, zodat ook gebruikers van Internet Explorer de lettergrootte kunnen veranderen.

nav h2

De <h2>'s binnen <nav>. Dat is er hier maar eentje: het kopje 'Menu'.

display: none;

In smallere browservensters staat het menu onderaan het venster in de vorm van grote knoppen, of het is een balk met knoppen bovenaan het venster. Omdat overduidelijk is dat dit een menu is, is de toevoeging 'Menu' overbodig.

Waar het menu links komt te staan, wordt dit kopje verderop weer zichtbaar gemaakt.

text-align: center;

Tekst horizontaal centreren.

margin-bottom: 5px;

Kleine afstand tussen het kopje en de eerste knop eronder.

nav ul

De ongeordende lijsten binnen een <nav>. Er is hier maar één <nav>, en daarin staat maar één <ul>. Daarbinnen staat het menu.

Een menu kan normaal genomen het beste binnen een <ul> worden gezet. Spraakbrowsers en dergelijke kunnen een <ul> in één keer passeren, waardoor blinden niet het hele menu voorgelezen krijgen. In de toekomst zal dat waarschijnlijk ook het geval zijn met <nav>, maar het duurt nog jaren voor elke spraakbrowser en dergelijke dat kan.

Los hiervan is een menu binnen een <ul> het makkelijkst op te maken.

list-style-type: none;

De gebruikelijk balletjes en dergelijke van een <ul> zijn hier niet welkom.

margin: 0; padding: 0;

Verschillende browsers hebben verschillende standaardinstellingen voor marge en padding bij een <ul>. Door beide op 0 te zetten, zijn ze overal hetzelfde.

nav li

De <li>'s binnen een <nav>. Er is hier maar één <nav>, waarbinnen het menu staat. Binnen de <li>'s staan de links van het menu.

width: 50%;

Een <li> is een blok-element en wordt normaal genomen even breed als zijn ouder, de <ul>. De <ul> is ook een blok-element en wordt normaal genomen ook even breed als z'n ouder, de <nav>. Ook de <nav> is een blok-element en wordt dus ook weer even breed als z'n ouder: div#wrapper. Ik kan het ook niet helpen, het wordt eentonig: die wordt ook weer even breed als zijn ouder: <body>. Even breed als de pagina dus. Via die hele ketting zou de <li> ook even breed als de pagina worden.

In dit geval is dat niet zo, omdat de <li>'s hieronder gefloat worden. En een gefloat blok-element krijgt niet meer ruimte dan nodig is, om de inhoud ervan weer te kunnen geven. De knoppen worden daardoor heel smal, want een knop met de tekst 'Top' wordt maar drie letters breed. Niet echt ideaal om met je vingers te bedienen.

Daarom geef ik zelf een breedte op: 50%.

Een breedte in procenten is altijd ten opzichte van de ouder. Via die hele ketting die hierboven staat opgesomd, kom je uiteindelijk bij de pagina uit. Elke <li>, en dus elke link in het menu, wordt half zo breed als de pagina. Nu zijn ze makkelijk met de vinger te bedienen.

float: left;

Een <li> is een blok-element. Normaal genomen komen die op een nieuwe regel te staan. Door ze naar links te floaten, komen er zoveel op één regel te staan als er naast elkaar passen. Omdat elke <li> hierboven half zo breed als de pagina is gemaakt, staan er twee <li>'s en dus twee knoppen uit het menu naast elkaar.

nav a

De links binnen een <nav>. Hier is maar één <nav>: de <nav> met het menu. In elke <a> staat één link van dat menu.

background: #ccc;

Achtergrond grijs.

color: black;

Tekst binnen een <a> krijgt normaal genomen een kleurtje. Het is hier al duidelijk genoeg dat het om een link gaat, en ik vind een kleurtje hier niet mooi.

display: block;

Een <a> is van zichzelf een inline-element. Door er een blok-element van te maken, kun je eigenschappen als hoogte gebruiken.

height: 1.2cm;

Eigenlijk zou dit niet nodig horen te zijn, omdat de regelhoogte hieronder ook al op 1,2 cm wordt gezet. Maar Opera Mini op Android 2.3.6 negeert die regelhoogte, waardoor je veel te kleine knoppen voor je vingers krijgt.

Als eenheid neem ik de absolute maat cm, zodat de knop altijd groot genoeg is, los van zoomen.

line-height: 1.2cm;

Tekst wordt automatisch halverwege de regelhoogte gezet. Door de regelhoogte even hoog te maken als de hoogte, komt de tekst automatisch halverwege de hoogte van de <a> te staan, en is dus verticaal gecentreerd.

Omdat de hoogte in cm is, is de regelhoogte ook in cm opgegeven.

text-align: center;

Tekst horizontaal centreren.

text-decoration: none;

Tekst binnen een <a> wordt normaal genomen onderstreept. Het is hier al duidelijk genoeg dat het om een link gaat, en ik vind een onderstreping hier niet mooi.

border: black solid;

Randje rondom de links. De breedte geef ik gelijk hieronder op.

border-width: 1px 1px 0 0;

De kleur en stijl heb ik gelijk hierboven al opgegeven.

Boven en rechts een border, onder en links niet.

De links komen naast en onder elkaar te staan. Als je aan alle vier de kanten een border zou opgeven, zouden op de grens tussen twee links twee borders tegen elkaar komen te staan, waardoor je daar een dikte van 2 px zou krijgen. Door de border aan onder- en linkerkant weg te laten, voorkom je dat.

Deze manier van een border opgeven is simpeler dan het schrijven van css voor twee aparte borders.

Er zit nu wel een opening aan de onderkant van de onderste knoppen, dat wordt later gecorrigeerd. Ook aan de linkerkant zit een opening: de border aan de linkerkant van de linkerknoppen mist. Alleen wordt die niet gecorrigeerd, omdat het nauwelijks opvalt dat daar een border mist.

nav li:nth-last-child(2) a

De <a>'s binnen een <li> binnen <nav>. Maar niet elke <li>, het gaat om één bepaalde <li>: de <li> binnen <nav> die het tweede kind van <nav> is, van achteraf geteld. :nth-last-child wil simpelweg zeggen: van achteraf geteld. En de 2 staat voor: de tweede. (Je kunt ook ingewikkelder dingen met deze selector (eigenlijk een pseudo-class) doen, maar dat gebeurt hier niet.)

Zoals bij alle <li>'s, zit ook binnen dit lijst-item maar één <a>. Uiteindelijk geldt dit dus voor de tweede link van het menu, van achteraf geteld.

Bij nav a is aan de links binnen het menu een border aan de bovenkant en aan de rechterkant gegeven. Aan de onderkant is geen border gegeven. Bij de laatste link 'Top' is dat geen probleem, omdat die tegen de footer staat. En de footer heeft aan de bovenkant een border.

Bij de een-na-laatste link, 'Link acht', kan de border aan de onderkant wel zichtbaar ontbreken.

Als er een oneven aantal links is, staat deze link namelijk in de rechterkolom, terwijl er in de linkerkolom nog een lagere link staat. Dat is op de afbeelding hieronder ook het geval. En dan zou je zien dat rechts een border aan de onderkant mist. Daarom wordt hier bij 'Link acht' een border aan de onderkant toegevoegd.

In dit geval is het beter om de links vanaf de achterkant te tellen. Het gaat namelijk altijd om de een-na-laatste link, die mogelijk een border aan de onderkant moet krijgen. Als er ooit 'n link wordt tussengevoegd of weggehaald, zou je makkelijk kunnen vergeten deze selector aan te passen. Nu hoeft hij nooit aangepast te worden, want de een-na-laatste link is altijd de een-na-laatste, hoeveel links er ook nog bij zouden komen of af zouden gaan.

margin-bottom: -1px; Afbeelding 13: ongelijke border onderaan knoppen menu

Dit zijn de laatste knoppen uit het menu, zoals ze in een smal venster worden weergegeven. 'Link acht' krijgt gelijk hieronder een border aan de onderkant.

'Link zeven' heeft geen border aan de onderkant. De border die je daar ziet, is de border aan de bovenkant van link 'Top'.

Hierdoor komt 'Link acht' 1 px lager uit dan 'Link zeven'. Omdat de <li>'s waar de links in staan naar links worden gefloat, komt hierdoor 'Top' 1 px te laag te staan. Dit is de reden van de verspringende lijn onder 'Link zeven' en 'Link acht' op de afbeelding.

Om dat te corrigeren wordt aan 'Link acht' aan de onderkant een negatieve marge van 1 px gegeven. Deze trekt alles onder 'Link acht', dus ook 'Top', 1 px omhoog, waardoor alles weer op de juiste hoogte staat.

Als 'Link acht', omdat er 'n link wordt tussengevoegd of weggehaald, gelijk boven de footer zou komen te staan, zou de border aan de onderkant van 'Link acht' tegen de border aan de bovenkant van de footer komen te staan. Wat een border van 2 px op zou leveren.

Ook dat wordt hiermee voorkomen, want nu wordt met deze negatieve marge van 1 px de footer 1 px omhoog getrokken. Daardoor komt de border aan de bovenkant van de footer over de border aan de onderkant van 'Link acht' te staan, en zie je die dus niet meer.

border-bottom: black solid 1px;

Border aan de onderkant.

footer p

De paragrafen binnen <footer>.

margin: 0 4px;

Omdat voor onder en links geen waarde is opgegeven, krijgen die automatisch dezelfde waarde als boven en rechts. Hier staat dus eigenlijk 0 4px 0 4px in de volgorde boven - rechts - onder - links.

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

Links en rechts een kleine afstand tussen <p>'s, en dus de tekst daarin, en zijkant van de footer.

css voor vensters breder dan 600 px

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

De css die hier tot nu toe staat, geldt voor alle browservensters. De css die hieronder staat, geldt alleen voor browservensters breder dan 600 px. Voor een deel is dit nieuwe css, voor een deel wordt hierboven staande css aangepast.

@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 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. Als je wilt printen, is het beter een stylesheet daarvoor te baseren op de algemene css die hierboven staat.

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

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

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

@media screen and (min-width: 600px) { 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 }.

#wrapper

Het element met id="wrapper". Dit is een div, waarbinnen tekst, afbeeldingen en menu staan. Deze div vult de ruimte tussen <header> en <footer>.

position: relative;

Het menu wordt gepositioneerd ten opzichte van deze div. Om dat te kunnen doen, moet deze div zelf een relatieve, absolute of fixed positie hebben. Omdat ik hier verder niets bij opgeef, heeft dit voor div#wrapper zelf verder geen enkele invloed.

#top

Het element met id="top". Dit is de link bovenin de header naar het menu onderin de pagina. Hij is alleen zichtbaar in vensters smaller dan 600 px, want alleen daar staat het menu onderaan de pagina.

display: none;

In vensters breder dan 600 px staat het menu bovenaan de pagina, of het staat op een vaste plaats aan de linkerkant en scrolt niet mee. In beide gevallen is de link naar het menu aan de onderkant van de pagina niet nodig, dus wordt hij verborgen.

h1

Belangrijkste kop van de pagina.

font-size: 1.6em;

Hierboven is de lettergrootte verkleind tot 1,2 em. Dat is veel kleiner dan de standaardlettergrootte van een <h1>. In vensters breder dan 600 px is er meer ruimte, daarom wordt de lettergrootte hier weer verhoogd. 1,6 em is nog steeds kleiner dan de standaardlettergrootte van een <h1>, maar die is ook wel érg groot.

Door de lettergrootte aan te passen met behulp van css, kan ik het uiterlijk aanpassen, terwijl voor zoekmachines, spraakbrowsers, en dergelijke toch duidelijk blijft dat het om de belangrijkste kop gaat.

Als eenheid gebruik ik em, zodat ook gebruikers van Internet Explorer de lettergrootte kunnen veranderen.

h2

Alle <h2>'s. Iets minder belangrijke kopjes dan de <h1>. Ze worden hier gebruikt om de verschillende onderdelen zoals header, footer en beschrijving aan te geven.

font-size: 1.2em;

Hierboven is de lettergrootte verkleind tot 1,1 em. Dat is veel kleiner dan de standaardlettergrootte van een <h2>. In vensters breder dan 600 px is er meer ruimte, daarom wordt de lettergrootte hier weer verhoogd. 1,2 em is nog steeds kleiner dan de standaardlettergrootte van een <h2>, maar hier groot genoeg.

Door de lettergrootte aan te passen met behulp van css, kan ik het uiterlijk aanpassen, terwijl voor zoekmachines, spraakbrowsers, en dergelijke toch duidelijk blijft dat het om een belangrijk onderdeel gaat.

Als eenheid gebruik ik em, zodat ook gebruikers van Internet Explorer de lettergrootte kunnen veranderen.

article

Alle <article>'s. Dat is er hier maar eentje. De tekst en de afbeeldingen staan erin.

padding-top: 2.2em;

Verderop wordt het menu absoluut gepositioneerd aan de bovenkant van <article>, in de vorm van een horizontale balk met knoppen. Daardoor zou het over de tekst in <article> heen komen te staan. Deze padding zet de tekst een stukje lager, zodat dat wordt voorkomen.

figure

Alle <figure>'s. Binnen elke <figure> staan een <img> en een <figcaption> met het onderschrift bij de afbeelding.

width: 25%;

Bovenin div#tekst, waarin de tekst met de oranje achtergrond staat. Onder div#tekst staan de <figure>'s met de afbeeldingen. Omdat de tekst de volle breedte van het venster vult, is er geen ruimte naast de tekst voor afbeeldingen. Dat komt pas in nog bredere vensters.

De <figure>'s met de afbeeldingen komen dus noodgedwongen onder de tekst te staan. Door ze 25% breed te maken, passen er precies vier naast elkaar, netjes verdeeld over de breedte van het venster van de browser.

float: left;

Een <figure> is een blok-element. Een blok-element komt normaal genomen op een nieuwe regel te staan. Door ze naar links te floaten, komen ze naast elkaar te staan. En omdat elke <figure> hierboven 25% breed is gemaakt, passen er precies vier naast elkaar op elke regel.

figure img

Alle <img>'s binnen een <figure>. Binnen elke <figure> staat een <img>: de kleine foto's.

max-width: 94%; Afbeelding 14: marge rondom foto's zichtbaar gemaakt

De <figure>'s hebben bij figure een breedte van 25% gekregen, zodat er vier naast elkaar passen. Maar ze staan dan wel helemaal tegen elkaar aan. Op de afbeelding hebben de <figure>'s een blauwe outline gekregen, zodat dat zichtbaar wordt.

Door de <img> een maximumbreedte van 94% te geven, ontstaat er toch wat ruimte tussen de afbeeldingen. Een breedte in procenten wordt altijd genomen ten opzichte van de ouder, dus de <img> is altijd minstens 6% smaller dan de <figure>.

Bij figure img is de <img> horizontaal gecentreerd binnen <figure>, zodat de marge links en rechts altijd even groot is. In bredere browservensters wordt de <figure> breder. Maar de <img> wordt nooit breder dan de 200 px, die de afbeelding breed is, en blijft altijd horizontaal gecentreerd binnen <figure>.

figcaption

Alle <figcaption>'s. Binnen elke <figure> staat een <img>. Het onderschrift bij de <img> staat in een <figcaption> binnen de <figure>.

width: 70%;

Bij de css voor alle breedtes hierboven is de breedte 60% gemaakt. Dat is in principe genoeg om het onderschrift op één regel weer te geven.

Afbeelding 15
Afbeelding 15: de volgende regel met afbeeldingen begint niet helemaal links, maar pas na de dubbele regel. Niet echt 'n ramp, maar het is netter als dit niet gebeurt.

Maar Opera Mobiel op Android 4.0.3 maakt de letters om een of andere reden groter, en dan passen de onderschriften niet meer op één regel. Door de breedte van de <figcaption> iets groter te maken, past alles weer op dezelfde regel.

Als een onderschrift niet op één regel past, verstoort dit het floaten van de <figure>'s. De nieuwe regel met <figure>'s wordt niet aan het begin begonnen, maar gelijk na het onderschrift dat op twee regels staat. Daarom is het beter dat te voorkomen. Overigens gebeurt dit in meerdere browsers, maar dan pas als de letters heel sterk worden vergroot.

nav

Alle <nav>'s. Dat is er hier maar eentje, het menu staat erin.

width: 100%;

Het menu moet over de volle breedte van de pagina komen te staan, gelijk onder <header>.

Een <nav> is een blok-element. Normaal genomen krijgt een blok-element automatisch dezelfde breedte als z'n ouder. Dat is hier div#wrapper. Ook div#wrapper wordt weer even breed als z'n ouder. Dat is <body>. div#wrapper en daardoor <nav> worden dus even breed als de pagina.

Maar hier niet. In <nav> zit een <h2> met 'Menu'. Die is bij nav h2 verborgen met display: none; en telt daarom hier niet mee.

Afbeelding 16: Te smalle knoppen in menu
Afbeelding 16: het tot grote droefenis stemmende resultaat als je niet zelf een breedte aan <nav> geeft. De bezuinigingen van Rutte zijn er niets bij.

Verder zit er een <ul> in de <nav>. De <li>'s in die <ul> worden naar links gefloat. Meer zit er niet in de <nav>. En als de inhoud van een blok-element wordt gefloat, krijgt het blok-element niet meer automatisch de volle breedte van z'n ouder, maar wordt niet breder dan nodig is om de inhoud weer te geven.

Door de <nav> een breedte van 100% te geven, wordt hij toch even breed als z'n ouder <article>, en omdat <article> even breed is als <body>, wordt de <nav> ook even breed als de pagina.

position: absolute;

Om de <nav> en dus het daarin zittende menu op de juiste plaats neer te kunnen zetten. Er wordt gepositioneerd ten opzichte van de eerste ouder die zelf een absolute, relatieve of fixed positie heeft. Dat is hier div#wrapper.

top: 0;

Helemaal bovenaan div#wrapper neerzetten. Omdat div#wrapper gelijk onder <header> begint, staat het menu tegen <header> aan.

#naar-top

Het element met id="naar-top". Dit is de laatste <li> binnen het menu met de tekst 'Top'. Als het menu onderaan de pagina staat, zoals in browservensters smaller dan 600 px het geval is, kun je met deze link weer terug naar boven gaan.

Omdat het de laatste <li> binnen de <ul> met het menu is, zou je ook de pseudo-class :last-child kunnen gebruiken, maar die wordt niet herkend door Internet Explorer 7 en 8. Daarom is een class gebruikt.

display: none;

De link naar boven is alleen nodig in vensters smaller dan 600 px, waar het menu onderaan komt te staan. In bredere vensters is hij overbodig en kan dus worden verborgen.

nav li

Alle <li>'s binnen <nav>. Er is hier maar één <nav>, waarbinnen het menu staat. Binnen elke <li> staat één link van dat menu.

width: 12%;

Er zijn acht lijst-items. Om de volle breedte van 100% te vullen, zou je elk lijst-item 12,5% breed moeten maken. Dat gaat grandioos mis. Die procenten moeten naar pixels worden vertaald, en daarbij worden enorme afrondingsfouten gemaakt door Google Chrome, Safari en Opera, wat soms wel 'n volle centimeter lege ruimte aan de rechterkant oplevert.

Daarom gebruik ik hele getallen, dat gaat wel goed.

Samen met de verplaatsing van 1 px naar links die gelijk hieronder wordt opgegeven, en met de marge links van de eerste <li>, die bij nav li:first-child wordt opgegeven, staat het menu horizontaal in het midden van de pagina.

margin-left: -1px;

Bij nav a wordt een witte border van 2 px aan de <a>'s in de <li>'s gegeven. Waar twee knoppen tegen elkaar aan staan, wordt die border 4 px breed. Dat is breder dan mooi is. Door elke <li> 1 px naar links te schuiven, worden de twee borders samen 3 px breed, omdat 1 px van de linkerborder van elke knop over de rechterborder van z'n buurvrouw komt te staan. Dat past beter bij de dikte van de rest van de border.

nav li:first-child

De <li> die het eerste kind is van <nav>. Er is hier maar één <nav>, waarbinnen het menu zit. Dit is het lijst-item waarbinnen 'Link een' zit.

margin-left: 2.5%;

Het complete menu is 100% breed. Maar elk van de acht <li>'s heeft bij nav li maar een breedte van 12% gekregen, samen 96%. Om de acht <li>'s horizontaal gecentreerd te krijgen, moet ik dus links een marge van 2% aanbrengen. Rechts van de laatste <li> blijft dan automatisch ook een marge van 2% over.

Maar bij nav li worden de <li>'s ook nog 1 px naar links geschoven, dus de totale breedte van de <li>'s is geen 96%, maar 96% min 8 px. Uitproberen levert op dat een marge van 2,5% links van de eerste <li> precies goed is: de acht knoppen staan nu horizontaal gecentreerd.

(Ja, inderdaad. Als je er 'n schuifmaat bij pakt, zie je dat ze niet in het midden staan. Tevreden met je ontdekking? Maakt dit je gelukkiger? Als dit je écht stoort, ben je misschien meer geschikt als praktiserend deelnemer aan het liefdesleven van een bepaald zespotig sociaal insect. Je kunt ook 'n goeie ram op je monitor geven, zodat de monitor iets smaller wordt. Staat het menu ook exact in het midden. Een schuifmaat kan trouwens lelijke krassen op de monitor opleveren.)

(Excuseer. Ik ben wat opgewonden geraakt van dat gedoe met afronden. 'n Verschil van 'n volle centimeter tussen browsers. Duurde even voor ik doorhad dat het afrondingsverschillen waren.)

nav a

De links binnen <nav>. Er is hier maar één <nav>, waarbinnen het menu zit. Dit zijn de links die bij dat menu horen.

background: black;

Hieronder wordt als achtergrond voor de knoppen van het menu een gradiënt, een verlopende kleur, gegeven. Die kleur verloopt van zwart via grijs naar donkergrijs. In Internet Explorer 8 kan dit alleen met een aparte afbeelding worden weergegeven. Daarom krijgt die browser gewoon een zwarte achtergrondkleur. De hier gelijk onderstaande linear-gradient kent Internet Explorer 8 niet, daarom negeert hij die hele tweede background gewoon. Browsers die linear-gradient wel kennen, gebruiken de background hieronder.

(Je zou voor Internet Explorer 8 een eigen methode van Microsoft kunnen gebruiken, zoals bij Speciaal voor Internet Explorer 7, 8 en 9 is gedaan bij div#onderaan, maar daarmee kun je maar twee kleuren aangeven, en dat zie je nauwelijks. In Internet Explorer 7 speelt dit niet, want dat ding is überhaupt te krakkemikkig om dit soort knoppen weer te geven. Internet Explorer 9 kent ook geen gradiënten, maar daarvoor wordt het verderop opgelost met behulp van SVG.)

background: -moz-linear-gradient(left, #000 0%, #595959 50%, #131313 100%); background: -ms-linear-gradient(left, #000 0%, #595959 50%, #131313 100%); background: -o-linear-gradient(left, #000 0%, #595959 50%, #131313 100%); background: -webkit-linear-gradient(left, #000 0%, #595959 50%, #131313 100%); background: linear-gradient(to right, #000 0%, #595959 50%, #131313 100%)

Als je goed kijkt, zie je dat hier in feite vijf keer vrijwel hetzelfde staat: background: linear-gradient (left, #000 0%, #595959 50%, #131313 100%). Alleen staat bij de vijfde keer geen left, maar to right. Waarom dit vijf keer wordt herhaald, staat bij De voorvoegsels -moz-, -ms-, -o- en -webkit-. Waarom er de vijfde keer to right staat, wordt hieronder verklaard.

Je kunt een gradiënt zelf uitvogelen, maar makkelijker is het om gebruik te maken van een gradiënt-editor. Ik heb gebruik gemaakt van de gradiënt-editor op colorzilla.com.

linear-gradient valt in een aantal delen uiteen.

left: de kant waar de gradiënt begint. Standaard is dat de bovenkant. Omdat de gradiënt hier van links naar rechts loopt, moet ik het opgeven.

Als vijfde en laatste staat hier de uiteindelijke vorm van linear-gradient, zonder voorvoegsel. Hier staat geen left, maar to right. De notatie voor de richting is nogal wat keren veranderd. Op 'n gegeven moment leek het erop dat het aangeven van de beginrichting (hier left) goed werkte. Waarop het in alle browsers is geïmplementeerd. Met een voorvoegsel, want het is nog experimenteel.

Vervolgens bleek in de praktijk dat dit niet goed werkte. In plaats van het vertrekpunt left bleek het beter het eindpunt van de gradiënt aan te geven: to right. Dat is de, zoals het er nu uitziet, definitieve syntax.

Zolang de variant met voorvoegsels wordt herkend door de browser, wordt de oude syntax gebruikt, inclusief de verouderde richtingsaanduiding. Zodra een browser de uiteindelijke syntax zonder voorvoegsel herkent, overrulet deze de oude syntax, omdat hij als vijfde en laatste in de css staat. Een aardige illustratie van het nut van voorvoegsels tijdens de experimentele fase: beide vormen van de syntax kunnen naast elkaar worden gebruikt.

Na de richting staan drie keer twee waardes, gescheiden door een komma. De eerste waarde is steeds de kleur, de tweede de plaats waar die kleur staat.

#000 0%: de kleur #000 (zwart) op 0% vanaf de linkerkant neerzetten (dat is helemaal links).

#595959 50%: de kleur #595959 (grijs) op 50% vanaf links neerzetten (dat is precies in het midden).

#131313 100%: de kleur #131313 (donkergrijs) op 100% vanaf links neerzetten (dat is helemaal rechts).

Er zijn drie plaatsen opgegeven die een bepaalde kleur moeten krijgen: links, midden en rechts. De overgang tussen die kleuren verloopt geleidelijk, dat regelt de browser verder. Dit is een hele simpele gradiënt, maar je kunt ook tig kleuren op tig plaatsen aangeven. En ook nog in allerlei richtingen.

color: white;

Voorgrondkleur wit, waardoor ook de tekst wit wordt. De achtergrond is vrijwel zwart, dus de normale zwarte tekst is hier wat minder handig.

border: white solid;

Witte rand rondom de links. De breedte geef ik gelijk hieronder op.

border-width: 2px 2px 0;

Kleur en stijl van de rand is gelijk hierboven al opgegeven.

Omdat voor links geen waarde is opgegeven, krijgt links automatisch dezelfde waarde als rechts. Hier staat dus eigenlijk 2px 2px 0 2px in de volgorde boven - rechts - onder - links. Aan alle kanten, behalve onder, een witte rand.

Deze manier van het opgeven van een border kost minder css, dan wanneer je drie aparte borders zou opgeven voor boven, rechts en links.

(Tussen twee knoppen in, waar 2 borders elkaar raken, is de border geen 4 px maar slechts 3 px breed, omdat bij nav li de <li>'s 1 px naar links worden gezet, zodat de borders iets over elkaar heen staan. Dat ziet er beter uit.)

border-radius: 25px 25px 0 0;

Links- en rechtsboven ronde hoeken, rechts- en linksonder gewoon rechte hoeken. Omdat er voor de ronde hoeken maar één maat is opgegeven, worden ze 25 px hoog en 25 px breed. Je kunt ook twee maten opgeven, dan krijg je ellipsvormige hoeken.

Anders dan de naam van deze eigenschap suggereert, krijgt ook de achtergrondkleur (en ook een eventuele achtergrond-afbeelding) ronde hoeken.

nav li:nth-last-child(2) a

De <a>'s binnen een <li> binnen <nav>. Maar niet elke <li>, het gaat om één bepaalde <li>: de <li> binnen <nav> die het tweede kind van <nav> is, van achteraf geteld. :nth-last-child wil simpelweg zeggen: van achteraf geteld. En de 2 staat voor: de tweede. (Je kunt ook ingewikkelder dingen met deze selector (eigenlijk een pseudo-class) doen, maar dat gebeurt hier niet.)

Zoals bij alle <li>'s, zit ook binnen dit lijst-item maar één <a>. Uiteindelijk geldt dit dus voor de tweede link van het menu, van achteraf geteld.

In dit geval is het belangrijk om exact deze selector te gebruiken. Bij nav li:nth-last-child(2) a heeft deze <a> een border aan de onderkant gekregen. Die moet hier worden weggehaald. Door exact dezelfde selector te gebruiken, weet je zeker dat het altijd om exact diezelfde <a> gaat, en niet om z'n buurmeisje omdat er 'n <a> is tussengevoegd of weggehaald.

border-bottom: none;

De bij nav li:nth-last-child(2) a aan de onderkant gegeven zwarte border moet weg, want die steekt hier aan de onderkant uit.

Bij nav a hierboven is de border al bij alle <a>' aan de onderkant weggehaald, maar dat werkt niet bij deze <a>. De border bij deze <a> is aangebracht met een selector waarin drie elementen staan: nav, li en a. Bovendien staat er nog de pseudo-class nth-last-child(2) in.

Om de border weg te halen, moet de selector minstens evenveel gewicht, evenveel specificiteit hebben. Alleen nav a heeft dat niet, want daar zitten alleen maar twee elementen in. Eén te weinig en de pseudo-class mist ook.

Daarom moet voor deze <a> de border aan de onderkant apart worden weggehaald met een selector die evenveel specificiteit (of meer) heeft, als waar de border mee is aangebracht. Deze selector heeft precies evenveel specificiteit, en omdat hij later in de css staat, overrulet hij de eerdere selector.

css voor vensters breder dan 810 px

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

De css die hier tot nu toe staat, geldt ook voor browserfvensters breder dan 810 px. Elk venster dat minimaal 600 px breed is, is immers ook 810 px breed. De css die hieronder staat, geldt alleen voor browservensters breder dan 810 px. Voor een deel is dit nieuwe css, voor een deel wordt hierboven staande css aangepast.

De opbouw van de regel staat beschreven bij @media screen and (min-width 600px), het enige verschil is dat het hier om een minimumbreedte van 810 px gaat.

.no-touch header

De <header>'s binnen een element met class="no-touch". Er is hier maar één <header>, het vlak met de gele achtergrond.

Als je in de broncode kijkt, zul je de class "no-touch" niet vinden. Deze class wordt door het JavaScript modernizr toegevoegd aan <html> bij browsers, die touch events niet herkennen. In principe werkt deze regel daardoor alleen in browsers, die touch events niet herkennen. Dat zijn (meestal) mobiele browsers.

Hoe dat precies werkt, staat bij Touchscreens herkennen met behulp van modernizr.

Om <html class="no-touch"> te kunnen zien in de broncode, moet je de gegenereerde code bekijken. In Firefox kan dat met behulp van bijvoorbeeld de extensies Firebug of Web Developer onder View Source → View Generated Source. Of met het in Firefox ingebouwde 'Element inspecteren'. Andere browsers hebben andere manieren om gegenereerde code te bekijken.

Doordat div#wrapper hieronder bij .no-touch #wrapper absoluut wordt gepositioneerd, scrollen tekst en foto's binnen die div. Daardoor blijft de header, ook bij scrollen, bovenaan het venster van de browser staan. Mobiele browsers hebben vaak moeite met dit soort constructies. Omdat mobiele browsers meestal touch events herkennen, missen die de class "no-touch" in <html> en negeren deze regel dus.

height: 7em;

Hoogte. Omdat deze css voor bredere vensters is, is er wat meer ruimte voor een iets hogere header dan misschien strikt nodig is. Als eenheid wordt em gebruikt, zodat bij een andere lettergrootte de verhoudingen zo goed mogelijk intact blijven.

overflow: auto;

Als de letters heel sterk worden vergroot, kan de tekst beneden de header komen te staan, over de rest van de pagina heen. Dit voorkomt dat. Als de tekst nu niet in de header past, verschijnt naast de header een verticale scrollbalk.

Dit werkt alleen maar, als het element een hoogte heeft, zoals hier het geval is.

border-bottom: black solid 1px;

Zwart randje aan de onderkant.

position: relative;

De header heeft een z-index nodig, omdat je anders het zwarte randje aan de onderkant niet overal ziet. Een z-index kan alleen worden gegeven aan een element dat absoluut, relatief of fixed is gepositioneerd. Omdat ik hier verder niets bij opgeef, heeft dit verder geen enkele invloed op <header>.

z-index: 10;

<header> is 7 em hoog. div#wrapper wordt hieronder absoluut gepositioneerd op 7 em van de bovenkant, dus sluit precies aan op <header>. Maar <header> heeft nog een border van 1 px aan de onderkant. Die komt nog bij die 7 em. Daardoor staat div#wrapper precies over die zwarte border heen.

Door <header> een hogere z-index te geven, komt hij boven div#wrapper te staan, en de zwarte border aan de onderkant dus ook. Een z-index van 1 zou ook al genoeg zijn, maar de afdeling Schade en Schande heeft geleerd dat het goed is om openingen in de volgorde van de z-index te houden, zodat je er later nog 'n z-index tussen kunt stoppen.

(Ooit honderden z-indexen aangebracht. Netjes op volgorde. En toen moest er helemaal aan het begin eentje tussen. Dat doe je maar één keer...)

Een z-index kan alleen worden gebruikt als het element relatief, absoluut of fixed is gepositioneerd. Gelijk hierboven is het relatief gepositioneerd, dus dat is geregeld.

.no-touch #wrapper

Het element met id="wrapper" binnen een element met class="no-touch". Dit is een div, waarbinnen tekst, afbeeldingen en menu staan. Deze div vult de ruimte tussen <header> en <footer>.

Als je in de broncode kijkt, zul je de class "no-touch" niet vinden. Deze class wordt door het JavaScript modernizr toegevoegd aan <html> bij browsers, die touch events niet herkennen. In principe werkt deze regel daardoor alleen in browsers, die touch events niet herkennen. Dat zijn (meestal) mobiele browsers.

Hoe dit verder precies werkt, staat bij Touchscreens herkennen met behulp van modernizr.

Om <html class="no-touch"> te kunnen zien in de broncode, moet je de gegenereerde code bekijken. In Firefox kan dat met behulp van bijvoorbeeld de extensies Firebug of Web Developer onder View Source → View Generated Source. Of met het in Firefox ingebouwde 'Element inspecteren'. Andere browsers hebben andere manieren om gegenereerde code te bekijken.

Omdat div#wrapper hieronder absoluut wordt gepositioneerd, scrollen tekst en foto's binnen die div. Daardoor blijven header, menu en footer altijd op dezelfde plaats staan. Mobiele browsers hebben vaak moeite met dit soort constructies. Omdat mobiele browsers meestal touch events herkennen, missen die de class "no-touch" in <html> en negeren deze regel dus.

width: 100%;

div#wrapper is een blok-element en zou automatisch dezelfde breedte als z'n ouder moeten krijgen. Dat is <body>, dus de div zou even breed als de pagina moeten worden. Dat is ook zo, maar niet in Internet Explorer 9.

In Internet Explorer 9 wordt de pagina ongeveer drie keer zo breed als het venster van de browser. Pardon? Om het spannend te maken wordt hij, ogenschijnlijk willekeurig, af en toe ook wel 'ns veel smaller dan het venster. De oorzaak kan ik niet vinden, want zodra de debugger aan staat, voelt de bug kennelijk nattigheid en verstopt zich, waardoor de pagina correct wordt weergegeven. Maar alleen met de debugger aan dus.

Door een breedte op te geven, verdwijnt deze bug. Omdat dit de normale situatie is, hebben andere browsers hier verder geen last van.

position: absolute;

Door div#wrapper absoluut te positioneren tussen de header en de footer, wordt hij op een bepaalde plaats op het scherm gezet. Vervolgens worden binnen div#wrapper de tekst en de afbeeldingen binnen <article> gezet. (<article> is eigenlijk 'n gewone div, maar dan met semantische betekenis.)

Door <article> even hoog te maken als div#wrapper en overflow op auto te zetten bij <article>, krijgt <article> bij voldoende content een verticale scrollbalk. Als je gaat scrollen, scrol je alleen de inhoud van <article>. div#wrapper blijft op z'n plaats staan. Hierdoor blijven ook header, footer en menu op hun plaats staan: alleen de tekst en de foto's scrollen.

top: 7em;

<header>, dat gelijk boven div#wrapper staat, is 7 em hoog. Daarom moet div#wrapper op 7 em vanaf de bovenkant beginnen om goed op <header> aan te sluiten.

bottom: 5em;

<footer>, dat gelijk onder div#wrapper staat, is 5 em hoog. Daarom moet div#wrapper tot 5 em vanaf de onderkant doorlopen om goed op <footer> aan te sluiten.

.no-touch article

De <article>'s binnen een element met class="no-touch". Er is hier maar één <article>. De tekst en de afbeeldingen staan erin.

Als je in de broncode kijkt, zul je de class "no-touch" niet vinden. Deze class wordt door het JavaScript modernizr toegevoegd aan <html> bij browsers, die touch events niet herkennen. In principe werkt deze regel daardoor alleen in browsers, die touch events niet herkennen. Dat zijn (meestal) mobiele browsers.

Hoe dit verder precies werkt, staat bij Touchscreens herkennen met behulp van modernizr.

Om <html class="no-touch"> te kunnen zien in de broncode, moet je de gegenereerde code bekijken. In Firefox kan dat met behulp van bijvoorbeeld de extensies Firebug of Web Developer onder View Source → View Generated Source. Of met het in Firefox ingebouwde 'Element inspecteren'. Andere browsers hebben andere manieren om gegenereerde code te bekijken.

Bij .no-touch #wrapper is div#wrapper absoluut gepositioneerd, wat de mogelijkheid geeft om alleen tekst en foto's te scrollen, terwijl header, menu en footer altijd op dezelfde plaats blijven staan. Mobiele browsers hebben vaak moeite met dit soort constructies. Omdat mobiele browsers meestal touch events herkennen, missen die de class "no-touch" in <html>.

Daardoor wordt door die browsers deze regel genegeerd, en dat is precies de bedoeling. Als div#wrapper niet absoluut is gepositioneerd, is deze regel ook niet nodig.

width: 80%;

Een breedte in procenten wordt altijd genomen ten opzichte van de ouder van het element. Dat is hier div#wrapper, dat de volle breedte van de pagina heeft: 100%. Door <article> een vijfde smaller te maken, komt er ruimte vrij om het menu naast <article> met de daarin zittende tekst en afbeeldingen te kunnen zetten.

height: 100%;
Afbeelding 17
Afbeelding 17: zonder hoogte bij <article> verschijnt er geen scrollbalk naast <article>. De blauwe scrollbalk hoort bij de pagina, bij <body>. Hierdoor scrollen ook header, menu en footer mee. Een deel van de content wordt hierdoor onzichtbaar, omdat de footer eroverheen staat.

In dit voorbeeld staan behoorlijk wat tekst en afbeeldingen binnen <article>. Normaal genomen zijn die altijd zichtbaar, ook als ze niet binnen het element passen. Normaal genomen is dat ook prima. Het is meestal beter dat de lay-out misschien wat wordt verstoord, dan dat er tekst en dergelijke gewoon verdwijnt.

Hier is dit echter niet de bedoeling. Als de tekst en dergelijke niet in het venster van de browser past, moet er rechts van <article> een scrollbalk verschijnen. Om dat voor elkaar te krijgen, moet een hoogte worden opgegeven.

Als je geen hoogte aan <article> geeft, gebeurt er wat op de afbeelding is te zien. Omdat niet alles in het venster past, verschijnt er netjes een verticale scrollbalk. Maar dat is geen scrollbalk bij <article>, het is de standaardscrollbalk die verschijnt als niet alles in het venster past. Een scrollbalk die bij de pagina, bij <body> hoort.

Omdat niet alleen <article>, maar de hele <body> scrolt, scrollen ook <header>, <nav> en <footer> mee. Vooral het meescrollen van <footer> is rampzalig.

Door aan <article> een hoogte te geven, is duidelijk dat <article> een scrollbalk moet krijgen, en niet de hele pagina.

Een hoogte in procenten wordt altijd genomen ten opzichte van de ouder, hier div#wrapper, die tussen <header> en <footer> staat. Als <article> even hoog wordt als div#wrapper, komt <article> daardoor ook tussen <header> en <footer> te staan. En daarmee een eventuele scrollbalk naast <article> ook.

Om de scrollbalk te laten verschijnen, moet ook de eigenschap overflow nog worden gebruikt, wat gelijk hieronder gebeurt.

overflow: auto;

Samen met de gelijk hierboven opgegeven hoogte zorgt deze eigenschap voor het verschijnen van een verticale scrollbalk naast <article>, als er zoveel tekst en dergelijke binnen <article> staat, dat dit niet in één keer zichtbaar is.

Standaard staat overflow op visible: als de content niet allemaal binnen het element past, laat het dan toch zien. Dat is normaal genomen beter dan dat het verdwijnt. Door overflow op auto te zetten, verschijnt een scrollbalk, maar alleen als dat nodig is, als er genoeg tekst en dergelijke aanwezig is.

Hiervoor is ook nog een hoogte nodig, want anders weet de browser niet hoe hoog het element is en wanneer er een scrollbalk moet verschijnen.

margin-left: 20%;

Normaal genomen wordt een element gewoon links in de ouder, hier div#wrapper, neergezet. Hiermee wordt de linkerkant van <article> 20% naar links geschoven, waardoor aan de linkerkant ruimte vrijkomt voor het menu.

Door als eenheid voor de vrije ruimte procenten te nemen, past de breedte zich aan de breedte van het venster van de browser aan, waardoor de verhoudingen beter intact blijven.

De <nav> waarin het menu staat wordt maar 18% breed. Maar door de padding en border die daar nog bij komen, sluiten <nav> en <article> toch goed op elkaar aan.

(Feitelijk staat <article> 'n heel klein fiebeltje achter <nav>, omdat procenten en px nou eenmaal moeilijk optellen. Maar daar zie je niets van. En bij 'n site geldt, anders dan bij religie: wat je niet ziet, bestaat niet. Dat optellen van verschillende soorten eenheden gaat in css3 ook ingrijpend verbeteren met behulp van calc(), maar op dit moment wordt dat nog onvoldoende ondersteund door de verschillende browsers.)

padding-top: 0;

Bij article is bovenaan een padding van 2,2 em gegeven om ruimte te maken voor het menu, dat in smallere vensters bovenaan komt te staan. Hier wordt het menu links neergezet en is die padding dus niet nodig.

#tekst

Het element met id="tekst". Binnen <article> staan twee belangrijke divs: div#tekst, waarin de tekst staat, en div#foto, waar verrassenderwijs de foto's in blijken te staan.

Door de opdeling in twee divs kunnen de foto's, als het venster breed genoeg is, hierdoor naast de tekst komen te staan.

width: 73%;

Een breedte in procenten wordt altijd genomen ten opzichte van de ouder, dat is hier <article>. Voor de tekst wordt driekwart van de breedte van <article> gereserveerd, waardoor er aan de rechterkant van de tekst 'n kwart overblijft om foto's in te zetten.

De hier opgegeven breedte is slechts 73%, maar bij #tekst is een padding rechts en links opgegeven van 1%. Samen maakt dat 75%.

Binnen elke <figure> staat één foto met onderschrift. <figure> heeft bij figure een breedte van 25% gekregen, waardoor er precies één kolom met foto's naast de tekst past.

float: left;

Normaal genomen worden blok-elementen op een nieuwe regel gezet. Dit geldt ook voor de blok-elementen, waar de foto's in staan. Door div#tekst naar links te floaten, gebeurt dat niet. Als er rechts van div#tekst genoeg ruimte is, wordt die nu opgevuld. In dit geval met de foto's en de bijbehorende tekst.

#foto h2

De <h2>'s in het element met id="foto". Dat is hier maar één kopje met de tekst 'Foto's'.

Een <h2> is een blok-element en zou normaal genomen op een nieuwe regel onder de tekst komen te staan. Maar de tekst in div#tekst is naar links gefloat, en daardoor komt de <h2> rechts naast de tekst te staan.

margin-top: 2%;

Kleine afstand tussen kopje en bovenkant van de kolom met foto's. Met deze marge komt het kopje gelijk te staan met de kopjes boven menu en tekst. Er is geen speciale reden om procent te gebruiken als eenheid, ik had ook em kunnen gebruiken.

Als het maar 'n relatieve eenheid is die mee verandert met de lettergrootte. Bij een absolute eenheid als px worden de verhoudingen in Safari en Internet Explorer verstoord bij een andere lettergrootte.

#foto p

De paragrafen binnen het element met id="foto". Dat is er hier maar eentje. De tekst boven de foto's staat erin.

width: 24%;

Er is ruimte voor een breedte van 25%, omdat de tekst 75% breed is. Door de <p> iets smaller te maken, krijg ik links en rechts ruimte voor een kleine marge.

float: left;

Zover mogelijk omhoog en dan zover mogelijk naar links zetten.

Ook zonder float zou de tekst in deze paragraaf rechts van de tekst met de oranje achtergrond komen te staan, omdat div#tekst, waarin de tekst met de oranje achtergrond zit, naar links is gefloat.

Maar de tekst uit deze <p> beslaat dan gewoon de volle breedte van de lege ruimte boven de foto's, en dat is te breed. De tekst uit deze <p> kan dan helemaal tegen de tekst met de oranje achtergrond komen te staan, of tegen de rechterkant van het venster. Daarom geef ik deze paragraaf hieronder een breedte, die iets minder is dan de breedte van de foto's. Hierdoor komt er ruimte voor een marge links en rechts.

Als ik dat doe, moet ik echter ook deze <p> floaten, omdat hij anders onder div#tekst met de tekst op de oranje achtergrond komt te staan.

Waarom een marge wordt gebruikt en geen simpele padding, wordt bij de hieronder staande eigenschappen van #foto p toegelicht.

margin: 0 0.5%;

Omdat voor onder en links geen waarde is opgegeven, krijgen die automatisch dezelfde waarde als boven en rechts. Hier staat dus eigenlijk 0 0.5% 0 0.5% in de volgorde boven - rechts - onder - links.

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

Links en rechts een kleine marge van 0,5%, zodat er wat ruimte links en rechts van de tekst komt.

padding: 0;

Bij #foto p is links en rechts een padding opgegeven. Die is nu overbodig, omdat al wat ruimte links en rechts is gekregen met behulp van de hierboven opgegeven marge.

Je zou denken dat ik dan, in plaats van al dat ingewikkelde gedoe hierboven met 'n marge, beter een padding aan de tekst had kunnen geven. Dat is ook zo. Alleen werkt dat niet. Door al het gefloat krijg je bij gebruik van een padding alleen rechts een padding, links niet. Dus links kan de tekst uit de <p> dan nog steeds tegen de tekst met de oranje achtergrond komen te staan.

.no-touch nav

De <nav>'s binnen een element met class="no-touch". Er is hier maar één <nav>, waarin het menu staat.

Als je in de broncode kijkt, zul je de class "no-touch" niet vinden. Deze class wordt door het JavaScript modernizr toegevoegd aan <html> bij browsers, die touch events niet herkennen. In principe werkt deze regel daardoor alleen in browsers, die touch events niet herkennen. Dat zijn (meestal) mobiele browsers.

Hoe dit verder precies werkt, staat bij Touchscreens herkennen met behulp van modernizr.

Om <html class="no-touch"> te kunnen zien in de broncode, moet je de gegenereerde code bekijken. In Firefox kan dat met behulp van bijvoorbeeld de extensies Firebug of Web Developer onder View Source → View Generated Source. Of met het in Firefox ingebouwde 'Element inspecteren'. Andere browsers hebben andere manieren om gegenereerde code te bekijken.

Bij .no-touch #wrapper is div#wrapper absoluut gepositioneerd, wat de mogelijkheid geeft om alleen tekst en foto's te scrollen, terwijl header, menu en footer altijd op dezelfde plaats blijven staan. Mobiele browsers hebben vaak moeite met dit soort constructies. Omdat mobiele browsers meestal touch events herkennen, missen die de class "no-touch" in <html>.

Daardoor wordt door die browsers deze regel genegeerd, en dat is precies de bedoeling. Als div#wrapper niet absoluut is gepositioneerd, hoeft ook <nav> niet links in het venster te worden gezet.

width: 18%;

18% breed maken. <nav> met het menu komt links van <article> te staan. Bij .no-touch article is hiervoor aan de linkerkant van <article> 20% ruimte vrijgemaakt. Dat is 2% meer dan <nav> breed is, maar bij die 18% komen nog de padding en de border die hieronder worden opgegeven.

De totale breedte van <nav> is dan ongeveer 20%. <article> staat in werkelijkheid 'n heel klein stukje onder <nav>, maar daar zie je niets van.

overflow: auto;

<nav> is absoluut gepositioneerd bij nav. De bovenkant is daar ook met top: 0; gelijk gezet met de bovenkant van div#wrapper, de ouder van <nav>. Hieronder wordt de onderkant met bottom: 0; gelijk gezet met de onderkant van div#wrapper.

Hierdoor heeft <nav> feitelijk een hoogte gekregen, ook al is die niet expliciet opgegeven, omdat boven- en onderkant bekend zijn.

Als de lettergrootte heel groot wordt, zou de tekst mogelijk niet meer in <nav> passen. Normaal genomen zou die dan toch zichtbaar worden, omdat overflow standaard op visible staat. Door overflow op auto te zetten ontstaat een verticale scrollbalk naast <nav>, maar alleen als dat nodig is, als de inhoud niet meer in <nav> past. Zo wordt voorkomen dat het menu een deel van <footer> onder het menu zou kunnen bedekken.

font-size: 1em;

Bij nav is de lettergrootte 0,7 em gemaakt. Dat is vrij klein en leuk voor kleine browservensters, maar hier is meer ruimte, dus kan de lettergrootte weer worden verhoogd.

Als eenheid neem ik em, zodat ook gebruikers van Internet Explorer de lettergrootte kunnen veranderen.

border-right: black solid 1px;

Lijntje rechts van het menu.

padding: 1.5% 1.1% 1% 1%;

Aan alle kanten wat padding, zodat er wat ruimte is tussen het menu in <nav> en de buitenkant van <nav>. Als eenheid is procent genomen, zodat de verhoudingen bij verschillende breedtes intact blijven.

De padding van 1,1% aan de rechterkant lijkt wat vreemd, en is dat eigenlijk ook. Door afrondingsverschillen bij het omrekenen van procenten naar pixels, ontstaat in Safari en Google Chrome op Linux en Windows een kleine kier tussen <nav> en <article>. Door de padding 0,1% hoger te nemen, verdwijnt die kier. Andere browsers hebben er geen last van.

bottom: 0;

Onderkant gelijk zetten met de onderkant van z'n ouder: div#wrapper. Hierdoor loopt ook de bij nav opgegeven groene achtergrondkleur door tot aan de onderkant van div#wrapper, gelijk boven <footer>.

.no-touch nav h2

De <h2>'s binnen een <nav>, die weer binnen een element met class="no-touch" zit. Er is hier maar één <nav>, waarin maar één <h2> zit: het kopje met 'Menu'.

Als je in de broncode kijkt, zul je de class "no-touch" niet vinden. Deze class wordt door het JavaScript modernizr toegevoegd aan <html> bij browsers, die touch events niet herkennen. In principe werkt deze regel daardoor alleen in browsers, die touch events niet herkennen. Dat zijn (meestal) mobiele browsers.

Hoe dit verder precies werkt, staat bij Touchscreens herkennen met behulp van modernizr.

Om <html class="no-touch"> te kunnen zien in de broncode, moet je de gegenereerde code bekijken. In Firefox kan dat met behulp van bijvoorbeeld de extensies Firebug of Web Developer onder View Source → View Generated Source. Of met het in Firefox ingebouwde 'Element inspecteren'. Andere browsers hebben andere manieren om gegenereerde code te bekijken.

Bij .no-touch #wrapper is div#wrapper absoluut gepositioneerd, wat de mogelijkheid geeft om alleen tekst en foto's te scrollen, terwijl header, menu en footer altijd op dezelfde plaats blijven staan. Mobiele browsers hebben vaak moeite met dit soort constructies. Omdat mobiele browsers meestal touch events herkennen, missen die de class "no-touch" in <html>.

Daardoor wordt door die browsers deze regel genegeerd, en dat is precies de bedoeling. Als het menu niet links wordt gepositioneerd, is deze <h2> ook niet nodig.

display: block;

Bij nav h2 is dit kopje verborgen. Als <nav> met het menu links wordt gepositioneerd, is het kopje weer welkom.

De rest van de opmaak is al opgegeven bij nav h2.

.no-touch nav li

De <li>'s binnen een <nav>, die weer binnen een element met class="no-touch" zit. Er is hier maar één <nav>, waarin de <li>'s met de links van het menu zitten.

Als je in de broncode kijkt, zul je de class "no-touch" niet vinden. Deze class wordt door het JavaScript modernizr toegevoegd aan <html> bij browsers, die touch events niet herkennen. In principe werkt deze regel daardoor alleen in browsers, die touch events niet herkennen. Dat zijn (meestal) mobiele browsers.

Hoe dit verder precies werkt, staat bij Touchscreens herkennen met behulp van modernizr.

Om <html class="no-touch"> te kunnen zien in de broncode, moet je de gegenereerde code bekijken. In Firefox kan dat met behulp van bijvoorbeeld de extensies Firebug of Web Developer onder View Source → View Generated Source. Of met het in Firefox ingebouwde 'Element inspecteren'. Andere browsers hebben andere manieren om gegenereerde code te bekijken.

Bij .no-touch #wrapper is div#wrapper absoluut gepositioneerd, wat de mogelijkheid geeft om alleen tekst en foto's te scrollen, terwijl header, menu en footer altijd op dezelfde plaats blijven staan. Mobiele browsers hebben vaak moeite met dit soort constructies. Omdat mobiele browsers meestal touch events herkennen, missen die de class "no-touch" in <html>.

Daardoor wordt door die browsers deze regel genegeerd, en dat is precies de bedoeling. Deze regel zorgt ervoor dat de links in het menu onder elkaar komen te staan, wat alleen nodig is als <nav> links wordt gepositioneerd.

width: 100%; Afbeelding 18: knoppen in menu te smal

Een <li> is een blok-element. Normaal genomen wordt dat automatisch even breed als z'n ouder, hier <nav> (te herkennen aan de groene achtergrond). Maar bij nav li is een breedte van 12% opgegeven, Een breedte wordt altijd genomen ten opzichte van de ouder. Dat levert het resultaat op dat op de afbeelding hiernaast is te zien. Niet helemaal wat ik in gedachten had.

Daarom wordt hier handmatig opgegeven dat het blok-element de volle breedte moet krijgen. Ik had ook auto, de standaardinstelling, kunnen gebruiken hier, dat heeft in dit geval hetzelfde effect.

De <li>'s, en dus de grijze achtergrond, worden nog steeds iets smaller dan de groene <nav>, omdat de <nav> bij .no-touch nav links en rechts een padding heeft gekregen. Omdat die padding links en rechts even groot is en de <li>'s de volle ruimte ertussen vullen, worden de <li>'s gelijk horizontaal gecentreerd.

float: none;

Een <li> is een blok-element. Normaal genomen komt dat op een nieuwe regel te staan. Daardoor zouden de links onder elkaar en niet naast elkaar komen te staan.

Bij nav li is float: left; opgegeven, zodat de <li>'s en de links daarin naast elkaar komen te staan. Door dat hier op te heffen, komen de <li>'s weer gewoon onder elkaar te staan.

margin: 0;

Bij nav li en nav li:first-child hebben de <li>'s een marge aan de linkerkant gekregen. Hier moet die weer weg, omdat ze anders niet netjes uitgelijnd onder elkaar en niet goed horizontaal gecentreerd staan.

.no-touch nav a

De <a>'s binnen een <nav>, die weer binnen een element met class="no-touch" zit. Er is hier maar één <nav>, waarbinnen de links van het menu zitten.

Als je in de broncode kijkt, zul je de class "no-touch" niet vinden. Deze class wordt door het JavaScript modernizr toegevoegd aan <html> bij browsers, die touch events niet herkennen. In principe werkt deze regel daardoor alleen in browsers, die touch events niet herkennen. Dat zijn (meestal) mobiele browsers.

Hoe dit verder precies werkt, staat bij Touchscreens herkennen met behulp van modernizr.

Om <html class="no-touch"> te kunnen zien in de broncode, moet je de gegenereerde code bekijken. In Firefox kan dat met behulp van bijvoorbeeld de extensies Firebug of Web Developer onder View Source → View Generated Source. Of met het in Firefox ingebouwde 'Element inspecteren'. Andere browsers hebben andere manieren om gegenereerde code te bekijken.

Bij .no-touch #wrapper is div#wrapper absoluut gepositioneerd, wat de mogelijkheid geeft om alleen tekst en foto's te scrollen, terwijl header, menu en footer altijd op dezelfde plaats blijven staan. Mobiele browsers hebben vaak moeite met dit soort constructies. Omdat mobiele browsers meestal touch events herkennen, missen die de class "no-touch" in <html>.

Daardoor wordt door die browsers deze regel genegeerd, en dat is precies de bedoeling. De css in deze regel is alleen bedoeld voor een menu, waarin de links niet naast elkaar, maar onder elkaar staan.

background: #ccc;

Grijze achtergrondkleur.

color: black;

Voorgrondkleur zwart, waardoor ook de tekst zwart wordt. Bij nav a is de voorgrondkleur wit gemaakt, maar op een grijze achtergrond is dat veel te onduidelijk.

height: 2.2em;

Hoogte. Door de hoogte aan de <a> te geven en niet aan de <li>, wordt de hele <a> gevoelig voor hoveren en klikken, en niet alleen de tekst erbinnen.

Een <a> is een inline-element, en hoogte en dergelijke kan alleen aan een blok-element worden gegeven. Bij nav a is de <a> veranderd in een blok-element, dus dat is al geregeld.

Op diezelfde plaats is ook een hoogte van 1,2 cm opgegeven. Die wordt hier veranderd in een iets lagere relatieve maat. Iets kleiner kan, omdat dit menu niet met de vinger wordt bediend. Door de relatieve eenheid em te gebruiken, wordt de hoogte van de knoppen gekoppeld aan de lettergrootte.

line-height: 2.2em;

Tekst wordt automatisch halverwege de regelhoogte neergezet. Door de regelhoogte even hoog als de gewone hoogte te maken, wordt de tekst verticaal gecentreerd.

Door de relatieve eenheid em te gebruiken, wordt de grootte van de letters gekoppeld aan de hoogte van de knoppen.

border: black solid;

Zwart randje. De breedte geef ik gelijk hieronder op.

border-width: 0 1px 1px;

Gelijk hierboven zijn kleur en stijl al opgegeven.

Omdat voor links geen waarde is opgegeven, krijgt dat automatisch dezelfde waarde als rechts. Hier staat dus eigenlijk 0 1px 1px 1px in de volgorde boven - rechts - onder - links. Aan alle kanten een lijntje, behalve aan de bovenkant.

Afbeelding 19: dubbele border tussen knoppen menu

Als ook aan de bovenkant een border zou komen, zou er tussen twee knoppen een dubbele lijn komen te staan, omdat de lijnen aan boven- en onderkant tegen elkaar aan komen te staan. Dit is op de afbeelding hiernaast te zien. Door de lijn aan de bovenkant weg te laten, voorkom je dat. Nu mist wel een lijn aan de bovenkant van de bovenste knop, maar dat wordt later opgelost.

border-radius: 0;

Bij nav a hebben de <a>'s ronde hoeken gekregen. Dat moet hier ook gebeuren, maar de daar opgegeven hoeken horen bij een horizontale menubalk met de knoppen naast elkaar. Daar kregen álle knoppen ronde hoeken, hier moeten alleen de bovenste en de onderste knop ronde hoeken krijgen.

Om te beginnen alle ronde hoeken weghalen. Dan zijn de binnenste knoppen al klaar, want die blijven gewoon rechthoekig. Voor de bovenste en onderste breng ik later de ronde hoeken weer aan, maar dan de juiste.

.no-touch nav a:focus, .no-touch nav a:hover

Waarom :focus en :hover zijn gebruikt, is te vinden bij Alleen :hover of :hover, :focus en :active?.

De <a>'s binnen een <nav>, die weer binnen een element met class="no-touch" zit. Maar alleen als de <a>'s focus hebben of als erover wordt gehoverd. Er is hier maar één <nav>, waarbinnen de links van het menu zitten.

Als je in de broncode kijkt, zul je de class "no-touch" niet vinden. Deze class wordt door het JavaScript modernizr toegevoegd aan <html> bij browsers, die touch events niet herkennen. In principe werkt deze regel daardoor alleen in browsers, die touch events niet herkennen. Dat zijn (meestal) mobiele browsers.

Hoe dit verder precies werkt, staat bij Touchscreens herkennen met behulp van modernizr.

Om <html class="no-touch"> te kunnen zien in de broncode, moet je de gegenereerde code bekijken. In Firefox kan dat met behulp van bijvoorbeeld de extensies Firebug of Web Developer onder View Source → View Generated Source. Of met het in Firefox ingebouwde 'Element inspecteren'. Andere browsers hebben andere manieren om gegenereerde code te bekijken.

Bij .no-touch #wrapper is div#wrapper absoluut gepositioneerd, wat de mogelijkheid geeft om alleen tekst en foto's te scrollen, terwijl header, menu en footer altijd op dezelfde plaats blijven staan. Mobiele browsers hebben vaak moeite met dit soort constructies. Omdat mobiele browsers meestal touch events herkennen, missen die de class "no-touch" in <html>.

Daardoor wordt door die browsers deze regel genegeerd, en dat is precies de bedoeling. :focus en :hover werken in vrijwel geen enkele mobiele browser goed, dus hoeven ze deze css niet te krijgen.

Het wordt hier gebruikt om de knoppen te laten verkleuren. Bij veel mobiele browsers zorgt het verkleuren van de knoppen alleen maar voor verwarring, omdat ze in die browsers alleen verkleurd zijn, als je met de back-knop van de browser teruggaat.

background: black;

Achtergrond zwart maken.

color: white;

Voorgrondkleur wit maken, waardoor ook de tekst wit wordt.

outline: transparent solid 0;

Een link die focus heeft, krijgt normaal genomen een outline. Daardoor weten mensen die de Tab-toets gebruiken om van link naar link te gaan, welke link focus heeft en gevolgd wordt als op Enter wordt gedrukt. Dat is hier niet nodig, omdat een link die focus heeft al verkleurt. Een outline is in dit geval foeilelijk.

De outline wordt hier weggehaald. Normaal genomen zou je dat doen met 'n simpel outline: 0;, maar Opera is kennelijk zo gehecht aan z'n foeilelijke knalblauwe weerzinwekkend dikke outline, dat alleen deze volledige regel Opera ertoe kan bewegen z'n outline niet te tonen.

.no-touch nav li:first-child a

De <a>'s binnen een <nav>, die weer binnen een element met class="no-touch" zit. Maar alleen als de <li> het eerste kind van de <nav> is. Er is hier maar één <nav>, waarin het menu zit. Binnen de eerste <li> zit de <a>, waarin 'Link een' staat. (Ja, ik heb een groots talent voor het bedenken van originele namen, al zeg ik het zelf.)

Als je in de broncode kijkt, zul je de class "no-touch" niet vinden. Deze class wordt door het JavaScript modernizr toegevoegd aan <html> bij browsers, die touch events niet herkennen. In principe werkt deze regel daardoor alleen in browsers, die touch events niet herkennen. Dat zijn (meestal) mobiele browsers.

Hoe dit verder precies werkt, staat bij Touchscreens herkennen met behulp van modernizr.

Om <html class="no-touch"> te kunnen zien in de broncode, moet je de gegenereerde code bekijken. In Firefox kan dat met behulp van bijvoorbeeld de extensies Firebug of Web Developer onder View Source → View Generated Source. Of met het in Firefox ingebouwde 'Element inspecteren'. Andere browsers hebben andere manieren om gegenereerde code te bekijken.

Bij .no-touch #wrapper is div#wrapper absoluut gepositioneerd, wat de mogelijkheid geeft om alleen tekst en foto's te scrollen, terwijl header, menu en footer altijd op dezelfde plaats blijven staan. Mobiele browsers hebben vaak moeite met dit soort constructies. Omdat mobiele browsers meestal touch events herkennen, missen die de class "no-touch" in <html>.

Daardoor wordt door die browsers deze regel genegeerd, en dat is precies de bedoeling. De ronde hoeken die hier worden gegeven, moeten alleen worden aangebracht als <nav> links van de tekst wordt gepositioneerd.

border-radius: 10px 10px 0 0;

Links- en rechtsboven ronde hoek, rechts- en linksonder niet.

Omdat maar één maat is opgegeven, worden de ronde hoeken even hoog als breed. (Je kunt ook twee maten opgeven, dan krijg je 'n ellipsvormige hoek.)

In tegenstelling tot wat de naam van deze eigenschap suggereert, krijgen ook achtergrondkleur en een eventuele achtergrond-afbeelding ronde hoeken.

border: black solid 1px;

Bij .no-touch nav a hebben alle <a>'s een zwarte border gekregen, maar niet aan de bovenkant. Bij de bovenste knop zie je dat, omdat daar de horizontale border aan de bovenkant ontbreekt. Die wordt hier alsnog gegeven. Omdat er aan vier kanten een border moet komen, kan ik gewoon border gebruiken, maar border-top zou hier ook genoeg zijn.

.no-touch nav li:nth-last-child(2) a

Deze selector geldt alleen voor de links binnen één specifieke <li> binnen <nav>. Het gaat om de tweede <li> binnen <nav>, van achteraf geteld. :nth-last-child wil simpelweg zeggen: van achteraf geteld. En de 2 staat voor: de tweede. (Je kunt ook ingewikkelder dingen met deze selector (eigenlijk een pseudo-class) doen, maar dat gebeurt hier niet.)

Het geheel moet binnen een element met class="no-touch" zitten.

In dit geval is het beter om de links vanaf de achterkant te tellen. Het gaat namelijk altijd om de een-na-laatste link, waar iets mee moet gebeuren. Als er ooit 'n link wordt tussengevoegd of weggehaald, zou je makkelijk kunnen vergeten deze selector aan te passen. Nu hoeft hij nooit aangepast te worden, want de een-na-laatste link is altijd de een-na-laatste, hoeveel links er ook nog bij zouden komen of zouden verdwijnen.

Als je in de broncode kijkt, zul je de class "no-touch" niet vinden. Deze class wordt door het JavaScript modernizr toegevoegd aan <html> bij browsers, die touch events niet herkennen. In principe werkt deze regel daardoor alleen in browsers, die touch events niet herkennen. Dat zijn (meestal) mobiele browsers.

Hoe dit verder precies werkt, staat bij Touchscreens herkennen met behulp van modernizr.

Om <html class="no-touch"> te kunnen zien in de broncode, moet je de gegenereerde code bekijken. In Firefox kan dat met behulp van bijvoorbeeld de extensies Firebug of Web Developer onder View Source → View Generated Source. Of met het in Firefox ingebouwde 'Element inspecteren'. Andere browsers hebben andere manieren om gegenereerde code te bekijken.

Bij .no-touch #wrapper is div#wrapper absoluut gepositioneerd, wat de mogelijkheid geeft om alleen tekst en foto's te scrollen, terwijl header, menu en footer altijd op dezelfde plaats blijven staan. Mobiele browsers hebben vaak moeite met dit soort constructies. Omdat mobiele browsers meestal touch events herkennen, missen die de class "no-touch" in <html>.

Daardoor wordt door die browsers deze regel genegeerd, en dat is precies de bedoeling. De ronde hoeken die hier worden gegeven, hebben alleen nut als <nav> links van de tekst wordt gepositioneerd.

border-bottom: black solid 1px;

Hé, de <a>'s hadden toch al 'n border aan de onderkant gekregen bij .no-touch nav a?

Ja, maar dat is niet voldoende voor deze <a>. Eerder in de css is bij nav li:nth-last-child(2) a specifiek bij deze <a> de border aan de onderkant weggehaald.

De border is weggehaald met de selector nav li:nth-last-child(2) a. Daarin zitten drie elementen (nav, li en a), en één pseudo-class (:nth-last-child(2)). Voor waar het hier om gaat, is een pseudo-class hetzelfde als een class. Deze selector bestaat dus uit drie elementen en één class.

Hierboven wordt een border gegeven met de selector .no-touch nav a. Daarin zitten twee elementen (nav en a) en één class (.no-touch).

In beide selectors zit één class. Maar in de eerste selector zitten drie elementen, en in de tweede maar twee. Daardoor heeft de eerste selector meer gewicht, meer specificiteit, en blijft van kracht, ook al staat de tweede selector later in de css.

En heeft deze <a> dus nog geen border aan de onderkant.

Om ook deze <a> een border aan de onderkant te geven, moet ik een selector gebruiken die evenveel of meer specificiteit heeft als de eerste selector. Evenveel is ook goed, want omdat hij later in de css staat overrulet hij de eerste selector dan ook. Bij dezelfde specificiteit wint de laatste selector.

De selector die ik hier gebruik is .no-touch nav li:nth-last-child(2) a. Daarin zitten drie elementen (nav, li en a), één pseudo-class (:nth-last-child(2)), en één class (.no-touch). De pseudo-class is voor waar het hier om gaat hetzelfde als een class, dus in deze selector zitten drie elementen en twee classes.

In de eerste selector, waarin de border werd verwijderd, zitten ook drie elementen. Maar er zit maar één class in, en in deze selector zitten er twee. Daardoor heeft deze selector meer specificiteit dan de eerste en heeft deze selector wel effect.

border-radius: 0 0 10px 10px;}

Links- en rechtsboven geen ronde hoek, rechts- en linksonder een ronde hoek.

Omdat maar één maat is opgegeven, worden de ronde hoeken even hoog als breed. (Je kunt ook twee maten opgeven, dan krijg je 'n ellipsvormige hoek.)

In tegenstelling tot wat de naam van deze eigenschap suggereert, krijgen ook achtergrondkleur en een eventuele achtergrond-afbeelding ronde hoeken.

css voor vensters breder dan 1400 px

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

De css die hier tot nu toe staat, geldt ook voor browservensters breder dan 1400 px. Elk venster dat minimaal 600 of 810 px breed is, is immers ook 1400 px breed. De css die hieronder staat, geldt alleen voor browservensters breder dan 1400 px. Voor een deel is dit nieuwe css, voor een deel wordt hierboven staande css aangepast.

De opbouw van de regel staat beschreven bij @media screen and (min-width 600px), het enige verschil is dat het hier om een minimumbreedte van 1400 px gaat.

#tekst

Het element met id="tekst". Dit is de div met de oranje achtergrond, waarbinnen de tekst staat.

width: 58%;

Bij de css voor vensters breder dan 810 px heeft div#tekst bij #tekst een breedte van 73% gekregen. Dat wordt in een venster met een minimale breedte van 1400 px behoorlijk breed en zou heel lange, lastig leesbare regels opleveren.

Die lange regels verschijnen niet, omdat bij de css voor alle breedtes bij #tekst een maximumbreedte van 50 em is opgegeven om dit te voorkomen.

In browservensters breder dan 810 px staat rechts van de tekst één kolom met foto's. Door de breedte van #tekst te verlagen in deze bredere vensters, komt er ruimte voor twee kolommen met foto's.

#foto p

De paragrafen binnen het element met id="foto". Dat is er hier maar eentje. De tekst gelijk onder het kopje 'Foto's' staat erin.

width: 39%;

Bij de css voor vensters breder dan 810 px is deze paragraaf bij #foto p 24 % breed gemaakt. De tekst staat boven de foto's. Nu er twee kolommen foto's naast div#tekst komen te staan, moet de <p> breder worden, anders zou hij maar boven één kolom komen te staan.

div#tekst is 58% breed, samen met deze <p> van 39% is dat 97%. Bij div#tekst komt nog een padding links en rechts van 1%, en bij deze <p> een padding van 0,5% links en rechts. Het totaal is dan 1 + 58 + 1 + 0,5 + 39 + 0,5 = 100%.

figure

Alle <figure>'s. Binnen elk van deze elementen staat een <img> met de afbeelding en een <figcaption> met het onderschrift.

width: 20%;

Bij figure heeft dit element een breedte van 25% gekregen, zodat er naast div#tekst, die 73% breed is, één kolom <figure>'s kan komen te staan.

Bij de css hier, voor vensters breder dan 1400 px, is bij #tekst een breedte van 58% aan div#tekst gegeven. Hierdoor is er nu ruimte voor twee kolommen <figure>'s, met de daarin zitten foto's en onderschriften.

Maar dan moet <figure> wel iets smaller worden gemaakt. Met een breedte van 20% passen er naast div#tekst met een breedte van 58% twee stuks. 58 + 20 + 20 = 98%. De 2% die overblijft, wordt gevuld met de padding van 1% links en rechts bij div#tekst.

<figure>'s die niet naast de tekst passen, worden onder de tekst gezet. Op elke regel onder de tekst passen vijf <figure>'s, en dus vijf foto's. En omdat de <figure> 20% breed is, staan ze netjes horizontaal verdeeld.

css voor vensters breder dan 1600 px

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

De css die hier tot nu toe staat, geldt ook voor browservensters breder dan 1600 px. Elk venster dat minimaal 600, 810 of 1400 px breed is, is immers ook 1600 px breed. De css die hieronder staat, geldt alleen voor browservensters breder dan 1600 px. Voor een deel is dit nieuwe css, voor een deel wordt hierboven staande css aangepast.

De opbouw van de regel staat beschreven bij @media screen and (min-width 600px), het enige verschil is dat het hier om een minimumbreedte van 1600 px gaat.

#tekst

Het element met id="tekst". Dit is de div met de oranje achtergrond, waarbinnen de tekst staat.

width: 48%;

Bij de css voor vensters breder dan 1400 px heeft div#tekst bij #tekst een breedte van 58% gekregen. Dat wordt in een venster met een minimale breedte van 1600 px behoorlijk breed en zou heel lange, lastig leesbare regels opleveren.

Maar dit gebeurt niet, omdat bij de css voor alle breedtes bij #tekst een maximumbreedte van 50 em is opgegeven, precies om dit te voorkomen.

In browservensters breder dan 1400 px staan rechts van de tekst twee kolommen met foto's. Door de breedte van #tekst te verlagen in deze nog bredere vensters, komt er ruimte voor drie kolommen met foto's.

#foto p

De paragrafen binnen het element met id="foto". Dat is er hier maar eentje. De tekst gelijk onder het kopje 'Foto's' staat erin.

width: 49%;

Bij de css voor vensters breder dan 1400 px is deze paragraaf bij #foto p 39 % breed gemaakt. De tekst staat boven de foto's. Nu er drie kolommen foto's naast div#tekst komen te staan, moet de <p> breder worden, anders zou hij maar boven twee kolommen komen te staan.

div#tekst is 48% breed, samen met deze <p> van 49% is dat 97%. Bij div#tekst komt nog een padding links en rechts van 1%, en bij deze <p> een padding van 0,5% links en rechts. Het totaal is dan 1 + 48 + 1 + 0,5 + 49 + 0,5 = 100%.

figure

Alle <figure>'s. Binnen elk van deze elementen staat een <img> met de afbeelding en een <figcaption> met het onderschrift.

width: 16.65%;

Bij figure heeft dit element een breedte van 20% gekregen, zodat er naast div#tekst, die 48% breed is, drie kolommen <figure>'s kunnen komen te staan.

Bij de css hier, voor browservensters breder dan 1600 px, is aan div#tekst bij #tekst een breedte van 48% gegeven. Hierdoor is er nu ruimte voor drie kolommen <figure>'s, met de daarin zitten foto's en onderschriften.

Maar dan moet <figure> wel iets smaller worden gemaakt. Met een breedte van 16,6% passen er naast div#tekst met een breedte van 48% drie stuks. 48 + 3 x 16,6 = 97,8%. De 2,2% die overblijft wordt gevuld met de padding van 1% links en rechts bij div#tekst.

(1 + 48 + 3 x 16,6 + 1 = 99,8%, en geen 100%. Maar die 0,2% zie je niet. Je zou 16,666666666666666...% kunnen nemen om steeds dichter bij de 100% te komen. Ik heb zoiets zelfs wel 'ns aangeraden gezien, nota bene in een peperduur papieren boek. Niet doen. Door afrondingsverschillen bij het omrekenen van procent naar pixel wordt de kans dan steeds groter dat de laatste <figure> nét niet meer op dezelfde regel past. Bovendien komt bij deze absurde precisie mijn weerzin voor vleselijke omgang met een bepaald zespotig sociaal insect weer naar boven.)

css voor vensters breder dan 1800 px

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

De css die hier tot nu toe staat, geldt ook browservensters breder dan 1800 px. Elk venster dat minimaal 600, 810, 1400 of 1600 px breed is, is immers ook 1800 px breed. De css die hieronder staat, geldt alleen voor browservensters breder dan 1800 px. Voor een deel is dit nieuwe css, voor een deel wordt hierboven staande css aangepast.

De opbouw van de regel staat beschreven bij @media screen and (min-width 600px), het enige verschil is dat het hier om een minimumbreedte van 1800 px gaat.

article

Alle <article>'s. Dat is er hier maar eentje. De tekst en de afbeeldingen zijn hierbinnen.

width: auto

Bij .no-touch article heeft <article> een breedte van 80% gekregen, zodat er aan de linkerkant een menu naast past. Bij vensters breder dan 1800 px wordt voor dat menu ruimte gemaakt met een marge aan de linkerkant. Bij een breedte van 80% blijft er veel te veel ruimte over voor dat menu.

auto is de standaardinstelling van <article>. Standaard wordt een blok-element zoals <article> even breed als zijn ouder, dat is hier div#wrapper. Die wordt standaard ook weer even breed als zijn ouder, dat is <body>. Via deze ketting wordt <article> ook even breed als de pagina.

Die ruimte van 80% werd alleen gegeven, als bij <html> de class "no-touch" stond. Hier krijgt <article> altijd auto. Dat maakt niet uit, omdat de <article>'s die niet binnen de class "no-touch" staan, altijd deze standaardinstelling al hadden. Die hebben hier dus geen enkele last van.

.no-touch article

De <article>'s binnen een element met class="no-touch". Er is hier maar één <article>. De tekst en de afbeeldingen staan erin.

Als je in de broncode kijkt, zul je de class "no-touch" niet vinden. Deze class wordt door het JavaScript modernizr toegevoegd aan <html> bij browsers, die touch events niet herkennen. In principe werkt deze regel daardoor alleen in browsers, die touch events niet herkennen. Dat zijn (meestal) mobiele browsers.

Hoe dit verder precies werkt, staat bij Touchscreens herkennen met behulp van modernizr.

Om <html class="no-touch"> te kunnen zien in de broncode, moet je de gegenereerde code bekijken. In Firefox kan dat met behulp van bijvoorbeeld de extensies Firebug of Web Developer onder View Source → View Generated Source. Of met het in Firefox ingebouwde 'Element inspecteren'. Andere browsers hebben andere manieren om gegenereerde code te bekijken.

Bij .no-touch #wrapper is div#wrapper absoluut gepositioneerd, wat de mogelijkheid geeft om alleen tekst en foto's te scrollen, terwijl header, menu en footer altijd op dezelfde plaats blijven staan. Mobiele browsers hebben vaak moeite met dit soort constructies. Omdat mobiele browsers meestal touch events herkennen, missen die de class "no-touch" in <html>.

Daardoor wordt door die browsers deze regel genegeerd, en dat is precies de bedoeling. Bij .no-touch nav is <nav> met daarin het menu aan de linkerkant van de tekst gezet, bij browser die touch events herkennen. De css hier is alleen voor die browsers nodig.

margin-left: 14%;

Aan de linkerkant een marge van 14% geven. Hierdoor komt daar ruimte om er <nav> met het menu neer te zetten.

.no-touch nav

De <nav>'s binnen een een element met class="no-touch". Er is hier maar één <nav>, waarbinnen het menu zit.

Als je in de broncode kijkt, zul je de class "no-touch" niet vinden. Deze class wordt door het JavaScript modernizr toegevoegd aan <html> bij browsers, die touch events niet herkennen. In principe werkt deze regel daardoor alleen in browsers, die touch events niet herkennen. Dat zijn (meestal) mobiele browsers.

Hoe dit verder precies werkt, staat bij Touchscreens herkennen met behulp van modernizr.

Om <html class="no-touch"> te kunnen zien in de broncode, moet je de gegenereerde code bekijken. In Firefox kan dat met behulp van bijvoorbeeld de extensies Firebug of Web Developer onder View Source → View Generated Source. Of met het in Firefox ingebouwde 'Element inspecteren'. Andere browsers hebben andere manieren om gegenereerde code te bekijken.

Bij .no-touch #wrapper is div#wrapper absoluut gepositioneerd, wat de mogelijkheid geeft om alleen tekst en foto's te scrollen, terwijl header, menu en footer altijd op dezelfde plaats blijven staan. Mobiele browsers hebben vaak moeite met dit soort constructies. Omdat mobiele browsers meestal touch events herkennen, missen die de class "no-touch" in <html>.

Daardoor wordt door die browsers deze regel genegeerd, en dat is precies de bedoeling. Als div#wrapper niet absoluut is gepositioneerd, hoeft ook <nav> niet links in het venster te worden gezet. En is daar dus ook geen css voor nodig.

width: 12%;

Bij .no-touch nav heeft <nav> een breedte van breedte van 18% gekregen. Dat is 'n beetje te veel van het goede in deze brede vensters, daarom wordt de breedte hier wat verlaagd.

#foto p

De paragrafen binnen het element met id="foto". Dat is er hier maar eentje. De tekst gelijk onder het kopje 'Foto's' staat erin.

width: auto;

Tot nu toe had deze <p> een breedte, zodat hij op de goede plaats boven één, twee of drie kolommen met foto's kwam te staan. In deze brede vensters is het aantal kolommen met foto's onbekend: er mogen er zoveel komen als in het venster passen.

Omdat het aantal onbekend is, is ook de gezamenlijke breedte van de kolom(men) met foto's onbekend. Dus is ook niet meer bekend, hoe breed deze <p> moet worden.

auto is de standaardinstelling. Een blok-element zoals een <p> vult dan normaal genomen de volle breedte van de ouder. Omdat bij foto p de tekst met text-align: center; horizontaal is gecentreerd, blijft de tekst toch horizontaal gecentreerd boven de foto's staan.

float: none;

Bij #foto p wordt deze <p> naar links gefloat om een marge te kunnen geven en zo. Dat is nu niet meer nodig. Maar als de <p> nog naar links wordt gefloat, komen <figure>'s en de foto's daarin niet onder, maar naast de <p> met tekst te staan, op dezelfde regel.

Door float ongedaan te maken, wordt de <p> weer een normaal blok-element en komen de <figure>'s niet naast, maar onder de tekst te staan.

figure

Alle <figure>'s. Binnen elk van deze elementen staat een <img> met de afbeelding en een <figcaption> met het onderschrift.

width: auto;

Tot nu toe had <figure> steeds een bepaalde breedte, zodat er in browservensters vanaf een bepaalde breedte één, twee of drie foto's naast de tekst pasten. Door een bepaalde breedte te gebruiken, konden die foto's netjes horizontaal verdeeld worden.

Nu is de breedte van het venster onbekend. Het is minimaal 1800 px breed, maar de precieze breedte is onbekend. Daarom wordt de breedte van <figure> ook vrijgegeven.

<figure> is een blok-element. Normaal genomen zou dat automatisch even breed worden als de ouder van het blok-element. Dat is hier div#foto. Die heeft geen breedte en wordt daardoor normaal genomen weer even breed als de ouder daarvan: <article>. Ook die heeft geen breedte en wordt dus even breed als de ouder daar weer van: div#wrapper. Ook al geen breedte, dus die wordt ook weer even breed als de ouder, dat is <body>. Hèhè, we zijn er. Via deze hele keten zou <figure> dus even breed worden als de pagina.

En omdat <figure> een blok-element is, zou elke <figure> op een nieuwe regel komen te staan. Hier is dat niet zo, omdat ze bij figure naar links zijn gefloat. En in dat geval wordt de breedte niet meer dan nodig is om de inhoud weer te geven. Dat zijn hier alleen de afbeelding met met links en rechts daarvan een kleine marge, en het bijbehorende onderschrift.

De breedte kan dus veilig worden verwijderd, waardoor er zoveel foto's naast elkaar worden gezet, als in de breedte van het venster passen.

Enige nadeel is dat ze nu niet meer netjes horizontaal zijn verdeeld, omdat de breedte onbekend is.

Je zou ze nog wel netjes kunnen verdelen door een nieuwe categorie browservensters te maken van 1800 tot 2000 px breed, van 2000 tot 2200 px breed, enz. Maar ik vind breder dan 1800 px mooi genoeg. Zoveel mensen zullen het venster van hun browser niet zo onwijs breed geopend hebben.

Speciaal voor Internet Explorer 7

Voor het grootste deel is dit dezelfde css, die wordt gebruikt voor andere browsers die touch events niet kennen. Maar omdat Internet Explorer 7 niet met de nieuwe media queries uit de voeten kan, wordt die css hier herhaald zonder media queries. Alleen de afwijkende css wordt hier beschreven, bij de css die hetzelfde is als de eerdere staan alleen verwijzingen naar die eerdere css.

De JavaScripts css3-mediaqueries.js en respond.js die het gebruik van media queries in Internet Explorer 7 mogelijk moeten maken, blijken niet te werken in deze browser. Dat is niet omdat die scripts zo slecht zijn, maar omdat Internet Explorer 7 voortdurend het meest krankzinnige en onverwachte gedrag vertoont. Als je rechts onderin een 'o' typt, springt er bij wijze van spreken spontaan een barst in de linkerbovenhoek van de monitor. Zoiets zal hier ook wel spelen. Waarschijnlijk zouden ze, met mogelijk veel moeite, wel werkend zijn te krijgen. Maar het is sneller om voor dit onding gewoon even de css te kopiëren en apart op te geven.

Ik geef direct toe dat ik niet meer echt grondig heb gezocht naar redenen, waarom iets niet goed werkte, of naar oplossingen. De ondersteuning voor deze browser wordt door steeds meer sites gestopt. Binnenkort is dat ook hier het geval. Er is geen enkele reden te bedenken, waarom iemand beslist met dit verouderde monster zou willen surfen. Het werkt. Alles meer is zonde van m'n tijd.

<!--[if IE 7]> <style> html {overflow: hidden;} header {max-width: 1280px; width: 100%; height: 7em; overflow: auto; border-bottom: black solid 1px; position: relative; z-index: 10;} #wrapper {max-width: 1280px; overflow-x: hidden; overflow-y: auto; position: absolute; bottom: 5em; top: 7em;} #top {display: none;} h1 {font-size: 1.6em;} h2 {font-size: 1.2em;} article {background: url(100-pics/space-1x1.gif); width: 80%; overflow: auto; margin: 0 0 5em 20%; padding-top: 0;} #tekst {background: url(100-pics/space-1x1.gif) orange; width: 73%; float: left;} #foto h2 {margin-top: 2%;} figure {width: 24.9%; float: left;} figure img {display: block; max-width: 94%;} nav {width: 18%; overflow: auto; font-size: 1em; margin-top: 0; border-right: black solid 1px; padding: 1.5% 1.1% 1% 1%; position: fixed; top: 7em; bottom: 5em;} #naar-top {display: none;} nav h2 {display: block;} nav li {width: 100%; float: none;} nav a {border-width: 0 1px 1px 0;} nav a {height: 2.2em; line-height: 2.2em; border-width: 0 1px 1px;} nav a:active, nav a:hover {background: black; color: white; outline: transparent solid 0;} nav li:first-child a {border-top: black solid 1px;} footer {width: 100%; max-width: 1280px; height: 5em; overflow: auto; position: fixed; bottom: 0;} </style> <![endif]-->

Dit eigenaardige stukje code heet een 'conditional comment' en wordt door alle browsers gezien als commentaar, omdat het tussen <!-- en --> staat. Maar Internet Explorer herkent het, door de extra toevoegingen, als speciaal voor Internet Explorer bedoeld en zal het dus uitvoeren. Het is veiliger dan een zogenaamde 'hack', waarbij vaak gebruik wordt gemaakt van 'n fout (bug) in de browser. Dit is opzettelijk aangebracht door Microsoft en zal dus blijven bestaan, terwijl 'n bug gerepareerd kan worden.

De style voor Internet Explorer moet ná de normale komen, omdat de opdrachten voor Internet Explorer dan over de normale heen gaan.

Dit stukje geldt voor Internet Explorer 7, maar je kunt het ook voor andere versies aangeven.

In plaats van de style kun je ook 'n normale link naar 'n extern css-bestand aanbrengen:

<!--[if IE 7]> <link rel="stylesheet" href="../../css/naam-van-ie-stylesheet.css"> <![endif]-->

Op de plaats van "../../css/naam-van-ie-stylesheet.css" vul je pad naar en naam van jouw stylesheet voor Internet Explorer 7 in. De css voor Internet Explorer 7 komt dan apart in die stylesheet te staan, zodat het de andere browsers niet stoort.

Het is belangrijk dat de spaties in <!--[if IE 7]> en <![endif]--> precies zo worden overgenomen zoals ze hier staan.

De toevoeging type="text/css" bij <style> of <link> is bij html5 niet meer nodig, omdat dit de standaardinstelling is.

html {overflow: hidden;}

Internet Explorer 7 heeft altijd een verticale scrollbalk, of dat nou nodig is of niet. Hiermee haal je die weg. Normaal genomen zou ik dat niet meer doen voor deze verouderde browser, daar is het niet belangrijk genoeg voor. Maar hieronder staat css die wél belangrijk is, en dan is het 'n kleine moeite dit erbij te zetten.

Als je 'n externe stylesheet gebruikt, loop je tegen 'n apart probleem aan bij html. Als je zonder meer html {overflow: hidden;} in je stylesheet zet, geldt dit voor élke pagina van je site. Terwijl het vrijwel zeker is dat er ook pagina's zullen zijn, waar deze instelling niet moet worden gebruikt.

Normaal genomen is dit geen probleem, omdat je bijvoorbeeld <body> 'n id kunt geven. Maar <html> valt buiten de body. Om dit op te lossen, kun je op de pagina's waar html {overflow: hidden;} moet worden gebruikt de html 'n id geven, bijvoorbeeld "ie-overflow-hidden". In je html wordt de regel dan iets als:

<html id="ie-overflow-hidden" lang="nl">

De precieze regel hangt af van het doctype dat je gebruikt. Dit is de regel die bij html5 hoort.

In de stylesheet gebruik je dan gewoon html#ie-overflow-hidden {...}. Nu is dit alleen geldig voor de pagina's die bij html de juiste id hebben staan.

<mopper>Zei ik 'kleine moeite'?</mopper>

header

Het vlak aan de bovenkant met de blauwe achtergrond.

max-width: 1280px;

Omdat media queries niet werken en de breedte van het browservenster dus onbekend is, wordt bij <header>, div#wrapper en <footer> op deze manier een maximumbreedte opgegeven om te lange, moeilijk leesbare regels te voorkomen.

Door bij alle drie de 'hoofd-onderdelen' dezelfde maximumbreedte op te geven, blijft de rechterkant van de pagina altijd recht, omdat alle onderdelen op dezelfde breedte eindigen.

height: 7em; overflow: auto; border-bottom: black solid 1px; position: relative; z-index: 10;

Beschrijving zie .no-touch header.

#wrapper

Het element met id="wrapper". Dit is een div, waarbinnen tekst, afbeeldingen en menu staan. Deze div vult de ruimte tussen <header> en <footer>.

max-width: 1280px;

Omdat media queries niet werken en de breedte van het browservenster dus onbekend is, wordt bij <header>, div#wrapper en <footer> op deze manier een maximumbreedte opgegeven om te lange, moeilijk leesbare regels te voorkomen.

Door bij alle drie de 'hoofd-onderdelen' dezelfde maximumbreedte op te geven, blijft de rechterkant van de pagina altijd recht, omdat alle onderdelen op dezelfde breedte eindigen.

overflow-x: hidden; overflow-y: auto;

Internet Explorer 7 krijgt een horizontale scrollbalk onder div#wrapper. De reden daarvan heb ik verder niet uitgezocht, het ding is gewoon overbodig. Met overflow-x wordt de horizontale scrollbalk verborgen.

Als ik gewoon overflow: hidden; zou gebruiken, verschijnt er ook geen verticale scrollbalk. Daardoor kun je helemaal niet scrollen en zijn niet alle tekst en afbeeldingen te zien. Daarom wordt overflow-x gebruikt: alleen de overflow in verticale richting.

Anders dan bij alle andere browsers moet hier de verticale scrollbalk niet naast <article>, maar hier naast div#wrapper komen, anders werkt hij niet. Daar zorgt deze overflow-y: auto; voor.

position: absolute; bottom: 5em; top: 7em;

Beschrijving zie .no-touch #wrapper.

#top {display: none;}

Beschrijving zie #top.

h1 {font-size: 1.6em;}

Beschrijving zie h1.

h2 {font-size: 1.2em;}

Beschrijving zie h2.

article

Alle <article>'s. Er is hier maar één <article>. De tekst en de afbeeldingen staan erin.

background: url(100-pics/space-1x1.gif);

Internet Explorer 7 heeft vaak problemen met scrollen. Dat is vaak op te lossen door een achtergrondkleur aan het te scrollen element te geven. Ook een doorzichtige gif lost vaak het probleem op. Dat laatste is hier gedaan. space-1x1.gif is een doorzichtige gif van 1 x 1 px.

width: 80%; margin-left: 20%;

Beschrijving zie .no-touch article.

#tekst {width: 73%; float: left;}

Beschrijving zie #tekst.

#foto h2 {margin-top: 2%;}

Beschrijving zie #foto h2.

figure {width: 24.9%; float: left;}

Beschrijving zie figure. Het enige verschil is dat de breedte hier 24,9% is en geen 25%, omdat er anders onder de tekst maar drie <figure>'s naast elkaar worden gezet, en dus ook maar drie foto's.

nav

Alle <nav>'s. Dat is er hier maar eentje: de <nav> waar het menu in staat.

width: 18%; overflow: auto; font-size: 1em; border-right: black solid 1px; padding: 1.5% 1.1% 1% 1%;

Beschrijving zie .no-touch nav.

position: fixed;

Bij nav is <nav> absoluut gepositioneerd, maar in deze browser scrolt <nav> en dus het menu toch mee. Door <nav> fixed te positioneren, blijft het ook hier stilstaan, als tekst en afbeeldingen worden gescrold.

top: 7em; bottom: 5em;

Vanwege de fixed positie moet <nav>, anders dan bij andere browsers, precies tussen <header> en <footer> worden neergezet.

#naar-top {display: none;}

Beschrijving zie #naar-top.

nav h2 {display: block;}

Beschrijving zie .no-touch nav h2.

nav li {width: 100%; float: none;}

Beschrijving zie .no-touch nav li.

nav a {height: 2.2em; line-height: 2.2em; border-width: 0 1px 1px;}

Beschrijving .no-touch nav a.

nav a:active, nav a:hover {background: black; color: white;}

Beschrijving zie .no-touch nav a:focus, .no-touch nav a:hover. Alleen wordt hier :active gebruikt in plaats van :focus.

nav li:first-child a

De link binnen het lijst-item dat het eerste kind is van <nav>. Dit is de link met 'Link een'.

border-top: black solid 1px;

Aan de bovenkant mist nog een zwarte border.

footer

Alle <footer>'s. Er is hier maar één <footer>, het blauwe vlak aan de onderkant.

width: 100%;

Beschrijving zie .no-touch footer.

max-width: 1280px;

Omdat media queries niet werken en de breedte van het browservenster dus onbekend is, wordt bij <header>, div#wrapper en <footer> op deze manier een maximumbreedte opgegeven om te lange, moeilijk leesbare regels te voorkomen.

Door bij alle drie de 'hoofd-onderdelen' dezelfde maximumbreedte op te geven, blijft de rechterkant van de pagina altijd recht, omdat alle onderdelen op dezelfde breedte eindigen.

height: 5em; overflow: auto;

Beschrijving zie .no-touch footer.

position: fixed;

In alle browsers werkt position: absolute; maar in deze browser scrolt de footer dan mee. Daarom wordt de footer fixed gepositioneerd.

bottom: 0;

Onderaan het venster van de browser zetten.

Speciaal voor Internet Explorer 9

<!--[if IE 9]> <style> @media screen and (min-width: 600px) { nav a {background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iIzU5NTk1OSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMxMzEzMTMiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);} } </style> <![endif]-->

Deze code geldt alleen voor Internet Explorer 9. Uitleg zie bij Speciaal voor Internet Explorer 7.

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

De opbouw van de regel staat beschreven bij @media screen and (min-width 600px).

nav a

De links binnen <nav>.

background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iIzU5NTk1OSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMxMzEzMTMiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);

Tja, het is Internet Explorer, en dat zul je weten ook.

In de knoppen bij browservensters van 600 tot 810 px breed wordt een linear-gradient gebruikt. Hierin zijn drie kleuren verwerkt. Helaas kent ook Internet Explorer 9 linear-gradient niet. Daarvoor moet je dus iets aparts doen.

Als je de linear-gradient in een andere browser exact honderd keer vergroot, zie je de afzonderlijke pixels. Een volledig witte pixel krijgt een waarde van 1, een zwarte pixel een waarde van 34.626. De tussenliggende kleuren krijgen simpelweg de tussenliggende waardes. Door deze decimale waarde te converteren naar de hexadecimale en tot de zevende macht te verheffen, krijgen we bovenstaande uitkomst, nadat we natuurlijk nog even zonder verdoving de wortel hebben getrokken. Het is niet lastig, want zelfs ik kan het. Heeft me maar drie weken gekost en het resultaat is indrukwekkend! Toch?

Als het aan Microsofts technologie zou liggen, zou je het inderdaad ongeveer zo doen, vrees ik. Gelukkig zijn er betere softwaremakers dan Microsoft. De gradiënt-editor op colorzilla.com levert gelijk met de normale linear-gradient ook bovenstaande toverformule.

De data:image/svg + xml;base64 aan het begin geeft aan dat het hier om een afbeelding gaat met MIME-type svg + xml, gecodeerd als base64. Maak je geen zorgen, de browser weet, wat dat betekent. Zelfs Internet Explorer 9.

Op deze manier kun je afbeeldingen in de css opnemen en hoef je geen extra afbeelding van de server te halen. En het is een aardige illustratie van de mogelijkheden van SVG, want je kunt er nog veel meer mee dan deze constructie, die eigenlijk overbodig zou moeten zijn. Op de pagina met links kun je onder het kopje SVG meer hierover vinden.

Speciaal voor Internet Explorer 7, 8 en 9

<!--[if (lt IE 10)]> <style> #onderaan {filter: progid:DXImageTransform.Microsoft.gradient startColorstr='#ffa500', endColorstr='#ffcccc');} </style> <![endif]-->

Deze code geldt alleen voor Internet Explorer beneden versie 10 (lt IE 10). Uitleg zie bij Speciaal voor Internet Explorer 7.

#onderaan

Het element met id="onderaan". Dit is een div die alleen voor de sier wordt gebruikt om de overgang van het oranje onder de tekst naar het roze onder de afbeeldingen iets te verzachten.

Bij #onderaan is een linear-gradient, een verlopende kleur, als achtergrond gegeven aan dit element. Internet Explorer 9 en eerder kennen dit niet. In Internet Explorer 10 is het waarschijnlijk eindelijk ingebouwd.

filter: progid:DXImageTransform.Microsoft.gradient startColorstr='#ffa500', endColorstr='#ffcccc');

Dit is Microsofts manier om verlopende kleuren aan te geven. De gradiënt-editor op colorzilla.com, die is gebruikt om de linear-gradient te maken, levert automatisch ook dit abacadabra.

Normaal genomen kun je de laatste kleur #ffcccc inkorten tot #fcc, maar hier kan dat niet.

Html5-elementen en Internet Explorer 7 en 8

Tegen de standaard in kun je in Internet Explorer 8 en ouder geen css gebruiken bij onbekende elementen. Volgens de standaard hoort de browser niets te doen met een onbekend element, maar moet je er wel css aan toe kunnen kennen. Microsoft wist dit weer 'ns beter en de gevolgen daarvan zullen nog jaren blijven spelen.

In dit voorbeeld worden de voor Internet Explorer 7 en 8 onbekende html5-elementen <header>, <section>, <nav>, <article>, <footer>, <figure> en <figcaption> gebruikt. De css voor deze elementen zou dus niet werken in Internet Explorer 8 en ouder.

Maar als je via JavaScript deze elementen eerst even 'voorstelt' aan de browser, blijken ze plotsklaps wél herkend te worden. En kan dus gewoon css voor deze elementen worden gebruikt. (In feite worden de elementen aan de DOM toegevoegd, een soort inhoudsopgave van onder andere alle html-elementen in een pagina.)

Internet Explorer 9 kent deze elementen wel, dus hier speelt dit probleem niet meer. (Internet Explorer 9 herkent trouwens, zoals het hoort, ook onbekende elementen, zodat je daar hoe dan ook css en zo bij kunt gebruiken.)

Anders dan vaak het geval is, moet deze JavaScript in de <head> van de pagina staan. De browser moet de elementen al kennen, voordat ze kunnen worden weergegeven. Als de elementen worden gelezen, voordat ze zijn aangemaakt, worden ze gewoon genegeerd. En kan er dus ook geen css aan worden gegeven.

Het eigenlijke JavaScript is heel kort en simpel. Voor dit voorbeeld kun je in de <head> het volgende neerzetten:

<!--[if lt IE 9]> <script> document.createElement("header"); document.createElement("section"); document.createElement("nav"); document.createElement("article"); document.createElement("footer"); document.createElement("figure"); document.createElement("figcaption"); </script> <![endif]-->

Deze code geldt alleen voor Internet Explorer beneden versie 9 (lt IE 9, less than). Uitleg zie bij Speciaal voor Internet Explorer 7.

<script> en </script> geven gewoon het begin en einde van het JavaScript aan. Bij html5 hoef je geen type meer op te geven, want het staat standaard op JavaScript ingesteld.

Het eigenlijke JavaScript bestaat uit:

document.createElement("header"); document.createElement("section"); document.createElement("nav"); document.createElement("article"); document.createElement("footer"); document.createElement("figure"); document.createElement("figcaption");

Door het toevoegen van zo'n regel voor een onbekend element, kan dat element nu gewoon worden gebruikt in Internet Explorer 7 en 8.

Deze JavaScript is uiterst beperkt: alleen de hier gebruikte html5-elementen worden aangemaakt, en dan alleen nog maar voor weergave op een scherm. Als je meer wilt doen dan alleen dit, is het mogelijk beter om voor Internet Explorer 7 en 8 het JavaScript op html5shiv te gebruiken. Voordeel van dit uitgebreidere script is onder andere dat standaard-instellingen als display: block; bij bijvoorbeeld <header> ook al worden doorgegeven aan Internet Explorer 7 en 8, zodat die niet in de css hoeven.

In dit voorbeeld zul je dit soort JavaScript niet vinden in de <head>. Er wordt in dit voorbeeld ook gebruik gemaakt van het JavaScript modernizr. Het herkennen van de onbekende html5-elementen kan ook door modernizr worden gedaan, als je er de hierboven genoemde html5shiv instopt. Dat is in dit voorbeeld gedaan. Meer hierover kun je vinden bij Touchscreens herkennen met behulp van modernizr. Omdat dit soort scripts voortdurend wordt verbeterd, is het absoluut nodig dat je zélf modernizr opnieuw samenstelt en niet gewoon het script uit de download gebruikt.

Het gebruik van JavaScript betekent helaas ook dat de css in Internet Explorer 7 en 8 niet werkt, als de bezoeker JavaScript uit heeft staan. Maar normaal genomen staat JavaScript alleen uit vanwege de veiligheid. En als je ook maar enigszins met veiligheid bezig bent, dan zul je niet Internet Explorer 7 of 8 gebruiken. Dus het aantal mensen waarbij in deze verouderde browsers JavaScript uit zal staan, is waarschijnlijk te verwaarlozen.

Mocht dit wel een bezwaar zijn, dan zul je <nav> en dergelijke door een gewone <div> moeten vervangen.

Een andere mogelijkheid is het gebruik van <noscript>, zoals ik op de site heb gedaan. Dit moet dan alleen voor Internet Explorer 7 en 8 worden gebruikt, want andere browsers herkennen de nieuwe elementen en hebben geen JavaScript nodig. In Internet Explorer kan <noscript> alleen css krijgen via een inline-style. Het wordt dan zoiets:

<!--[if lt IE 9]> <noscript> <div style="border: dotted red 10px; padding: 5px; background: white;"> Helaas, deze pagina werkt niet goed met oudere versies van Internet Explorer zonder JavaScript.<br> Drie mogelijkheden:<br> * Schakel JavaScript in;<br> * Installeer Internet Explorer 9;<br> * Stop met die troep van Microsoft en installeer 'n échte browser zoals Firefox, Google Chrome, Opera of Safari. </div> </noscript> <![endif]-->

Los van dat deze browsers bij <noscript> alleen css binnen 'n inline-style kunnen verwerken, moet ook nog 'n extra <div> worden gebruikt. Als je de style met <noscript style="..."> zou gebruiken, wordt een deel van de inhoud van <noscript> altijd getoond in Internet Explorer 8, ook al staat JavaScript aan.

Media queries en Internet Explorer 7 en 8

In css3 zijn de @media-regels fors uitgebreid. Met behulp van @media kunnen nu dingen als de breedte en hoogte van het browservenster worden opgevraagd. Afhankelijk van het resultaat kan dan bepaalde css juist wel of juist niet worden gebruikt.

Helaas kunnen Internet Explorer 7 en 8 hier niet mee overweg, en omdat Microsoft bestaande browsers nooit update (op veiligheidsupdates na), zal dit ook niet veranderen. Wat Microsoft kennelijk niet kan, heeft een aantal programmeurs zelf dan maar geprobeerd voor elkaar te krijgen. Met behulp van JavaScript kunnen ook deze browsers gebruik maken van media queries.

Helemaal probleemloos werkt dit bepaald niet. Omdat de code van deze browsers geheim is en er bergen afwijkingen en bugs in zitten, werkt dit JavaScript ook niet altijd, of soms zelfs helemaal niet.

Er zijn twee veel gebruikte JavaScripts om media queries te kunnen gebruiken: css3-mediaqueries-js en respond.js.

respond.js wordt alleen op de site gebruikt bij de pagina's die achter de links in het menu zitten. Op de site zitten in die pagina's links. De opmaak van die links is afhankelijk van de breedte van het venster van de browser. In de download staan geen links op die pagina's, dus daar speelt dit niet.

Om onduidelijke redenen werkt css3-mediaqueries.js niet goed op deze pagina's, en respond.js wel. Het zijn uiterst simpele pagina's, maar om een of andere reden gaat het mis bij gebruik van css3-mediaqueries.js. In Internet Explorer 8 is de linkerknop leeg, de links daarin verschijnen pas als je op de knop klikt, en dan nog niet allemaal in één keer, maar een voor een. respond.js werkt wel goed.

Op de voorbeeldpagina met de lay-out is het net omgekeerd. respond.js werkt wel op de voorbeeldpagina in de download, maar doet helemaal niets in vrijwel dezelfde pagina op de site. css3-mediaqueries.js werkt goed op beide pagina's. Goed? Nou, dat wil zeggen: in Internet Explorer 8. In Internet Explorer 7 doen beide scripts helemaal niets. (respond.js werkt dus wel op de sites in de pagina's achter de links in het menu.)

Internet Explorer 7 krijgt daarom eigen css, waarbij niet wordt gekeken naar de breedte van het venster van de browser. Omdat binnenkort de ondersteuning voor die verouderde gedrocht toch stopt, vind ik het wel prima zo.

Hieruit blijkt weer dat je de roestbakken die Microsoft abusievelijk browser noemt, uiterst goed moet testen. En waarom deze scripts niet werken? Geen flauw idee. Mogelijk is daar wel achter te komen, maar het werkt, en ik kan m'n tijd beter gebruiken.

In de <head> staat het volgende stukje code:

<!--[if IE 8]> <script src="100-files-dl/css3-mediaqueries.js"></script> <![endif]-->

Deze code geldt alleen voor Internet Explorer beneden versie 8. Uitleg zie bij Speciaal voor Internet Explorer 7.

css3-mediaqueries.js is het in de download bijgesloten JavaScript, dat ervoor zorgt dat Internet Explorer 8 met media queries uit de voeten kan.

Omdat dit soort scripts regelmatig wordt bijgewerkt, is het uitermate belangrijk dat je zelf dit script ophaalt van css3-mediaqueries-js en niet gewoon het script uit de download gebruikt.

Touchscreens herkennen met behulp van modernizr

In browservensters breder dan 810 px worden header, menu en footer vastgezet. Alleen de tekst en de foto's kunnen scrollen. Dit gebeurt door de footer, het menu en div#wrapper (met daarin de tekst en de foto's) absoluut te positioneren. Helaas kan dit in mobiele browsers tot grote problemen leiden, zoals het verdwijnen van een deel van de pagina. Dit speelt vooral in oudere browsers, nieuwere browsers kunnen beter met dit soort constructies uit de voeten. Een volledig overzicht van de problemen kun je vinden bij Bekende problemen.

Het is leuk dat dit probleem over 'n tijdje niet meer speelt, maar op dit moment zijn deze problemen nog zo groot, dat het beter is in mobiele browsers álles te laten scrollen, ook in vensters die breder zijn dan 810 px.

Hier ontstaat echter een probleem. Er is geen betrouwbare methode om te testen welke browser je site bezoekt. Vroeger moest dat noodgedwongen vanwege alle fouten en afwijkingen in browsers voor de desktop, en zelfs met 'n heel beperkt aantal browsers ging dat heel vaak mis. (Als je zoekt op 'browser sniffing' kun je, als je van griezelverhalen houdt, je hart ophalen.)

Voor mobiel bestaan veel meer browsers dan voor de desktop. Bovendien is het aantal resoluties vrijwel onbeperkt. En dan hebben de diverse apparaten ook nog 'ns hun specifieke eigenaardigheden en bugs. Op de desktop is een monitor gewoon een monitor, op mobiele apparaten ligt dat anders. Kortom: het is onbegonnen werk om op een betrouwbare manier te kijken, welk apparaat, welke versie van een besturingssysteem en welke browser iemand gebruikt. Je gaat gegarandeerd goed werkende browsers behandelen alsof ze problemen geven, en - erger - browsers met problemen alsof ze goed werken.

Dat was 'n inleiding om vrolijk van te worden: grote problemen en geen oplossing, want browser sniffing werkt niet betrouwbaar.

Er zijn mogelijkheden om op de server te kijken, of de site wordt bezocht door een mobiele browser of door een desktopbrowser, en afhankelijk daarvan een pagina voor mobiel of voor de desktop te sturen. Maar dan zit je in feite met twee (of nog meer) verschillende pagina's. Op de pagina met links vind je onder Mobiele apparatuur → Validators, snelheid testen, browser sniffing, en dergelijke links naar sites die hier bij kunnen helpen.

In dit voorbeeld wordt van één pagina uitgegaan. Om toch verschil te kunnen maken tussen mobiele browsers en browsers voor de desktop, wordt gekeken of de browser 'touch events' herkent. (Hartelijke verontschuldigingen en zo, maar er bestaan gewoon geen gangbare Nederlandse woorden voor dit soort Engelse termen. Bij 'aanrakings-evenement' denk ik persoonlijk niet direct aan een browser, en bij 'aanrakings-belevenis' ga ik echt aan héle andere dingen denken, die ik liever privé houd.)

Een browser die touch events herkent, zal in de regel een mobiele browser zijn. Een browser die touch events niet herkent, zal in de regel een desktopbrowser zijn. Als een desktopbrowser ten onrechte voor een mobiele browser wordt aangezien, is dat niet zo'n ramp. Alles werkt en ziet er goed uit en zo, alleen scrolt de hele pagina.

Als een mobiele browser voor een desktopbrowser wordt aangezien, kan dat vervelender zijn. Niet als de mobiele browser met deze constructie uit de voeten kan, maar dat is dus niet altijd het geval. Bij de geteste browsers is dat het geval bij Opera Mini op de iPad. In portretstand gaat het goed, want dan is het venster maar 768 px breed en scrolt de hele pagina. Maar in landschapsstand is het venster 1024 px breed. En Opera Mini meldt, ten onrechte, dat het geen touch events herkent, en wordt dus voor een desktopbrowser aangezien. (Wat er precies misgaat staat uitgebreider bij Bekende problemen.)

Een echt waterdichte oplossing is er niet voor dit probleem. Browser sniffing is onbetrouwbaar, en bij detectie op de server zit je met meerdere pagina's. Er wordt wel gewerkt aan dit probleem, en in css4 is het mogelijk opgelost, maar dat is voorlopig nog (verre) toekomstmuziek.

Het testen op het al dan niet herkennen van touch events gebeurt met behulp van een JavaScript: modernizr. Dit is een hele kleine JavaScript-bibliotheek die kan testen of een browser bepaalde mogelijkheden wel of niet heeft. Het gaat dan vooral om css3- en html5-mogelijkheden, maar ook testen op touch events kan.

Op de site van modernizr kun je aangeven, waarop je wilt testen. Er wordt dan een script op maat gemaakt, zodat het zo klein mogelijk is. Dit script test vervolgens of een browser iets wel of niet kan. Afhankelijk daarvan wordt aan de tag <html> een bepaalde class toegevoegd. In het geval van touch events is die class 'touch' of 'no-touch'. Dit geeft de mogelijkheid om, zonder verder JavaScript of zo nodig te hebben, aparte css te schrijven voor touchscreens en voor andere schermen.

css voor touchscreens laat je gewoon voorafgaan door .touch, en css voor andere schermen door .no-touch. Omdat in <html> één van deze twee aanwezig is, hoef je de selectors voor touchscreens alleen maar met .touch te beginnen, en die voor andere schermen met .no-touch. css die voor alle schermen hetzelfde is, laat je gewoon niet beginnen met .touch of .no-touch, zodat het op alle schermen werkt.

Omdat de meest simpele browsers de grootste problemen hebben met deze lay-out, wordt er standaard vanuit gegaan dat het om een mobiele browser gaat. Pas als de browser daadwerkelijk meldt dat touch events niet worden herkend, wordt de css voor een vaste header, menu en footer gebruikt.

De meest simpele browsers zitten in de regel ook op de kleinste apparaten. Daarom wordt ook standaard uitgegaan van een heel klein scherm. Pas als de browser meldt dat het venster breder is, wordt de css voor bredere vensters gebruikt.

In de download zit het gebruikte JavaScript bijgesloten als modernizr-touch-html5shiv.js. Dit script bevat meer dan alleen nodig is om touch events te detecteren. Het zorgt er ook voor dat Internet Explorer 7 en 8 html5-elementen herkennen. Je zou dat ook in een apart script kunnen doen, maar modernizr kan die twee scripts combineren.

Het is belangrijk zelf een nieuw script aan te maken op de site van modernizr, want dit soort scripts wordt voortdurend bijgewerkt. Het script dat is bijgesloten in de download kan inmiddels zijn verouderd.

Het JavaScript kun je aanmaken op modernizr.com/download. Om touch events te kunnen detecteren, heb ik daar onder Misc. 'Touch Events' aangevinkt. Verder moet je, om classes bij <html> aan te laten maken, onder 'Extra' nog aanvinken 'Add CSS Classes'.

Verder is nog aangevinkt 'html5shiv v3.4', zodat Internet Explorer 7 en 8 html5-elementen herkennen. Als je in plaats hiervan 'html5shiv v3.4 w/ printshiv' aanvinkt, kunnen deze elementen ook nog worden geprint door Internet Explorer 7 en 8.

Na het aanvinken van wat je in het JavaScript wilt hebben, klik je op de knop 'GENERATE!' Gelijk onder die knop staat nu het JavaScript. Dat is heel compact, tenzij je gelijk eronder een vinkje zet bij 'Don't Minify Source'. Ik heb daar geen vinkje gezet, want ik ga niets aan dit JavaScript veranderen, dus ik vind het prima als het script zo klein mogelijk is, ook al wordt het daar volstrekt onleesbaar door.

Het gegenereerde JavaScript kopieer je en plak je op de plaats waar het script moet komen te staan. Op mijn site bijvoorbeeld is dat in de folder 'js'.

Dit JavaScript wordt gelijk onder de link naar de style in de <head> gezet:

<script src="pad-en-naam.js"></script>

(In html5 is het type niet meer nodig bij een script, omdat standaard van JavaScript wordt uitgegaan.)

Aan de tag <html> voeg je de classnaam 'no-js' toe:

<html lang="nl" class="no-js">

Aan no-js worden door modernizr één of meer andere andere classes toegevoegd, afhankelijk van waarop wordt getest. In het geval van testen op touch events wordt er touch (aanwezig) of no-touch (niet aanwezig) toegevoegd. En no-js wordt altijd vervangen door js.

Altijd? Nee. Niet als JavaScript uitstaat, want dan werkt modernizr niet. Dat is een zwak punt van modernizr: het werkt niet als JavaScript ontbreekt of uitstaat. Maar in de praktijk vallen de beperkingen hiervan erg mee. Bovendien heb je ook nog de mogelijkheid om no-js in de selector te verwerken. no-js wordt immers alleen door js vervangen als JavaScript aanstaat. Dit geeft de mogelijkheid afwijkende css te geven als JavaScript uitstaat.

Zonder JavaScript komt er geen no-touch bij <html> te staan, dus wordt er dan vanuit gegaan dat het om een mobiele browser gaat. Er kan dus alleen ten onrechte een desktopbrowser worden aangezien voor een mobiele browser, en dat kan alleen als JavaScript uit staat. Dat is geen echt probleem, want ook dan zie je een fatsoenlijke pagina, alleen kan de hele pagina scrollen. Het is al mooi als alles werkt, want heel vaak is dat niet het geval zonder JavaScript. En ik kan het weten, want ik surf al jaren met JavaScript standaard uit.

Als modernizr goed is geïnstalleerd, zou je in de broncode bij <html> het volgende moeten zien:

<html lang="nl" class=" js no-touch">

of

<html lang="nl" class=" js touch">

Maar als je nu spoorslags in de broncode gaat controleren of dit klopt, zul je zien dat dit niet zo is. Als je gewoon de broncode bekijkt, zie je precies wat daar staat: de broncode. En daarin staat <html lang="nl" class="no-js">, dus dat zie je.

Wat je wilt zien, is de door JavaScript gegenereerde code. Die kun je in Firefox zien met behulp van bijvoorbeeld de extensie Firebug. Of met de extensie Web Developer onder View source → View Generated Source. Of met het in Firefox ingebouwde 'Element inspecteren'. Andere browsers hebben soortgelijke mogelijkheden om gegenereerde code te bekijken.

De code aanpassen aan je eigen ontwerp

Toegankelijkheid en zoekmachines

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

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

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

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

Enkele tips die helpen bij toegankelijkheid:

Specifiek voor dit voorbeeld

Zonder css wordt de site in de volgorde van de html op het scherm gezet: header, tekst en foto's, menu, footer. Dit is ook zoals de meeste spraakbrowsers en dergelijke het zullen zien.

Omdat de volgorde wat afwijkt van wat op het scherm wordt getoond (behalve in browservensters smaller dan 600 px), zijn bij dit voorbeeld WAI-ARIA-codes gebruikt om de toegankelijkheid te vergroten. Meer daarover kun je lezen bij Semantische elementen en WAI-ARIA.

Het menu is in een ongeordende lijst <ul> gezet, omdat veel spraakbrowsers en dergelijke een menu daarbinnen herkennen, zodat de gebruiker het in één keer kan passeren en naar de echte inhoud van de pagina kan gaan.

In de toekomst zullen spraakbrowsers en dergelijke een menu in een <nav> ook gaan herkennen, maar dat kan nog jaren duren. Bovendien is een menu in een <ul> heel makkelijk op te maken.

Getest in

Laatst gecontroleerd op 10 juli 2012.

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. Het is belangrijk dat 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 onderaan Toegankelijkheid en zoekmachines onder het kopje Specifiek voor dit voorbeeld.

Dit voorbeeld is getest op de volgende systemen:

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

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

Er is getest met behulp van muis en toetsenbord, behalve op de iPad en Android, waar een touchscreen is gebruikt.

Naast deze 'gewone' browsers is ook getest in Lynx, WebbIE, NVDA en Fangs Screen Reader Emulator. Lynx is een browser die alleen tekst laat zien en geen css gebruikt. WebbIE is een browser die gericht is op mensen met een handicap. NVDA is een screenreader, zoals die door blinden wordt gebruikt. Fangs Screen Reader Emulator is een extensie bij Firefox, die de pagina laat zien, zoals een screenreader hem ziet.

Als het voorbeeld in deze vier 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 onderaan 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 vermeld.

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

Bekende problemen

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.

Dit is een ontmoedigend lange lijst, maar de meeste problemen vallen heel erg mee. De lijst is vooral zo lang, omdat ik probeer zo volledig mogelijk te zijn.

Links binnen de pagina (ankers) in vensters breder dan 810 px

Kort samengevat: deze lay-out is minder geschikt voor pagina's die ankers bevatten. Het uitgebreidere verhaal:

Normaal genomen kun je met de Terug- en Vooruit-knop (de precieze naam hangt van de browser af) naar een vorige of (als die er al is) volgende pagina gaan. (Bij gebruik van een toetsenbord werken, afhankelijk van de browser, bepaalde toetscombinaties zoals alt+→ en alt+← precies hetzelfde.) Daarbij maakt het niet uit of die vorige of volgende pagina binnen of buiten de huidige site staat.

Op precies dezelfde manier kun je binnen een pagina terug- en vooruitgaan. Als je bijvoorbeeld bovenaan de pagina op een link klikt naar een plaats verderop in dezelfde pagina ('n anker), kun je normaal genomen met iets als alt+← weer terug, naar waar je geklikt hebt.

Omdat in dit geval alleen de rechterkolom, bij genoeg inhoud, wordt gescrold, zullen dit soort ankers alleen binnen de rechterkolom voorkomen. Helaas werken bij deze constructie de genoemde toetsen niet binnen de pagina zelf: je gaat niet terug of vooruit naar de vorige of volgende positie binnen de pagina, maar naar een compleet andere vorige of volgende pagina.

Als je position: absolute; weghaalt bij div#wrapper, of als je height: 100%; of overflow: auto; weghaalt bij <article>, werken de toetsen zoals ze normaal genomen werken: je gaat ook binnen de pagina terug of vooruit naar een vorige of volgende positie. Het weghalen van één van deze drie eigenschappen is al voldoende. (Voor zover browsers hier van afwijken, staat dat hieronder per browser aangegeven.) Alleen schiet dat ook niet echt op, omdat je dan deze lay-out niet kunt maken.

Dit is ook de reden dat dit probleem alleen speelt in browservensters breder dan 810 px: in smallere vensters worden deze drie eigenschappen niet gebruikt.

Deze lay-out is dus niet echt geschikt voor teksten, waarbinnen je veel heen en weer moet gaan, bijvoorbeeld om voetnoten onderaan de pagina te bekijken. En ook niet voor pagina's met (veel) ankers.

Om misverstanden te voorkomen: het gaat hier alleen om links binnen div#wrapper. Links vanuit header, footer of linkerkolom naar div#wrapper werken volledig normaal. Ook links naar en van andere pagina's werken op de normale manier, inclusief de genoemde toetscombinaties.

Overigens speelt ditzelfde probleem in de linkerkolom en in de footer, maar die zullen normaal genomen niet hoger zijn, dan er ruimte is, en er zullen al helemaal geen ankers in voorkomen.

Aanvullend op bovenstaande zijn er nog verschillen per browser:

Opera Mini: terug- of vooruitgaan binnen de pagina werkt helemaal nooit, je gaat altijd terug of vooruit naar de vorige of volgende pagina.

Safari (overal), Google Chrome (overal), Opera Mobiel (Android 4.0.3) en Android browser (Android 2.3.6): in deze browsers werken werken deze navigatietoetsen op de normale manier, ook binnen div#wrapper: je gaat terug naar de plaats waar je vandaan kwam, ook binnen de pagina. (Bij Safari en Google Chrome was dit eerst niet zo, dus er is hoop dat ze ooit in alle browsers goed werken.)

Internet Explorer 7: Ook als position: absolute; bij div#wrapper wordt weggehaald, of height: 100% of overflow: auto; bij <article>, wordt terug- of vooruitgegaan naar een vorige of volgende pagina, niet naar de vorige of volgende positie binnen de pagina.

Alle niet-mobiele browsers in vensters breder dan 810 px

Als het goed is, scrollen in deze browsers header, menu en footer niet mee met de rest van de pagina, maar blijven ze vast op het scherm staan.

Als er een verticale scrollbalk in het venster van de browser staat, kun je scrollen binnen het element waar die scrollbalk bij hoort. Vaak zal dat de hele pagina zijn. In dit voorbeeld is het de rechterkolom. (Hoewel wat hier beschreven staat ook geldt voor de footer en de linkerkolom, als daar zoveel in staat dat er een verticale scrollbalk zou verschijnen.)

Dat scrollen doen de meeste mensen met het wieltje van de muis of door in de scrollbalk te klikken of te slepen. Dit werkt allemaal zoals het normaal werkt.

Scrollen kan echter ook met PgDn of Spatiebalk, PgUp of Shift+Spatiebalk, ↓ of ↑. Met de eerste twee ga je 'n venster omlaag, met de middelste twee 'n venster omhoog, en met de pijltjes één regel omlaag of omhoog.

Omdat de rechterkolom binnen een absoluut gepositioneerde div staat, werken deze toetsen niet zonder meer. Je moet eerst even binnen div#content klikken. Mensen die deze toetsen gebruiken, zullen dit echter weten, omdat je dit heel vaak tegenkomt. Dus 'n echt groot probleem zal dit niet zijn.

Bij 'n touchscreen speelt dit uiteraard niet, omdat je per definitie het scherm aan moet raken om te kunnen scrollen.

Internet Explorer 7 en 8

  • Als het niet lijkt, op wat je op de site ziet, geen achtergrondkleuren heeft, alles zomaar ergens neergesmeten lijkt te zijn, enz., heb je waarschijnlijk geen JavaScript aangebracht voor deze browsers, of JavaScript staat uit. Bij Media queries en Internet Explorer 7 en 8 en Touchscreens herkennen met behulp van modernizr staat hier meer over.
  • Internet Explorer 7 en 8 hebben geen ronde hoeken aan boven- en onderkant van het menu, omdat ze border-radius niet kennen. Ik heb enkele scripts en dergelijke geprobeerd die ronde hoeken mogelijk maken in deze browser, maar die werkten niet. Soms werken die script wel, soms niet. Omdat de broncode van deze browsers geheim is, zijn altijd werkende scripts eigenlijk niet te maken.

    Op de pagina met links onder CSS → Bugs en hacks → Dingen mogelijk maken specifiek voor Internet Explorer vind je links naar JavaScript en zo, waarmee je zelf nog kunt gaan spelen in de hoop ronde hoeken te kunnen maken. Persoonlijk vind ik het de moeite niet waard. Het ziet er goed uit, alleen heeft het menu rechte hoeken.

    Internet Explorer 9 herkent (eindelijk) gewoon border-radius.

    (Ik jok 'n beetje. Verschillende scripts werkten te goed: het ene script maakte het menu helemaal zwart, maar met ronde hoeken, dat wel. Een andere script liet alleen de border van het menu staan, zonder links. Maar wel weer met ronde hoeken, eerlijk is eerlijk. Als je van 'n wild en opwindend leven houdt, zou ik zeker proberen ronde hoeken aan te brengen in deze browsers. Goedkoper dan 'n overlevingssafari en minstens even afwisselend.)

Internet Explorer 7

  • In Internet Explorer 7 is de zoomfunctie hopeloos slecht. Bij uitzoomen (verkleinen) vallen er op de wildste plaatsen gaten in de lay-out. Bij inzoomen (vergroten) verschijnt een horizontale scrollbalk. Alles is wel te zien, maar je moet voortdurend horizontaal scrollen, omdat tekst uit de rechterkolom onder het menu links verdwijnt.

    Als je alleen de lettergrootte verandert, gaat het wel goed.

  • In de rechterkolom werken PgDn, PgUp en de spatiebalk niet (normaal genomen werken Spatiebalk en Shift+Spatiebalk hetzelfde als PgDn en PgUp). Ze werken wel, als je eerst ergens in het roze deel naast de tekst klikt. Pardon? Welkom in de wondere wereld van Internet Explorer. Omdat deze browser inmiddels ook zwaar verouderd is, ga ik hier verder geen tijd aan besteden.
  • Dit pareltje van techniek, waarop Microsoft terecht apetrots was, kan de breedte van het browservenster niet vaststellen met behulp van @media. Daardoor zouden in brede vensters heel lange regels kunnen ontstaan, wat lastig leest. Om dat te voorkomen heeft deze zielenpiet een max-width gekregen. Dat kan ze nog net begrijpen. Op de pagina met links vind je onder CSS → Bugs en hacks → Dingen mogelijk maken specifiek voor Internet Explorer JavaScript en zo, waarmee je eventueel wel media queries werkend kunt proberen te krijgen. Mij is het niet gelukt in Internet Explorer 7. Maar ik heb het ook niet echt heel fanatiek geprobeerd, want binnenkort stop ik volledig met de ondersteuning voor deze browser.
  • Omdat de breedte niet met behulp van @media kan worden vastgesteld, komt in deze browser ook in vensters smaller dan 810 px een rij foto's naast de tekst te staan. Geen echt probleem, alleen worden de regels met tekst wat kort. Ook scrollen header, menu en footer nooit mee. De combinatie Internet Explorer 7 in een venster smaller dan 810 px zal trouwens niet heel vaak voorkomen.
  • Een serie kleinere afwijkingen, die mogelijk makkelijk zijn te herstellen, maar dat heb ik niet geprobeerd:
    onder de foto's zit een kleine lege ruimte;
    in de tekst boven de foto's wordt de padding aan de rechterkant genegeerd;
    de foto's naast de tekst staan iets te veel naar rechts;
    de <figcaption> onder de afbeeldingen wordt niet breder dan de tekst die erin staat.

Internet Explorer 8

  • In browservensters smaller dan 810 px hoort achter de knoppen van het menu een gradiënt te zitten: links en rechts zwart, in het midden iets grijzer. Zo'n gradiënt met drie kleuren is niet te maken in Internet Explorer 8, je zou daar een afbeelding voor moeten gebruiken. Daarom is in deze browser de achtergrond van de knoppen gewoon effen zwart.
  • Bij uitzoomen (verkleinen) springt de pagina steeds weer terug naar boven, als er omlaag wordt gescrold. In vensters breder dan 1400 px vervormen de afbeeldingen bij uitzoomen zo sterk, dat ze volledig onbruikbaar worden. Bij smallere vensters treedt dit ook op, maar pas bij sterk uitzoomen. Als alleen de lettergrootte wordt veranderd, gaat het wel goed.

    Dit zijn bijwerkingen van het JavaScript css3-mediaqueries.js. Bij het JavaScript respond.js gebeurde dit niet. (Ik gebruik css3-mediaqueries.js, omdat op de site respond.js niet werkt, en ik probeer het 'n beetje hetzelfde te houden, anders wordt het al snel één grote bende.)

    Dit komt trouwens niet, doordat dit script zo slecht is, maar doordat internet Explorer 8 barstensvol bugs en afwijkingen zit. En omdat de broncode ook nog 'ns geheim is, is het vrijwel onmogelijk die fouten te omzeilen.

Opera Mini op Android 2.3.6

  • Met de éénkolomsstand aan negeert Opera Mini de minimumhoogte van de links, waardoor het wat lastig is deze met de vingers te bedienen. Met de éénkolomsstand uit wordt de minimumhoogte wel aangehouden.
  • In vensters smaller dan 600 px staat het menu onderaan de pagina, gelijk boven de footer. In de header verschijnt een link naar het menu. Deze link is in Opera Mini niet onderstreept, waardoor het iets minder duidelijk is dat dit een link is. Opera Mini schijnt links gewoon nooit te onderstrepen.

Opera Mini op de iPad

Opera Mini op de iPad lijkt ten onrechte niet te melden dat touch events worden herkend. In portretstand is dit geen probleem, omdat de weergave dan altijd zonder gebruik van absolute posities is.

Maar in landschapsstand is dit wel een groot probleem, omdat footer, menu en div#wrapper met de tekst en foto's nu absoluut zijn gepositioneerd. Als je omlaag wilt scrollen in de tekst en de foto's, werkt dat niet. Tekst en foto's die onder het venster staan, worden niet zichtbaar. De hele pagina scrolt weliswaar, inclusief menu en footer, maar er verschijnt geen nieuwe tekst en geen nieuwe foto's. De hele pagina verdwijnt gewoon aan de bovenkant buiten het venster.

Als de pagina wordt geopend in portretstand, gaat het goed. Als vervolgens wordt gedraaid naar landschapsstand, blijft het goed gaan. De weergave voor mobiele browsers blijft behouden. Pas als na het draaien de pagina wordt ververst, wordt de weergave voor desktopbrowsers gebruikt en gaat het mis.

Als de pagina wordt geopend in landschapsstand, is het net omgekeerd. Ook bij draaien naar portretstand blijft de weergave voor desktopbrowsers gebruikt worden, en scrolt dus de hele pagina van het scherm, zonder dat nieuwe tekst of foto's verschijnen. Pas als de pagina na draaien wordt ververst, wordt de weergave voor mobiele browsers gebruikt.

Vensters breder dan 1800 px (in Opera breder dan 1600 px)

De thumbnails onder de tekst staan niet meer netjes uitgelijnd, omdat de breedte is 'vrijgegeven' en dus onbekend is. Ook naast de tekst staan de thumbs niet meer netjes verdeeld. Ze staan nog wel in kolommen uitgelijnd, maar de kolommen zelf zijn niet meer horizontaal gelijkelijk verdeeld over de lege ruimte naast de tekst.

Je kunt dit eventueel voorkomen door max-width te gebruiken, maar dat lijkt me eigenlijk de moeite niet waard, want niet veel mensen zullen zo'n breed browservenster hebben. En voor de enkeling die wel zo'n onwijs breed browservenster heeft, is dit waarschijnlijk het kleinste probleem...

In Opera speelt dit al in vensters breder dan 1600 px. Omdat het maar om 'n klein probleem gaat op 'n heel klein aantal schermen, laat ik dit verder zo.

Zoomen

Firefox, Opera, Internet Explorer 8 en 9 in Windows, OSX en Linux: in- en uitzoomen ziet er hetzelfde uit als wanneer de pagina zou worden getoond in een smaller of breder browservenster.

Safari en Google Chrome in Windows en OSX, Google Chrome in Linux: inzoomen (vergroten) werkt prima. Bij uitzoomen (verkleinen) wordt de lay-out nogal veranderd. Alles is goed te zien en zo, maar het ziet er niet meer echt heel netjes uit.

Valideren

linear-gradient wordt door de css-validator nog niet herkend en dus als fout aangemerkt. Omdat de oorzaak van de fout bekend is, is dat hier geen probleem. De validator wordt vaak veel te fanatiek gebruikt: het is een hulpmiddel om fouten te vinden, geen gereedschap om de Olympische Spelen voor Foutloze Code te winnen.

Mobiele browsers en fixed of absolute positie

Het gaat hier om problemen die zich niet voordoen, omdat geen fixed of absolute positie wordt gebruikt bij mobiele browsers. Maar als dat wel zou worden gebruikt, dan zouden onderstaande problemen zich voordoen. Die problemen zijn precies de reden dat geprobeerd wordt een absolute positie bij mobiele browsers te voorkomen.

Omdat er maar een beperkt aantal browsers is getest, zullen er waarschijnlijk nog (veel) meer problemen zijn die hier niet worden beschreven, omdat er niet op is getest.

Opera Mobiel op Android 4.0.3 in landschapsstand (1024x768): omdat in portretstand de hele pagina scrolt, spelen in portretstand onderstaande problemen niet.

Als de footer een absolute positie krijgt, staat de footer netjes onderaan het browservenster. Helaas scrolt de footer mee met de rest van de pagina. Daardoor is een deel van de tekst onleesbaar, omdat deze onder de meescrollende footer staat.

Dit is op te lossen door de footer een fixed positie te geven. (Dat is alleen nodig voor Opera Mobiel. Bij alle andere geteste browsers gaat het ook goed, als de footer een absolute positie heeft.) Als de footer een fixed positie krijgt, scrolt hij nog steeds mee. Maar als je stopt met scrollen, springt hij weer terug naar de onderkant van het venster. Het ziet er niet echt geweldig uit, maar in ieder geval is alles nu te zien.

Behalve helemaal onderaan de pagina, daar staat de footer weer over het onderste deel. Daardoor kun je van de onderste foto's 'n deel van de onderkant niet zien. Door onderaan <article> een extra marge te geven, wordt dat opgelost. Andere browsers hebben er geen last van, en voor Opera Mobiel geeft het ruimte om de footer neer te zetten, zonder dat die over de onderste foto's komt te staan.

Afbeelding 20: menu is in Opera mobiel lastig te scrollen

In Opera Mobiel op Android 4.0.3 scrolt het menu in de linkerkolom mee met de rest van de pagina. Je zou dat ook 'n fixed positie kunnen geven, zodat het net als de footer elke keer na het scrollen terugspringt. Maar dat begint meer op 'n vlooiencircus met 'n mislukte vlooientemmer aan het hoofd te lijken dan op een fatsoenlijke pagina.

Om een of andere reden geeft Opera Mobiel een grotere letter dan de andere browsers op dit systeem. Daardoor is het menu niet volledig zichtbaar: de onderste knop valt weg, zoals op de afbeelding hiernaast is te zien. Rechts van het menu staat echter wel een scrollbalk, waarmee die onderste knop toch valt te bereiken. Als je met je vinger scrolt, beweegt de hele pagina mee, dus je moet echt precies de scrollbalk aanraken met je vinger. Op de afbeelding is dat het minuscule donkergrijze stukje onderaan de scrollbalk. Een fantastische oefening voor een revalidatiecentrum.

Vanwege al deze problemen is het beter gewoon de hele pagina te laten scrollen. Dan hoeven menu en footer ook niet fixed gepositioneerd te worden, absoluut volstaat.

Opera Mini op de iPad in landschapsstand (1024x768): in portretstand speelt dit probleem niet, want daar scrolt de hele pagina mee.

Bij openen van de pagina ziet alles eruit zoals het hoort: header bovenaan, footer onderaan, menu links, tekst en 1 kolom foto's rechts. Maar bij scrollen blijkt álles mee te scrollen, alsof de pagina 'n afbeelding is. Bovendien verschijnen er ook geen nieuwe tekst of foto's: je ziet alleen wat er bij opening al zichtbaar was. De footer scrolt ook mee naar boven, en daaronder verschijnt gewoon een lege ruimte. Anders dan bij Opera Mobiel op Android is dit niet op te lossen door een fixed positie voor de footer te gebruiken.

Safari en Google Chrome op de iPad, Google Chrome, Android browser, Firefox en Opera Mobiel op Android 4.0.3, allemaal in landschapsstand (1024x768): niet echt een probleem, maar ik moest het ergens kwijt. Bij inzoomen (vergroten) verdwijnen header en footer buiten het venster. Als door scrollen de header of footer weer terugkomt op het venster, blijft die weer staan. In Android browser blijft de footer altijd staan. In Opera Mobiel verdwijnt de footer bij scrollen, maar springt gelijk terug zodra het scrollen stopt.

Het werkt allemaal wel, maar om nou te zeggen dat het 'n rustig beeld geeft...

Android browser in landschapsstand op Android 4.0.3: in landschapsstand werkt er geen enkele link naar een anker binnen de pagina, ook niet vanuit de header, menu of footer. Links naar andere pagina's werken wel normaal. Ook zonder position: absolute; bij div#wrapper werken de ankers niet, wel als je height: 100%; of overflow: auto; bij <article> weghaalt. Probleem is dat de ankers gewoon helemaal niet worden herkend: de id wordt niet opgepikt. Vandaar dat een link naar een andere site wel gewoon werkt. Dit is ook de reden dat het in portretstand wel werkt: daar worden deze eigenschappen niet gebruikt.

Dit is een ernstig probleem. Samen met het gelijk hieronder staande probleem in Firefox op Android 4.0.3, maakt dit het gebruik van ankers feitelijk onmogelijk, als de pagina ook geschikt moet zijn voor mobiel.

Firefox in landschapsstand op Android 4.0.3: (Vlak voordat deze tekst af was, verscheen Firefox 14 voor mobiel. In deze versie is onderstaand probleem opgelost.)

Links vanuit header, menu en footer naar 'n anker binnen div#wrapper werken gewoon.

In portretstand werkt alles zoals het hoort. In landschapsstand gebeurt er het volgende: als er binnen div#wrapper een link staat naar 'n anker dat ook binnen div#wrapper staat, werkt ook die link de eerste keer normaal. Maar bij elke volgende aanraking van div#wrapper (het oranje deel van de pagina), waar dan ook, verschuift de pagina naar een ogenschijnlijk willekeurige plaats. Dat gebeurt ook, als je 'n link naar 'n anker aanraakt. Bij een volgende aanraking werkt alles weer normaal, bij de aanraking daarna wordt weer verplaatst naar 'n ogenschijnlijk willekeurige positie, enz. Dus afwisselend goed en fout.

Dit is vervelender dan het mogelijk lijkt. Op het moment dat je voor de tweede keer op een link klikt en naar een ogenschijnlijk willekeurige plaats wordt gescrold, is de link waar je op klikte ook verdwenen. En er is geen simpele manier om naar die link terug te gaan, dus dat wordt zoeken.

Dit is een ernstig probleem. Samen met het gelijk hierboven staande probleem in Android browser op Android 4.0.3, maakt dit het gebruik van ankers feitelijk onmogelijk, als de pagina ook geschikt moet zijn voor mobiel.

(Vlak voordat deze tekst af was, verscheen Firefox 14 voor mobiel. In deze versie is onderstaand probleem opgelost.)

Wijzigingen

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

:

Nieuw opgenomen.

4 april 2013:

Hele stuk over de nieuwe html5-outline verwijderd, omdat dit toch niet in de uiteindelijke specificatie komt te staan.