Toveren met CSS Grid Layout

CSS is de opmaaktaal voor websites en -apps. Met de bundel van drie boeken uit de Web Development Library over die onderwerp leer je alle mogelijkheden, waardoor je veel betere websites ontwerpt. In het boek CSS 3 van Doolaard en Kassenaar leer je werken met CSS-selectors, maateenheden, het box-model, kleurmodellen en meer. De vele oefeningen maken het tot een perfect (zelf-)studieboek. Ben je de basis voorbij? In CSS Flexbox & Grid Layout helpt Peter Doolaard je met het maken van lay-outs voor webpagina’s met Flexible Box Layout en CSS Grid Layout. Deze technieken zijn bedoeld om op een intuïtieve manier complete webpagina’s, apps en onderdelen van de gebruikersinterface in te delen. Met het boek Bootstrap 4 van Peter Kassenaar kunnen niet-designers hun websites snel op consistente en eenvoudige manier opmaken, terwijl ‘echte’ designers hun hart kunnen ophalen aan de vele mogelijkheden die het framework biedt om het naar eigen wens in te stellen. Vergroot je CSS-expertise en bestel deze drie boeken samen voor een voordelige prijs. Hieronder vind je een voorbeeld over het werken met CSS: Toveren met CSS Grid layout van de hand van Peter Doolaard.(H.F.)

Toveren met CSS Grid layout

Hoe bouw je met dezelfde HTML-codebasis een website met vier gezichten? Je leest het in dit artikel waarin we de website rollingstone.com namaken. De lay-out van deze website varieert van één tot vier kolommen waarbij de inhoud steeds net even anders wordt gepresenteerd. CSS Grid Layout en de nieuwe optie subgrid zorgen voor de magie.

Op Codepen staan twee versies van dit project. De eerste versie is gebouwd met een grid in een grid. De tweede versie is gemaakt met de nieuwe optie subgrid. Dit artikel gaat over het subgrid. Leg de code ernaast en je kunt precies volgen wat er gebeurt. Bovendien kun je experimenteren omdat de code bewerkbaar is.

Het project: rollingstone.com

Moderne CSS heeft steeds betere hulpmiddelen om elke lay-out te bouwen die je kunt bedenken. Waar je ooit moest knoeien met tabellen en floats, bouw je nu met CSS Grid Layout en media queries snel een website die er goed uitziet op een telefoon, een tablet, een laptop en een groot desktopscherm, inclusief alle tussenmaten. Ons project is de homepage van het Amerikaanse blad Rolling Stone. Het bovenste deel van die pagina bestaat uit vier secties: een header, Features, The Latest en Trending. Dat deel gaan we bouwen.

Schermopname van de pagina rollingstone.com.
De bovenste sectie van het voorbeeld op een desktopscherm.

CSS Grid Layout

Met CSS Grid Layout bouw je een opmaakraster (grid). Je kunt daarbij denken aan een krantenopmaak met 12 kolommen. Daarin plaats je tekst en afbeeldingen die afwisselend een of meer kolommen overspannen. Zo’n raster geeft ritme en consistentie aan de lay-out.

Een webpagina is geen krant. Je weet nooit op welk schermformaat iemand de pagina bekijkt en daarom kun je geen statische lay-out maken. Maar je kunt wel degelijk een opmaakraster gebruiken. Je moet er alleen voor zorgen dat het raster flexibel is. Dat kun je bereiken met CSS Grid Layout en media queries.

112 Firefox

Rasters kunnen verwarrend zijn en dan is het reuze handig om een hulpmiddel te hebben waarmee je kunt zien wat je doet. De browser Firefox heeft zo’n hulpmiddel. Open in Firefox de site rollingstone.com, activeer met Ctrl+Shift+I de hulpmiddelen voor ontwikkelaars (devtools) en activeer de responsivedesignmodus (Ctrl+Shift+M). Kies een apparaat met een schermbreedte van 360 pixels, bijvoorbeeld een Galaxy S9. (Of versleep de rechterrand van de weergave om ‘het scherm’ kleiner te maken.) De rasterhulp vind je op het tabblad Indeling. Met selectievakjes schakel je de weergave van een of meer rasters in. Je ziet nu aan de genummerde lijnen hoe het raster is opgebouwd.

