Vijf basistechnieken voor flexibel webdesign

Een website telt tegenwoordig niet mee als hij niet goed op een mobieltje te lezen valt. Dat komt onder meer omdat mensen er steeds vaker op belanden via een link op Twitter (merk ik in elk geval). Een site moet zich dus aanpassen aan het schermformaat van de gebruiker. Dit heet flexible/adaptive/fluid/responsive design. Het lijkt ingewikkeld, maar in de praktijk is het goed te doen, nadat je jezelf over de drempel gezet hebt dat je niet meer op de pixel nauwkeurig al je pagina-elementen kunt neerzetten. Hieronder een stappenplan, waarbij ik aanneem dat je al weet hoe je een inflexibele site maakt.

Media queries

Media queries vormen het hart van flexibel design: hiermee kun je verschillende opmaakmogelijkheden hanteren afhankelijk van de breedte van de browser. Zet daartoe regels volgens het volgende stramien in je css bestand:

@media screen and (max-width: 640px) {body {background:yellow;}}@media screen and (min-width: 641px) and (max-width: 1000px) {body {background:red;}}@media screen and (min-width: 1001px) {body {background:blue;}}

Dit simpele voorbeeld maakt de achtergrond geel, rood of blauw afhankelijk van de schrembreedte. Uiteraard kun je zoveel schermformaten onderscheiden als je zelf wilt. Je zult deze regels vooral gebruiken voor de ordening van kolommen: alles onder elkaar op een mobieltje, meerdere kolommen naast elkaar op grote schermen.

Browser afhankelijkheden

Is het zo simpel? Ja. Ware het niet dat niet alle browsers even goed omgaan met media queries. Sommige mobiele browsers (met name Safari) hebben de neiging een pagina te schalen waar dat helemaal niet de bedoeling is. Gelukkig is daar een eenvoudige remedie voor. Voeg de volgende regel toe aan de head van je site:

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

Een groter probleem vormen oude versies van Internet Explorer. Die snappen media queries niet. Daar zijn twee oplossingsrichtingen voor:

  1. Voeg een stuk javascript toe om oudere browsers te vertellen hoe media queries werken. Mijn ervaring is dat dit goed functioneert, maar wel langzaam. Een alternatief, iets minder krachtig script werkt sneller, maar je houdt het probleem dat Internet Explorer veel tijd nodig heeft om alle pagina elementen op zijn plek te zetten.
  2. Neem aan dat oude versies van Internet Explorer draaien op een scherm van tenminste 1024 pixels breed. Zet de betreffende opmaakaanwijzingen vóór de media queries in je css bestand. Browsers lezen die dan als eerste in. Moderne browsers gooien die weg als ze even later vervangende aanwijzingen tegen komen in de media queries. Een schoonheidsprijs verdient deze aanpak niet, maar het werkt wel.

Omgaan met kolommen

Er zijn allerlei manieren om een kolomindeling te realiseren. De eenvoudigste manier is om die flexibel te maken is door te spelen met breedtes en floats, bijvoorbeeld als volgt:

@media screen and (max-width: 640px) {.maincontent {width:100%;}, .sidebar1 {width:100%;}, .sidebar2 {width:100%;}}@media screen and (min-width: 641px) and (max-width: 1000px) {.maincontent {width:66%;float:left;}, .sidebar1 {width:33%;float:right;}, .sidebar2 {width:33%;float:right;}}@media screen and (min-width: 1001px) {.maincontent {width:50%}, .sidebar1 {width:25%; float:right;}, .sidebar2 {width:25%;float:right;}}

Bovenstaande is een layout met een hoofdkolom en twee sidebars. Bij kleine schermen pakken ze alle drie de volledige breedte, zodat ze onder elkaar belanden. Bij middelgrote schermen staan de twee sidebars onder elkaar rechts van de hoofdkolom, omdat ze tegen de rechtermarge aangedrukt worden, maar er vanwege hun breedtes niet genoeg ruimte is om ze naast elkaar te tonen. Bij grote schermen is er wel genoeg ruimte om ze naast elkaar te tonen, dus zal dat ook gebeuren.

Floats, em’s en percentages

In bovenstaand voorbeeld kwam al aan de orde dat je de breedte van kolommen definieert in percentages (dus niet in pixels) en positioneert met floats (dus niet met het position attribute). De derde component voor een flexibele lay-out is em, waarmee je het formaat van lay-out onderdelen kunt relateren aan de fontgrootte. In feite moet je proberen geen enkele onderdeel van je vormgeving in pixels te definiëren, behalve dingen als dunne lijntjes.