Schermafbeelding van De ontwikkelaarshulpmiddelen van Firefox.
De ontwikkelaarshulpmiddelen van Firefox. Links labels met grid, subgrid en flex. Rechts de selectievakjes om het raster zichtbaar te maken.

 

Schermopname van rollingstone.com.
De sectie Features op een telefoon met rasterweergave ingeschakeld.

Ook in de telefoonweergave zijn alle onderdelen uit de eerste afbeelding er, maar ze zijn anders gerangschikt. Hier kunnen we wel gelijk de HTML-structuur uit afleiden, want deze weergave is het resultaat van de normale flow. Dat wil zeggen: de onderdelen op de pagina worden getoond in de volgorde waarin ze in de HTML-code staan. In volgorde zie je:

  • de paginaheader;
  • een grote foto/uitgelicht artikel;
  • twee kleinere foto’s/uitgelichte artikelen;
  • het laatste nieuws;
  • de meestgelezen artikelen.

De meeste onderdelen gebruiken op telefoon de hele breedte van het scherm, waardoor ze vanzelf onder elkaar komen te staan. Maar de artikelen met een kleine foto moeten naast elkaar komen. Wordt het scherm wat groter, dan staan de drie artikelen naast elkaar (zie de afbeelding met het breekpunt op 768 pixels). Daarom is het bij dit project handig om gelijk al een raster (grid) te definiëren.

Voorbereiding

Voor een goede werking zijn de afmetingen van de afbeeldingen aan banden gelegd. In de CSS zijn de breedte en hoogte ingesteld op 100%. Zo wordt de foto altijd even groot als zijn container. Doe je dat niet, dan zou de foto buiten het scherm doorlopen (overloop met een horizontale schuifbalk) of niet groot genoeg worden. De afbeeldingen zijn ook volgens een vaste verhouding bijgesneden: de kleine zijn vierkant en bij de grote foto is de hoogte 1,2 keer de breedte.

Mobile first

Het is gebruikelijk om een veranderende lay-out te coderen van klein naar groot (mobile first). Een reden daarvoor is dat een ontwerp op een telefoon meestal uit één kolom bestaat. Daardoor vallen de onderdelen vaak vanzelf op hun plek. De CSS-code die je daarvoor schrijft, is grotendeels ook geschikt voor grotere weergaven. Je hoeft alleen de basiscode uit te breiden met de veranderingen voor grotere weergaven.

Een raster instellen

Een raster bestaat uit een container met daarin items. Alleen kinderen van de rastercontainer zijn rasteritems. Andere afstammelingen zijn dat niet. Dat is een belangrijk gegeven, want alleen rasteritems houden zich aan de regels van het raster. Het betekent ook dat je soms een raster in een raster moet maken (nesten). Dat kan prima en het is op dit moment voor productiewebsites de enige mogelijkheid. Hoe dat werkt zie je in het codevoorbeeld grid in grid op CodePen.

Dit artikel beschrijft een nieuwe mogelijkheid voor het bouwen van rasters: subgrid. Helaas werkt subgrid alleen in Firefox. In andere browsers is het nog niet ingebouwd. Maar je had Firefox toch al nodig vanwege het geweldige hulpmiddel om rasters te debuggen.

Als je de pagina rollingstone.com op verschillende formaten bekijkt, zie je dat er nooit meer dan vier kolommen en vier rijen zijn. Daarmee maken we het basisraster dat wordt toegepast op het element main. Dit is ons uitgangspunt dat vanaf een telefoon van 320 pixels breed prima werkt.

main {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(4, auto);
}

Met display: grid maak je een rastercontainer. De kinderen van main zijn de rasteritems: .features, .latest en .trending. Je merkt terecht op dat dit geen vier maar drie rijen zijn. Maar nu maken we het subgrid voor .features, de drie foto’s die op een telefoon deels onder elkaar staan.

De waarde 1fr staat voor één deel van ruimte die overblijft nadat blokken die een vaste afmeting hebben zijn geplaatst. Hier heeft niets een vaste afmeting, dus de vier kolommen krijgen elk een kwart van de breedte.

Het sleutelwoord auto maakt een rastercel zo groot als nodig is voor de inhoud die erin moet.

Het subgrid maken

.features {
  display: grid;
  grid-column: 1 / 5;
  grid-row: 1 / 3;
  grid-template-columns: subgrid;
  grid-template-rows: subgrid;
}

Deze CSS-code plaats het rasteritem .features als geheel op kolom 1 t/m 4 en rij 1 en 2. De nummers in de CSS verwijzen naar de rasterlijnen: kolom 1 loopt van lijn 1 naar lijn 2, kolom 2 loopt van lijn 2 naar lijn 3 enzovoort. Bekijk dit vooral in de rasterweergave van Firefox en schakel Regelnummers weergeven in.

Tegelijk wordt met display: grid van .features ook een rastercontainer gemaakt. De template voor het raster (de indeling in rijen en kolommen) wordt door de instelling subgrid overgenomen van main. Dus nu heeft .features ook een raster van vier kolommen en vier rijen. Daarin plaatsen we de berichten met foto’s:

.feature.col2 {
  grid-column: 1 / 5;
  grid-row: 1 / 2;
}
.feature:nth-of-type(2) {
  grid-column: 1 / 3;
  grid-row: 2 / 3;
}
.feature:nth-of-type(3) {
  grid-column: 3 / 5;
  grid-row: 2 / 3;
}

De selector nth-of-type() selecteert het zoveelste element in een reeks van dezelfde elementen op hetzelfde niveau. Dat zijn hier het tweede en derde element article.

Je ziet boven de sectie met de foto’s geen kop. Toch is die er wel in de HTML-code. De kop is onzichtbaar gemaakt, maar is wel beschikbaar voor screenreaders (voorleessoftware). Een bezoeker kan met een screenreader door de koppen bladeren en zo vergroot je de toegankelijkheid van de pagina. In de CSS-code voor de klasse .visually-hidden zie je dat de kop absoluut gepositioneerd is. Daardoor is het geen rasteritem meer.

Nu hoeven we alleen nog .latest en .trending in de goede kolommen en rijen te plaatsen.

.latest {
  grid-column: 1 / 5;
  grid-row: 3 / 4; 
} 
.trending {
  grid-column: 1 / 5;
  grid-row: 4 / 5; 
}

De weergave op telefoon is klaar. Op naar het eerste breekpunt.

De basis is klaar.

Het breekpunt op 768 pixels

Bij een breedte van 768 pixels verandert de lay-out. Dat is niet geheel toevallig de breedte van een iPad in portretstand. Wat niet betekent dat je rekening moet proberen te houden met de afmetingen van elk denkbaar apparaat. Kijk vooral naar hoe je ontwerp past in de ruimte en benut de ruimte ook.

De weergave vanaf een breedte van 768 pixels.

Op een breekpunt kun je andere CSS-code activeren. Je maakt een breekpunt met een media query. In een media query geef je voorwaarden aan. Als daaraan wordt voldaan, wordt de CSS-code in de media query gebruikt. Zo niet, dan geldt de oorspronkelijke CSS. Een instelling die gelijk blijft hoef je in de media query niet te herhalen.

De volgende media query geldt voor beeldscherm en de viewport (venster) is minimaal 768 pixels breed.

@media screen and (min-width: 768px) {
  main {
    grid-template-columns: repeat(3, 1fr) 26%;
  }
  .feature.col2 {
    grid-column: 1 / 4;
    grid-row: 1 / 3;
  }
  .feature:nth-of-type(2) {
    grid-column: 4 / 5;
    grid-row: 1 / 2;
  }
  .feature:nth-of-type(3) {
    grid-column: 4 / 5;
    grid-row: 2 / 3;
  }
}

Vanaf 768 pixels staan de kleine foto’s naast de grote. De breedte van de rechterkolom wordt beperkt tot 26%. Daarom wordt op main een nieuwe template voor kolommen ingesteld. De rijen blijven hetzelfde.

De grote foto wordt beperkt tot drie kolommen, maar overspant nu wel twee rijen. De kleine foto’s komen in kolom 4, in rij 1 en in rij 2.

De secties .latest en .trending staan er nog steeds onder, maar dat verandert bij het volgende breekpunt.

Het resultaat op een iPad in portretstand.

Breekpunt op 960 pixels

Bij 960 pixels verandert de lay-out weer. De kleine foto’s gaan terug onder de grote en .latest en .trending komen links en rechts van de foto’s te staan.