Wanneer je alle fontformaten, spatiëringen, lijnhoogtes, marges, enzovoort in em’s en percentages hebt uitgedrukt, reageert je site beter als het beeld geschaald wordt. Ook kun je, door het formaat van het bodyfont te veranderen, de hele site schalen zonder dat de proporties veranderen. Je kunt bijvoorbeeld in de media queries opnemen dat het font kleiner is op de kleinste schermen, omdat gebruikers die dichter bij hun ogen houden.

Schaalbare plaatjes

Als kolommen kleiner/groter worden, moeten de plaatjes uiteraard mee schalen. Browsers doen dat automatisch, tenzij expliciet de breedte en hoogte van een plaatje wordt aangegeven. Dit heb je grotendeels zelf in de hand, behalve dat WordPress de hinderlijke gewoonte heeft hoogte en breedte toe te voegen. Je kunt ze weer handmatig verwijderen, maar je kunt het ook voorkomen met het volgende stukje code in het functions.php bestand van je thema:

<?phpfunction remove_thumbnail_dimensions ($html) {$html = preg_replace ('/(width|height)="d*"s/', "", $html); return $html;}add_filter ('post_thumbnail_html', 'remove_thumbnail_dimensions', 10);add_filter ('image_send_to_editor', 'remove_thumbnail_dimensions', 10);add_filter ('wp_get_attachment_link', 'remove_thumbnail_dimensions', 10);?>

Hoewel het dus niet handig is de precieze hoogte en breedte aan te geven, wil je allicht niet dat plaatjes al te groot (of te klein) worden. Daarvoor gebruik je max-width en min-width. Wanneer je (zoals deze site) plaatjes standaard met een breedte van 750 pixels inlaadt, zet je de max-width op 750, omdat het plaatje vaag wordt als de kolom breder wordt. Max-width en width zijn in combinatie te gebruiken. Op deze manier kun je bijvoorbeeld zorgen dat een plaatje altijd de volle kolombreedte pakt, maar niet verder groeit als de kolom breder wordt dan 750 pixels:

img {width:100%; max-width:750px;}

De plaatjes in de sidebar zullen doorgaans aanzienlijk kleiner zijn dan die in de hoofdkolom. Die kun je ook gewoon schalen, maar daar word je site langzaam van: grote plaatjes vreten immers bandbreedte. Gelukkig slaat WordPress standaard vier versies op van een plaatje. Je kunt in je thema dan een kleinere versie opnemen in de sidebar en zo bandbreedte sparen.

Nu zul je zien dat de standaard versies niet goed aansluiten bij de standaard kolombreedten van je thema. De standaardmaten kun je wijzigen bij instellingen–>media in de WordPress installatie. Je kunt je eigen voorkeursformaten ook in je thema stoppen door de volgende regels toe te voegen aan functions.php (tutorial hier):

<?phpadd_theme_support('post-thumbnails');add_image_size('naam-voor-gebruik-in-thema', BREEDTE, LENGTE, true);?>

Touch ready

Hartstikke mooi, al die effectjes die je krijgt als je met de muis over een element heen beweegt, maar op een touchscreen zie je daar helemaal niets van. Dat is niet zo erg voor decoratieve effecten, zoals links die van kleur veranderen. Maar als je niet bij alle menufuncties kunt, omdat die pas uitklappen als de muis over de hoofdmenubalk gaat, is dat toch wel een probleem.

Het probleem is dat browsers niet vooraf detecteren of je met een muis- of touch-apparaat van doen hebt. Bovendien zijn de eerste apparaten gesignaleerd die allebei hebben, zodat je als ontwerper helemaal niet weet waar je aan toe bent. Voor essentiële onderdelen van een ontwerp is het daarom het verstandigst helemaal geen hover-functies te gebruiken.

Wat browsers wel doen is een signaal afgeven zodra de eerste touch-handeling een feit is. Je kunt dus een site ontwerpen voor muis, maar de lay-out switchen zodra je een aanraking waarneemt. Met de volgende code verander je de class van je body. Met css kun je vervolgens elementen van je site aanpassen aan touch-gebruik:

<body class="mouseuser" ontouchstart="$(this).removeClass('mouseuser').addClass('touchuser');">

Als alleen je menubalk moet uitklappen, is het intuïtief logischer om het ontouchstart-event te koppelen aan de wrapper van je menu. Ideaal is deze oplossing niet, maar het werkt wel.

Tot slot

Er zijn manieren om dit allemaal geavanceerder aan te pakken, met name HTML5 Boiler Plate en Bootstrap. Dat zijn platforms waarin veel van het bovenstaande is ingebouwd. Dat is handig, maar er is wel een extra leerstap voor nodig.