@media screen and (min-width: 960px) {
  main {
    grid-template-columns: 
      min(15%, 175px) 1fr 1fr 18.75rem;
  }
  .feature.col2 {
    grid-column: 2 / 4;
    grid-row: 1 / 2;
  }
  .feature:nth-of-type(2) {
    grid-column: 2 / 3;
    grid-row: 2 / 3;
  }
  .feature:nth-of-type(3) {
    grid-column: 3 / 4;
    grid-row: 2 / 3;
  }
  .latest {
    grid-column: 1 / 2;
    grid-row: 1 / 5;
  }
  .trending {
    grid-column: 4 / 5;
    grid-row: 1 / 5;
  }
}

De opvallendste CSS-code zit in de kolomtemplate voor main:

grid-template-columns: min(15%, 175px) 1fr 1fr 18.75rem;

Er worden weer vier kolommen gedefinieerd. Voor kolom 1 is een gloednieuwe CSS-functie gebruikt. Met min(15%, 175px) zeg je: de kolom mag zo breed zijn als 15% van de container, maar niet breder dan 175 pixels. In een rastertemplate kun je ook de functie minmax() gebruiken, waarmee je een minimale en een maximale waarde instelt. Maar een minimale waarde is hier niet nodig. Voordat de kolom te smal kan worden, is er al een andere media query van toepassing.

Nadat ook kolom 4 zijn breedte van 18,75rem heeft ingenomen (1 rem = de standaardtekstgrootte van html = 16 pixels), krijgen de kolommen 2 en 3 elk de helft van de ruimte die overblijft. Daardoor worden de twee kleine foto’s weer even groot weergegeven onder de grote foto.

De weergave vanaf 960 pixels.

Laatste breekpunt op 1100 pixels

Tijd voor de grote finale. Vanaf 1100 pixels gaan alle registers open. De secties komen in vier kolommen naast elkaar.

@media screen and (min-width: 1100px) {
  main {
    grid-template-columns: min(15%, 175px) 1fr 15% 18.75rem;
  }
  .feature.col2 {
    grid-column: 2 / 3;
    grid-row: 1 / 3;
  }
  .feature:nth-of-type(2) {
    grid-column: 3 / 4;
    grid-row: 1 / 2;
  }
  .feature:nth-of-type(3) {
    grid-column: 3 / 4;
    grid-row: 2 / 3;
  }
  .latest {
    grid-column: 1 / 2;
    grid-row: 1 / 5;
  }
  .trending {
    grid-column: 4 / 5;
    grid-row: 1 / 5;
   }
}
Het eindresultaat op volle breedte. Je ziet de rasterlijnen en de tussenruimte (gap).

Opnieuw wordt de kolomtemplate van main aangepast. De breedte van de kolom met de kleine foto’s wordt beperkt tot 15% van de breedte van de container. De resterende ruimte gaat naar de grote foto.

grid-template-columns: min(15%, 175px) 1fr 15% 18.75rem;

Verder hoeven alleen de posities van de onderdelen te worden aangepast. Als je het raster bekijkt, zie je dat twee rijen ook genoeg zijn. Toch is het niet nodig om die template aan te passen. De overbodige rijen blijven gewoon leeg.

De maximale breedte van main is 1300 pixels. Daarboven worden de kolommen niet breder.

Er is meer

Als je tot hier bent gekomen ben je waarschijnlijk geïnteresseerd in CSS. Dan vind je in de code meer leuks dan alleen het raster met een subgrid.

  • Het originele logo van Rolling Stone is een SVG-afbeelding die je natuurlijk niet zomaar mag gebruiken. Dat is hier opgelost door het hetzelfde kleurverloop toe te passen op gewone HTML-tekst.
  • De header is hoger bij een breder scherm, maar wordt vanzelf lager als je scrolt.
  • De rode balk bovenaan de pagina is een pseudo-element van main. Zo kun je content toevoegen zonder extra HTML-elementen.
  • De lijst van meestgelezen artikelen is een zelfgemaakte automatisch genummerde lijst, omdat daarmee meer controle mogelijk is over de opmaak van de nummers. De lijst is gemaakt met flexbox.
  • De kleine uitgelichte artikelen zijn zelf ook weer gebouwd met een raster. Met flexbox kan dat trouwens ook prima.
  • In de footer zie je hoe eenvoudig je met flexbox een element centreert.

Je kunt al deze code bekijken en bewerken op CodePen.

Geef een reactie

Deze website gebruikt Akismet om spam te verminderen. Bekijk hoe je reactie-gegevens worden verwerkt.