🎨CSS
Zelfstudie met uitleg, live voorbeelden en oefeningen: van je eerste kleurtje tot een volledig opgemaakte, responsieve pagina met Flexbox en Grid.
Overzicht
Werk de onderdelen hieronder in je eigen tempo af: lees de uitleg, doe het opzoekwerk en sluit af met een quizje. Klik een onderdeel open om te starten.
Van kale HTML naar een mooie pagina: hoe CSS werkt, hoe je een regel schrijft en op welke manieren je CSS aan je pagina koppelt.
Wat is CSS?
CSS staat voor Cascading Style Sheets. Waar HTML de inhoud en structuur van een pagina beschrijft, bepaalt CSS het uitzicht: kleuren, lettertypes, marges, de plaats van elementen en zelfs animaties.
Zonder CSS ziet elke pagina eruit zoals in 1995: zwarte tekst op een witte achtergrond. Met CSS krijgt ze karakter, en dat zonder je HTML aan te passen. Eén stylesheet kan het uitzicht van een héle website tegelijk bepalen.
“Cascading” betekent “trapsgewijs”. Meerdere regels kunnen op hetzelfde element van toepassing zijn, en CSS heeft vaste afspraken over welke regel wint. Dat leer je in het hoofdstuk over de cascade.
De opbouw van een CSS-regel
CSS bestaat uit regels. Elke regel zegt: kies deze elementen en geef ze deze eigenschappen.
stijl.cssh1 {
color: blue;
font-size: 32px;
}| Onderdeel | In het voorbeeld | Betekenis |
|---|---|---|
| Selector | h1 | welke elementen je opmaakt |
| Declaratieblok | { … } | alle opmaak tussen accolades |
| Eigenschap (property) | color | wát je wijzigt |
| Waarde | blue | hoe je het wijzigt |
Eigenschap en waarde staan gescheiden door een dubbele punt. Elke declaratie eindigt met een puntkomma.
Een vergeten ; of } laat de browser de volgende regel negeren, zonder foutmelding. Krijg je een regel maar niet aan de praat? Zoek eerst naar een ontbrekende puntkomma of accolade in de regel erboven.
Drie manieren om CSS toe te voegen
1. Extern (in een apart bestand) ← zo doen wij het altijd. Je koppelt het bestand in de head met <link>:
index.html<head>
<link rel="stylesheet" href="css/stijl.css">
</head>2. Intern: in de pagina zelf, in een <style>-element in de head. Handig voor een snel proefje, of als je één pagina hebt.
<head>
<style>
h1 { color: blue; }
</style>
</head>3. Inline: rechtstreeks bij één element met het style-attribuut. Zonder selector en zonder accolades.
<p style="color: blue; font-size: 20px;">Deze alinea is blauw.</p>| Extern | Intern | Inline | |
|---|---|---|---|
| Hergebruik op meerdere pagina’s | ✅ | ❌ | ❌ |
| Eén plek om aan te passen | ✅ | ❌ | ❌ |
| Snel testen | ➖ | ✅ | ✅ |
| Aanbevolen voor projecten | ja | nee | bijna nooit |
Zet CSS in een extern bestand: dan blijft je HTML kort en leesbaar, en verander je het uitzicht van de hele site op één plek. In de "Probeer zelf"-blokken hier gebruiken we een <style> omdat er maar één pagina is.
Commentaar en witruimte
Commentaar schrijf je tussen /* en */. De browser negeert het. Witruimte (spaties, enters) maakt voor CSS niet uit, dus zet elke declaratie op een eigen regel en spring in: dat is veel leesbaarder.
/* ---------- Titels ---------- */
h1 {
color: navy; /* donkerblauw */
text-align: center;
} Hoe werkt het samen met HTML?
CSS zoekt in je HTML de elementen die bij de selector passen en geeft ze de eigenschappen. Daarom zijn id en class uit de HTML-cursus zo belangrijk: dat zijn de haakjes waaraan je CSS zich vasthangt (zie volgend hoofdstuk).
Zo verwerkt de browser je paginaBrowser laadt index.html
└─ leest <link rel="stylesheet" href="css/stijl.css">
└─ laadt stijl.css
└─ past elke regel toe op de passende elementenBij de oefeningen typ je enkel CSS. De HTML is al voorzien en met ▶ Voorbeeld zie je meteen wat je CSS doet. Controleer kijkt na of je de gevraagde regels geschreven hebt.
Verwerk wat je hierboven las met de onderdelen hieronder. Ze horen bij deze theorie.
🧪 Oefeningen — Wat is CSS?
Typ je code in het vak en klik op "Controleer". Je code wordt nagekeken op de vereiste onderdelen (waar een Voorbeeld-knop staat, kan je je pagina ook meteen bekijken). Je code wordt bewaard als je aangemeld bent.
Schrijf twee regels: alle h1 worden rood (color: red) en alle p krijgen een lettergrootte van 18px (font-size).
Maak één regel voor body met een lichtgele achtergrond (background-color: lightyellow) en het lettertype Arial, sans-serif (font-family). Maak een tweede regel: h1 wordt gecentreerd (text-align: center). Voeg boven de regels een commentaar toe.
Schrijf een stukje HTML met een <head> en <body>. In de head: (1) een <link> naar het stylesheet css/stijl.css en (2) een <style> met een regel die de h1 blauw maakt. In de body: een <h1> en een <p> met een inline stijl die de tekst groen maakt.
🔍 Opzoekwerk — Wat is CSS?
Zoek het antwoord zelf op (internet, cursus, ...) en typ het hieronder. Wordt automatisch bewaard.
Tip: zoek naar "history of CSS Håkon Wium Lie".
✓ opgeslagenTip: de HTML is bij elk ontwerp hetzelfde, enkel de CSS verschilt.
✓ opgeslagen✅ Testjezelf-quiz — Wat is CSS?
Beantwoord alle vragen en klik daarna op "Controleer". Je mag zo vaak opnieuw proberen als je wil.
Met een selector kies je precies welke elementen je opmaakt: op naam, klasse, id, positie of toestand.
Element-, klasse- en id-selectors
De drie basis-selectors kies je op basis van de HTML:
| Selector | Schrijfwijze | Kiest |
|---|---|---|
| Element | p | alle <p>-elementen |
| Klasse | .tip | alle elementen met class="tip" |
| Id | #hoofdtitel | het ene element met id="hoofdtitel" |
p { color: gray; } /* alle alinea's */
.tip { background: #fef9c3; } /* alles met class="tip" */
#hoofdtitel { font-size: 40px; } /* het element met id="hoofdtitel" */Kies in CSS bij voorkeur klassen: je kan ze hergebruiken en ze zijn makkelijker te overschrijven. Bewaar id’s vooral voor JavaScript en ankers. Onthoud: een punt voor een klasse, een hekje voor een id.
Groeperen en combineren
Je kan selectors combineren om nauwkeuriger te kiezen:
| Schrijfwijze | Naam | Kiest |
|---|---|---|
h1, h2, h3 | groep | alle h1, h2 én h3 (één regel voor meerdere selectors) |
nav a | afstammeling | alle a die ergens binnen een nav staan |
ul > li | kind | enkel li die rechtstreeks in een ul staan |
h1 + p | buur | de p die meteen na een h1 komt |
p.tip | element én klasse | enkel p mét class="tip" (geen spatie!) |
* | universeel | alle elementen |
nav a (met spatie) = een a in een nav. p.tip (zonder spatie) = een p die zelf de klasse tip heeft.
Pseudo-klassen: toestanden
Een pseudo-klasse (met een dubbele punt) kiest een element in een bepaalde toestand of positie:
| Pseudo-klasse | Betekenis |
|---|---|
a:hover | de muis staat erop |
input:focus | het veld is actief (cursor erin) |
button:disabled | de knop is uitgeschakeld |
li:first-child | de eerste li in zijn ouder |
li:last-child | de laatste li in zijn ouder |
li:nth-child(2n) | elke tweede li (2, 4, 6, …): handig voor zebrastrepen |
input:checked | een aangevinkte checkbox of radio |
Attribuut-selectors en pseudo-elementen
Met attribuut-selectors kies je op basis van een attribuut in de HTML:
input[type="text"] { border: 2px solid gray; } /* enkel tekstvelden */
a[href^="https"] { color: green; } /* links die met https beginnen */
a[target="_blank"] { font-style: italic; }Pseudo-elementen (met een dubbele dubbele punt) kiezen een deel van een element, of voegen zelf inhoud toe:
p::first-letter { font-size: 200%; } /* de eerste letter */
p::first-line { font-weight: bold; }
.nieuw::before { content: "🆕 "; } /* voegt tekst vóór het element toe */
.extern::after { content: " ↗"; } Verwerk wat je hierboven las met de onderdelen hieronder. Ze horen bij deze theorie.
🧪 Oefeningen — Selectors: kies je elementen
Typ je code in het vak en klik op "Controleer". Je code wordt nagekeken op de vereiste onderdelen (waar een Voorbeeld-knop staat, kan je je pagina ook meteen bekijken). Je code wordt bewaard als je aangemeld bent.
Schrijf twee regels: (1) alle elementen met de klasse tip krijgen een lichtblauwe achtergrond (background-color: lightblue); (2) het element met id hoofdtitel wordt oranje (color: orange).
(1) Geef h1 én h2 in één regel (met een komma) de kleur navy. (2) Zet enkel de links in de nav op text-decoration: none. (3) Maak enkel de rechtstreekse kinderen van de ul color: green (met de kindselector >).
(1) Laat een link rood worden bij hover (a:hover, color: red). (2) Geef een tekstveld dat actief is (input:focus) een oranje outline (outline: 2px solid orange). (3) Geef elke even li (li:nth-child(even)) een grijze achtergrond (background-color: #eee).
🔍 Opzoekwerk — Selectors: kies je elementen
Zoek het antwoord zelf op (internet, cursus, ...) en typ het hieronder. Wordt automatisch bewaard.
Tip: zoek naar "CSS Diner".
✓ opgeslagenTip: developer.mozilla.org -> :nth-child().
✓ opgeslagen✅ Testjezelf-quiz — Selectors: kies je elementen
Beantwoord alle vragen en klik daarna op "Controleer". Je mag zo vaak opnieuw proberen als je wil.
Kleurnamen, hex, rgb en hsl; achtergrondkleuren, afbeeldingen en kleurverlopen.
Tekstkleur en achtergrondkleur
Twee eigenschappen gebruik je voortdurend:
color: de kleur van de tekst (en van randen die geen eigen kleur hebben);background-color: de kleur van de achtergrond.
body {
background-color: #f8fafc;
color: #1e293b;
}Lichtgrijze tekst op een witte achtergrond is moeilijk leesbaar, zeker voor slechtzienden. Streef naar een contrastverhouding van minstens 4,5 : 1 (test op een contrastchecker).
Kleuren schrijven: vier notaties
| Notatie | Voorbeeld | Uitleg |
|---|---|---|
| Naam | tomato | ±140 kleurnamen (red, navy, gold, lightblue, …) |
| Hex | #3b82f6 | #RRGGBB in hexadecimaal; korte vorm #38f kan ook |
| rgb() | rgb(59, 130, 246) | rood, groen, blauw: elk 0 tot 255 |
| rgba() | rgba(0, 0, 0, 0.5) | rgb + doorzichtigheid (0 = onzichtbaar, 1 = volledig) |
| hsl() | hsl(217, 91%, 60%) | tint (0–360°), verzadiging en helderheid: handig om varianten te maken |
Ze geven allemaal dezelfde soort resultaat, dus kies de notatie die je het handigst vindt. In ontwerpen (Figma) krijg je meestal een hex-code: die kopieer je gewoon.
Met hsl() maak je makkelijk een lichtere of donkerdere versie van dezelfde kleur: verander enkel het laatste getal (helderheid): hsl(217, 91%, 30%) is donker, hsl(217, 91%, 90%) is heel licht.
Achtergrondafbeeldingen
Met background-image zet je een afbeelding achter een element. Met een paar extra eigenschappen bepaal je hoe:
.hero {
background-image: url("../img/strand.jpg");
background-size: cover; /* vul het hele vlak, snij bij indien nodig */
background-position: center; /* waar de afbeelding staat */
background-repeat: no-repeat; /* niet herhalen */
height: 300px; /* zonder hoogte is het element mogelijk leeg */
}| Eigenschap | Waarden |
|---|---|
background-size | cover (vullen), contain (helemaal zichtbaar), of een afmeting |
background-repeat | repeat (standaard), no-repeat, repeat-x |
background-position | center, top, left bottom, … |
Een pad in url() is relatief ten opzichte van het CSS-bestand, niet van de HTML-pagina. Staat je CSS in css/stijl.css en je foto in img/, dan schrijf je ../img/foto.jpg.
Kleurverlopen
Een verloop (gradient) is een achtergrond die van de ene kleur naar de andere overgaat, zonder afbeelding. Je zet het in background of background-image:
.banner {
background: linear-gradient(to right, #3b82f6, #8b5cf6);
}
.cirkel {
background: radial-gradient(circle, yellow, orange);
}Bij linear-gradient geef je een richting (to right, to bottom, 45deg) en daarna twee of meer kleuren.
Doorzichtigheid: opacity
Met opacity (0 tot 1) maak je een heel element doorzichtig, inclusief tekst en kinderen. Wil je enkel de achtergrond doorzichtig maken en de tekst leesbaar houden, gebruik dan rgba() in background-color.
.vervaagd { opacity: 0.4; } /* alles 40% zichtbaar */
.glas { background-color: rgba(255, 255, 255, 0.6); } /* enkel de achtergrond */ Verwerk wat je hierboven las met de onderdelen hieronder. Ze horen bij deze theorie.
🧪 Oefeningen — Kleuren en achtergronden
Typ je code in het vak en klik op "Controleer". Je code wordt nagekeken op de vereiste onderdelen (waar een Voorbeeld-knop staat, kan je je pagina ook meteen bekijken). Je code wordt bewaard als je aangemeld bent.
Geef de titels elk een kleur in een andere notatie: h1 met een naam (bv. crimson), h2 met een hex-code (bv. #3b82f6), h3 met rgb() en de alinea p met hsl(). Alles via color.
Maak voor .banner: een lineair verloop naar rechts (linear-gradient(to right, …)) van #3b82f6 naar #8b5cf6, witte tekstkleur (color: white) en padding: 30px. Geef .glas een halfdoorzichtige zwarte achtergrond met rgba(0, 0, 0, 0.5) en witte tekst.
Geef .hero een achtergrondafbeelding ../img/strand.jpg (met url()), laat ze het vlak vullen (background-size: cover), gecentreerd (background-position: center) en niet herhalen (no-repeat). Geef het een hoogte van 300px en een grijze achtergrondkleur (#ddd) voor als de foto niet laadt.
🔍 Opzoekwerk — Kleuren en achtergronden
Zoek het antwoord zelf op (internet, cursus, ...) en typ het hieronder. Wordt automatisch bewaard.
Tip: zoek naar "color palette generator".
✓ opgeslagenTip: zoek naar "WebAIM contrast checker".
✓ opgeslagen✅ Testjezelf-quiz — Kleuren en achtergronden
Beantwoord alle vragen en klik daarna op "Controleer". Je mag zo vaak opnieuw proberen als je wil.
Lettertypes kiezen, groottes en gewicht, regelafstand, uitlijning en het opmaken van links.
Het lettertype kiezen: font-family
Met font-family kies je het lettertype. Je geeft altijd een lijstje: de browser probeert ze van links naar rechts, en het laatste is een generieke familie als reserve.
body {
font-family: "Segoe UI", Arial, sans-serif;
}
h1 {
font-family: Georgia, "Times New Roman", serif;
}
code {
font-family: Consolas, monospace;
}| Generieke familie | Kenmerk |
|---|---|
serif | met staartjes (Times, Georgia): klassiek |
sans-serif | zonder staartjes (Arial, Helvetica): modern, goed leesbaar op scherm |
monospace | elke letter even breed: voor code |
Lettertypenamen met een spatie zet je tussen aanhalingstekens ("Times New Roman"), namen zonder spatie niet.
Eigen lettertypes met Google Fonts
Niet elke bezoeker heeft jouw lettertype geïnstalleerd. Met Google Fonts laad je een lettertype van het internet in. Kies er een op fonts.google.com, en kopieer de <link> naar je head:
in de <head> van je HTML<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap" rel="stylesheet">Daarna gebruik je het gewoon in je CSS, met een reserve-lettertype:
body {
font-family: "Poppins", sans-serif;
}Gebruik hoogstens twee lettertypes op een site (bv. één voor titels, één voor tekst) en laad enkel de gewichten die je nodig hebt (400 en 700). Zo blijft je pagina snel.
Grootte, gewicht en stijl
| Eigenschap | Voorbeelden |
|---|---|
font-size | 16px, 1.25rem, 120% |
font-weight | normal, bold, of 100 tot 900 (400 = normaal, 700 = vet) |
font-style | normal, italic |
font | verkorte schrijfwijze: font: italic 700 18px/1.5 Arial, sans-serif; |
Koppen zijn standaard al groter en vet. Wil je ze anders, dan pas je ze aan met deze eigenschappen; maar kies nog altijd de juiste HTML-kop (h1, h2, …) voor de betekenis.
Uitlijning, regelafstand en versiering
| Eigenschap | Waarden en uitleg |
|---|---|
text-align | left, center, right, justify |
line-height | regelafstand: 1.6 (zonder eenheid = 1,6 × de lettergrootte); zorgt voor leesbare tekst |
text-decoration | none, underline, line-through |
text-transform | uppercase, lowercase, capitalize |
letter-spacing | ruimte tussen letters, bv. 2px |
text-shadow | schaduw: 2px 2px 4px gray (x, y, vervaging, kleur) |
Geef doorlopende tekst een line-height tussen 1.4 en 1.7: dat leest veel prettiger dan de standaardafstand. Gebruik geen eenheid, dan schaalt het mee met de lettergrootte.
Links opmaken
Een link heeft meerdere toestanden, elk met een eigen pseudo-klasse. Schrijf ze in deze volgorde (LoVe HAte): anders overschrijft een regel de andere.
a:link { color: royalblue; } /* nog niet bezocht */
a:visited { color: purple; } /* al bezocht */
a:hover { color: crimson; } /* muis erop */
a:active { color: red; } /* ingedrukt */In de praktijk schrijf je vaak gewoon a en a:hover. Wil je het onderstreepte weg (bijvoorbeeld in een menu), gebruik dan text-decoration: none.
a {
color: royalblue;
text-decoration: none;
}
a:hover {
text-decoration: underline;
} Lijsten opmaken
Met list-style verander je de opsommingstekens: list-style: none haalt ze weg (nodig voor een menu), square, circle en decimal kunnen ook. Bij menu’s haal je meestal ook de standaardruimte weg met padding: 0 en margin: 0.
nav ul {
list-style: none;
margin: 0;
padding: 0;
} Verwerk wat je hierboven las met de onderdelen hieronder. Ze horen bij deze theorie.
🧪 Oefeningen — Tekst en lettertypes
Typ je code in het vak en klik op "Controleer". Je code wordt nagekeken op de vereiste onderdelen (waar een Voorbeeld-knop staat, kan je je pagina ook meteen bekijken). Je code wordt bewaard als je aangemeld bent.
Maak voor body: lettertype Georgia, serif, lettergrootte 18px en regelafstand 1.6 (zonder eenheid). Maak h1 gecentreerd en hoofdletters (text-transform: uppercase).
Maak het menu: de lijst in de nav (nav ul) krijgt list-style: none, margin: 0 en padding: 0. De links in de nav (nav a) krijgen kleur #1e40af, text-decoration: none en font-weight: bold. Bij hover (nav a:hover) worden ze onderstreept.
Geef .titel: font-size: 40px, letter-spacing: 3px en een text-shadow: 2px 2px 4px gray. Geef .oud: text-decoration: line-through en color: gray.
🔍 Opzoekwerk — Tekst en lettertypes
Zoek het antwoord zelf op (internet, cursus, ...) en typ het hieronder. Wordt automatisch bewaard.
Tip: zoek naar "font pairing" voor inspiratie.
✓ opgeslagenTip: zoek naar "web safe fonts CSS font stack".
✓ opgeslagen✅ Testjezelf-quiz — Tekst en lettertypes
Beantwoord alle vragen en klik daarna op "Controleer". Je mag zo vaak opnieuw proberen als je wil.
Elk element is een doos: inhoud, binnenmarge, rand en buitenmarge. Wie het boxmodel begrijpt, begrijpt CSS-layout.
Elk element is een doos
Voor CSS is elk HTML-element een rechthoekige doos, opgebouwd uit vier lagen, van binnen naar buiten:
Het boxmodel┌──────────────────────── margin ─────────────────────────┐
│ ┌──────────────────── border ─────────────────────┐ │
│ │ ┌───────────────── padding ────────────────┐ │ │
│ │ │ │ │ │
│ │ │ content (tekst, afbeelding) │ │ │
│ │ │ │ │ │
│ │ └───────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘| Laag | Eigenschap | Uitleg |
|---|---|---|
| Content | width, height | de eigenlijke inhoud |
| Padding | padding | binnenmarge: ruimte tussen inhoud en rand (heeft de achtergrondkleur van het element) |
| Border | border | de rand rond de padding |
| Margin | margin | buitenmarge: ruimte tussen dit element en andere elementen (altijd doorzichtig) |
Wil je ruimte binnen het vlak (tekst die niet tegen de rand plakt)? Padding. Wil je ruimte tussen twee vlakken? Margin.
Padding en margin schrijven
Je kan één waarde voor alle vier de zijden geven, of ze apart instellen. Bij meerdere waarden ga je met de wijzers van de klok: boven, rechts, onder, links.
padding: 10px; /* alle vier de zijden */
padding: 10px 20px; /* boven en onder 10px, links en rechts 20px */
padding: 10px 20px 30px; /* boven 10, links/rechts 20, onder 30 */
padding: 10px 20px 30px 40px; /* boven, rechts, onder, links */
padding-top: 10px; /* of één zijde apart */
margin-left: 50px;Dezelfde schrijfwijze werkt voor margin. Bij margin kan je ook auto gebruiken: margin: 0 auto; centreert een blok horizontaal, mits het een vaste width heeft.
Randen en afgeronde hoeken
De verkorte eigenschap border bevat drie dingen: dikte, stijl en kleur.
border: 2px solid #1e40af; /* dikte stijl kleur */
border-bottom: 1px dashed gray; /* enkel de onderkant */
border-radius: 8px; /* afgeronde hoeken */
border-radius: 50%; /* een cirkel (bij een vierkant) */Stijlen: solid (lijn), dashed (streepjes), dotted (puntjes), none (geen). Zonder stijl verschijnt er geen rand, ook al geef je een dikte en kleur.
box-sizing: de grote valkuil
Geef je een element width: 200px en padding: 20px plus een rand van 5px, hoe breed is het dan? Standaard 430px (200 + 2×20 + 2×5): padding en rand komen bovenop de breedte! Dat rekent lastig.
Met box-sizing: border-box tellen padding en rand mee in de breedte: het element is dan echt 200px breed. Bijna elke ontwikkelaar zet daarom onderaan zijn stylesheet-begin:
bovenaan elk stylesheet*, *::before, *::after {
box-sizing: border-box;
}Zet box-sizing: border-box altijd op alle elementen. Zonder dit past een element met width: 100% en padding niet meer in zijn ouder en loopt de pagina horizontaal uit.
Schaduw en overloop
Een schaduw geeft diepte: box-shadow: x y vervaging kleur.
.kaart {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); /* zacht, onderaan */
}Wat als de inhoud groter is dan de doos? Met overflow bepaal je wat er gebeurt: visible (standaard, loopt eruit), hidden (afgesneden), scroll / auto (schuifbalk).
Met max-width laat je een element meegroeien maar niet breder dan een grens (bv. tekst die niet over de volledige breedte van een groot scherm loopt). Ook min-width, min-height en max-height bestaan.
Verwerk wat je hierboven las met de onderdelen hieronder. Ze horen bij deze theorie.
🧪 Oefeningen — Het boxmodel
Typ je code in het vak en klik op "Controleer". Je code wordt nagekeken op de vereiste onderdelen (waar een Voorbeeld-knop staat, kan je je pagina ook meteen bekijken). Je code wordt bewaard als je aangemeld bent.
Maak .kaart met: een width van 300px, een padding van 20px, een rand 2px solid #cbd5e1, afgeronde hoeken van 8px en een margin waarmee de kaart gecentreerd wordt: 20px auto.
(1) Zet box-sizing: border-box op alle elementen met de selector * (voeg ook *::before en *::after toe). (2) .ouder krijgt width: 300px en een rand 3px solid black. (3) .kind krijgt width: 100%, padding: 15px en een achtergrond lightgreen.
Maak .knop: achtergrond #2563eb, tekstkleur white, padding: 10px 24px, border: none, border-radius: 6px en een schaduw box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3). Bij hover (.knop:hover) wordt de achtergrond #1d4ed8.
🔍 Opzoekwerk — Het boxmodel
Zoek het antwoord zelf op (internet, cursus, ...) en typ het hieronder. Wordt automatisch bewaard.
Tip: de gekleurde doos toont padding (groen) en margin (oranje).
✓ opgeslagenTip: zoek naar "margin collapse CSS".
✓ opgeslagen✅ Testjezelf-quiz — Het boxmodel
Beantwoord alle vragen en klik daarna op "Controleer". Je mag zo vaak opnieuw proberen als je wil.
px, %, em, rem, vw en vh: welke eenheid gebruik je waarvoor? Zo schaal je pagina’s mee met elk scherm.
Absolute en relatieve eenheden
Bij afmetingen (lettergrootte, breedte, marges, …) kies je een eenheid. Die zijn twee soorten:
- Absoluut: altijd even groot. Enkel
px(pixel) is daarvan nuttig op scherm. - Relatief: afhankelijk van iets anders (de ouder, de lettergrootte of het scherm). Die zorgen voor pagina’s die zich aanpassen.
| Eenheid | Relatief aan | Gebruik voor |
|---|---|---|
px | niets (vast) | randen, schaduwen, kleine details |
% | de ouder | breedtes: width: 50% |
em | de lettergrootte van het element zelf (of zijn ouder) | marges en padding die met de tekst meeschalen |
rem | de lettergrootte van de root (html, standaard 16px) | lettergroottes en algemene afstanden |
vw / vh | 1% van de breedte / hoogte van het scherm | volledige schermhoogte: height: 100vh |
rem: de beste keuze voor tekst
Standaard is 1rem gelijk aan 16px. Schrijf je lettergroottes in rem, dan schalen ze mee als een bezoeker in zijn browser een grotere tekstgrootte kiest (belangrijk voor slechtzienden). Met pixels gebeurt dat niet.
body { font-size: 1rem; } /* 16px */
h1 { font-size: 2.5rem; } /* 40px */
h2 { font-size: 1.75rem; } /* 28px */
small { font-size: 0.875rem; } /* 14px */1rem = 16px, dus 24px = 1.5rem, 20px = 1.25rem, 12px = 0.75rem. Deel het aantal pixels door 16.
Procenten en meegroeiende blokken
Met % laat je een element meegroeien met zijn ouder. Combineer het met max-width voor een meegroeiende maar begrensde container: dat is de basis van een goede pagina.
.container {
width: 90%; /* op een klein scherm: 90% van de breedte */
max-width: 1000px; /* op een groot scherm: nooit breder dan 1000px */
margin: 0 auto; /* gecentreerd */
}
img {
max-width: 100%; /* een afbeelding wordt nooit breder dan haar ouder */
height: auto; /* behoud de verhoudingen */
}De twee regels op img zorgen ervoor dat grote foto’s netjes krimpen op een gsm in plaats van uit het scherm te lopen. Zet ze in elk project!
vw, vh en calc()
vh en vw zijn percentages van het scherm (viewport): 100vh is de volledige schermhoogte, ideaal voor een hero-blok. Met calc() reken je met verschillende eenheden door elkaar:
.hero { height: 100vh; } /* volledige schermhoogte */
.inhoud { width: calc(100% - 250px); } /* alles behalve een zijbalk van 250px */
h1 { font-size: clamp(1.5rem, 5vw, 3rem); } /* meegroeiend, maar tussen 1.5rem en 3rem */Rond + en - in calc() moeten spaties staan: calc(100% - 250px). Zonder spaties werkt het niet.
Verwerk wat je hierboven las met de onderdelen hieronder. Ze horen bij deze theorie.
🧪 Oefeningen — Eenheden en afmetingen
Typ je code in het vak en klik op "Controleer". Je code wordt nagekeken op de vereiste onderdelen (waar een Voorbeeld-knop staat, kan je je pagina ook meteen bekijken). Je code wordt bewaard als je aangemeld bent.
Zet de lettergroottes in rem: h1 = 2.5rem (40px), h2 = 1.75rem (28px), p = 1rem en small = 0.875rem (14px).
Maak .container: width: 90%, max-width: 1000px en gecentreerd (margin: 0 auto). Maak ook afbeeldingen responsief: img met max-width: 100% en height: auto.
(1) Geef .pagina een height van 100vh. (2) .zijbalk krijgt width: 250px en float: left. (3) .inhoud krijgt width: calc(100% - 250px) en float: left. Vergeet de spaties rond de min niet.
🔍 Opzoekwerk — Eenheden en afmetingen
Zoek het antwoord zelf op (internet, cursus, ...) en typ het hieronder. Wordt automatisch bewaard.
Tip: zoek naar "em vs rem CSS".
✓ opgeslagenTip: zoek naar "100vh mobile browser problem dvh".
✓ opgeslagen✅ Testjezelf-quiz — Eenheden en afmetingen
Beantwoord alle vragen en klik daarna op "Controleer". Je mag zo vaak opnieuw proberen als je wil.
Wat als twee regels elkaar tegenspreken? De cascade bepaalt wie wint: leer waarom je CSS soms “niet werkt” en hoe je dat oplost.
Het probleem: conflicterende regels
Meerdere regels kunnen op hetzelfde element van toepassing zijn en elkaar tegenspreken:
HTML<p id="intro" class="tip">Welke kleur ben ik?</p>CSSp { color: blue; }
.tip { color: green; }
#intro { color: red; }De tekst wordt rood. De browser lost het conflict op met drie criteria, in deze volgorde: 1. belangrijkheid (!important), 2. specificiteit en 3. volgorde in het bestand.
Specificiteit: hoe “gericht” is een selector?
Hoe specifieker een selector, hoe zwaarder hij weegt. De rangorde, van zwak naar sterk:
| Soort | Voorbeeld | Gewicht |
|---|---|---|
| Element (en pseudo-element) | p, ::before | laag (0,0,1) |
| Klasse, attribuut, pseudo-klasse | .tip, [type="text"], :hover | middel (0,1,0) |
| Id | #intro | hoog (1,0,0) |
| Inline style | style="…" | nog hoger |
!important | color: red !important; | wint bijna altijd |
Je telt het aantal id’s, klassen en elementen in de selector. Eén id wint van duizend klassen, en één klasse wint van duizend elementen:
Specificiteit tellenp → (0,0,1)
.tip → (0,1,0) wint van p
p.tip → (0,1,1) wint van .tip
nav ul li a → (0,0,4)
.menu a:hover → (0,2,1)
#intro → (1,0,0) wint van alle voorgaande Bij gelijke specificiteit: de laatste wint
Hebben twee regels evenveel gewicht, dan wint de regel die het laatst in het stylesheet staat (of het laatst geladen wordt).
.knop { background: blue; }
.knop { background: red; } /* deze wint: hij staat onderaan */Schrijf algemene regels bovenaan (element-selectors), daaronder specifiekere (klassen). Dan hoef je zelden tegen de specificiteit te vechten.
Overerving (inheritance)
Sommige eigenschappen worden doorgegeven van een ouder aan zijn kinderen, zodat je ze niet overal moet herhalen. Typisch tekst-eigenschappen: color, font-family, font-size, line-height, text-align.
body {
font-family: Arial, sans-serif; /* alle tekst op de pagina erft dit */
color: #333;
}Eigenschappen zoals border, margin, padding en background worden niet geërfd (logisch: als een doos een rand krijgt, wil je niet dat elk kind ook een rand krijgt).
Met de waarde inherit dwing je overerving af, met initial zet je terug naar de standaardwaarde. Bijvoorbeeld: knoppen en invoervelden erven het lettertype standaard niet:
button, input, textarea {
font-family: inherit; /* neem het lettertype van de pagina over */
}
a {
color: inherit; /* een link krijgt de tekstkleur van zijn ouder */
} !important: wees voorzichtig
Met !important achter een waarde win je van (bijna) alles. Het is verleidelijk, maar het maakt je CSS onbeheersbaar: het volgende probleem los je enkel op met nóg een !important.
Gebruik !important zo goed als nooit. Is een regel niet van toepassing? Maak je selector specifieker (bv. .menu .knop in plaats van .knop) of verplaats de regel lager in het bestand.
Debuggen met DevTools
Werkt je CSS niet? Open de DevTools (F12), kies Elements, klik op het element en kijk naar het Styles-paneel:
- Regels die het verliezen staan
doorgestreept: dat is de winnende regel die eroverheen gaat; - Je ziet uit welk bestand en welke regel elke declaratie komt;
- Vinkje weg = eigenschap tijdelijk uit: zo test je snel;
- Een ⚠️ gele driehoek naast een eigenschap betekent dat de browser hem niet begrijpt (typfout?).
Je kan waarden rechtstreeks in DevTools aanpassen en meteen het resultaat zien. Dat verdwijnt bij het herladen; kopieer wat werkt naar je stylesheet.
Verwerk wat je hierboven las met de onderdelen hieronder. Ze horen bij deze theorie.
🧪 Oefeningen — De cascade en specificiteit
Typ je code in het vak en klik op "Controleer". Je code wordt nagekeken op de vereiste onderdelen (waar een Voorbeeld-knop staat, kan je je pagina ook meteen bekijken). Je code wordt bewaard als je aangemeld bent.
Onderstaande tekst is rood door het id. Zorg dat ze groen wordt, zonder !important en zonder de bestaande regels te verwijderen: voeg onderaan een regel toe met een specifiekere selector (id én klasse samen: #intro.tip) die color: green instelt.
(1) Zet op body het lettertype Arial, sans-serif en de kleur #333: alle tekst erft dat. (2) Laat links de tekstkleur van hun ouder overnemen: a met color: inherit. (3) Laat knoppen het lettertype van de pagina overnemen: button met font-family: inherit.
Maak enkel de laatste item van het .menu rood (.menu li:last-child, color: red), zonder de lijst .lijst te raken. Zet ook bovenaan een algemene regel voor alle li met list-style: square: algemene regels eerst, specifieke daaronder.
🔍 Opzoekwerk — De cascade en specificiteit
Zoek het antwoord zelf op (internet, cursus, ...) en typ het hieronder. Wordt automatisch bewaard.
Tip: zoek naar "CSS specificity calculator" of "specificity.keegan.st".
✓ opgeslagenTip: zoek naar "why avoid !important CSS".
✓ opgeslagen✅ Testjezelf-quiz — De cascade en specificiteit
Beantwoord alle vragen en klik daarna op "Controleer". Je mag zo vaak opnieuw proberen als je wil.
Blok of inline? Verborgen? Vastgeplakt? Met display en position bepaal je hoe en waar een element in de pagina staat.
display: blok, inline en inline-block
De eigenschap display bepaalt hoe een element zich gedraagt in de stroom van de pagina:
| Waarde | Gedrag |
|---|---|
block | begint op een nieuwe regel, neemt de volle breedte; breedte, hoogte en marges werken (div, p, h1, ul, …) |
inline | loopt mee in de tekst; breedte en hoogte werken niet, verticale marges ook niet (span, a, strong, img) |
inline-block | staat naast elkaar zoals inline, maar breedte, hoogte en marges werken wél |
none | het element wordt volledig verborgen en neemt geen plaats meer in |
flex / grid | een moderne layout-container (volgende hoofdstukken) |
display: none haalt het element weg alsof het er nooit was. visibility: hidden maakt het onzichtbaar maar de plaats blijft leeg. Handig: met JavaScript zet je een klasse aan of uit om iets te tonen of te verbergen.
position: elementen verplaatsen
Met position haal je een element uit de normale stroom of zet je het vast. Daarna schuif je het met top, right, bottom en left.
| Waarde | Werking |
|---|---|
static | standaard: normale stroom; top/left doen niets |
relative | blijft op zijn plaats in de stroom, maar je kan hem schuiven vanaf zijn eigen plaats; dient vooral als referentiepunt voor absolute kinderen |
absolute | uit de stroom; positioneert zich ten opzichte van de dichtstbijzijnde ouder die niet static is (bv. relative) |
fixed | vast ten opzichte van het scherm: blijft staan bij scrollen (bv. een chatknop) |
sticky | gedraagt zich normaal, maar blijft plakken aan de rand van het scherm bij scrollen (bv. een menubalk) |
Het klassieke patroon: relative + absolute
Zo plaats je een badge of sluitknop in de hoek van een kaart: de kaart is relative (referentiepunt), de badge is absolute en schuift vanuit die hoek.
.kaart {
position: relative; /* referentiepunt voor de badge */
}
.badge {
position: absolute; /* uit de stroom, tov .kaart */
top: 8px;
right: 8px;
}Vergeet je position: relative op de ouder, dan positioneert de absolute badge zich ten opzichte van de hele pagina in plaats van van de kaart. Dat is de meest gemaakte fout bij position.
Vast en plakkend: fixed en sticky
header {
position: sticky; /* plakt bovenaan bij scrollen... */
top: 0; /* ...op 0px van de bovenrand */
background: white;
z-index: 10; /* boven de rest van de inhoud */
}
.chat-knop {
position: fixed; /* altijd zichtbaar, ook bij scrollen */
bottom: 20px;
right: 20px;
}Als elementen elkaar overlappen, bepaalt z-index wat bovenaan ligt: het element met het hoogste getal komt voor. Het werkt enkel bij elementen met een position anders dan static (en bij flex- en grid-kinderen).
Verwerk wat je hierboven las met de onderdelen hieronder. Ze horen bij deze theorie.
🧪 Oefeningen — Display en positie
Typ je code in het vak en klik op "Controleer". Je code wordt nagekeken op de vereiste onderdelen (waar een Voorbeeld-knop staat, kan je je pagina ook meteen bekijken). Je code wordt bewaard als je aangemeld bent.
Maak van .tag nette knopjes: display: inline-block, padding: 6px 14px, margin: 4px, achtergrond #dbeafe en border-radius: 999px. Verberg .verborgen helemaal met display: none.
Zet .kaart op position: relative (met width: 240px en padding: 20px, rand 1px solid #ccc). Zet .badge op position: absolute, top: 8px en right: 8px, met achtergrond crimson, witte tekst en padding: 4px 10px.
Maak header plakkend: position: sticky, top: 0, achtergrond #1e293b, witte tekst, padding: 12px en z-index: 10. Maak daarnaast .chat vast in de hoek: position: fixed, bottom: 20px, right: 20px.
🔍 Opzoekwerk — Display en positie
Zoek het antwoord zelf op (internet, cursus, ...) en typ het hieronder. Wordt automatisch bewaard.
Tip: zoek naar "why width doesn't work on span".
✓ opgeslagenTip: zoek naar "z-index not working stacking context".
✓ opgeslagen✅ Testjezelf-quiz — Display en positie
Beantwoord alle vragen en klik daarna op "Controleer". Je mag zo vaak opnieuw proberen als je wil.
De moderne manier om elementen naast of onder elkaar te zetten, uit te lijnen en te centreren: rijen, menu’s en kaartjes worden kinderspel.
Wat is Flexbox?
Flexbox (flexible box) is een layoutsysteem voor één richting: een rij of een kolom. Je zet display: flex op de ouder (de flex-container); de directe kinderen (de flex-items) staan dan automatisch naast elkaar en je regelt hun uitlijning met een paar eigenschappen op de container.
.rij {
display: flex;
}Meer is er niet nodig om drie <div>s naast elkaar te krijgen!
Twee assen: hoofdas en kruisas
Flexbox werkt met twee assen. Dit is de sleutel om het te begrijpen:
Assen in flexboxflex-direction: row (standaard) flex-direction: column
hoofdas ──────────────► kruisas ──────────►
┌───┐ ┌───┐ ┌───┐ kruisas ┌───┐ hoofdas
│ 1 │ │ 2 │ │ 3 │ │ │ 1 │ │
└───┘ └───┘ └───┘ ▼ ├───┤ │
│ 2 │ ▼
└───┘- De hoofdas is de richting waarin de items staan (bij
row: horizontaal). Uitlijnen langs de hoofdas doe je metjustify-content. - De kruisas staat er loodrecht op. Uitlijnen langs de kruisas doe je met
align-items.
Uitlijnen: justify-content en align-items
| Eigenschap | Waarden |
|---|---|
flex-direction | row (standaard), column, row-reverse |
justify-content(hoofdas) | flex-start, center, flex-end, space-between (ruimte tússen), space-around, space-evenly |
align-items(kruisas) | stretch (standaard), center, flex-start, flex-end |
gap | ruimte tussen de items, bv. 16px |
flex-wrap | nowrap (standaard), wrap (naar volgende regel als het niet past) |
Met gap zet je ruimte tussen de items, zonder marges op de kinderen. Veel netter dan marges (want er komt geen extra ruimte aan de buitenkant).
Perfect centreren
Iets horizontaal én verticaal centreren was vroeger een nachtmerrie. Met flexbox zijn het drie regels:
.scherm {
display: flex;
justify-content: center; /* horizontaal (hoofdas) */
align-items: center; /* verticaal (kruisas) */
height: 100vh;
} De items zelf: flex-grow, flex-shrink en flex-basis
Ook de kinderen kan je sturen. De verkorte eigenschap flex bepaalt hoe een item ruimte inneemt:
.item { flex: 1; } /* alle items delen de ruimte gelijk */
.groot { flex: 2; } /* dubbel zoveel ruimte als een item met flex: 1 */
.vast { flex: 0 0 200px; } /* niet groeien, niet krimpen, altijd 200px */
.kaart { flex: 1 1 250px; } /* groeien, krimpen, en begin op 250px */| Deel van flex | Betekenis |
|---|---|
flex-grow | hoeveel van de overblijvende ruimte het item mag opeisen |
flex-shrink | mag het krimpen als er te weinig plaats is? |
flex-basis | de beginbreedte (voor het groeien en krimpen) |
Met align-self lijn je één item anders uit dan de rest, en met order wijzig je de volgorde zonder je HTML aan te passen.
Praktijk: een menubalk en kaartjes
Menubalk: logo links, links rechts, alles verticaal gecentreerd.
nav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
}
nav ul {
display: flex; /* de lijst zelf is ook een flex-container */
gap: 20px;
list-style: none;
margin: 0;
padding: 0;
}Kaartjes die naar een volgende regel gaan als er geen plaats meer is (zonder media-queries!):
.kaarten {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.kaart {
flex: 1 1 220px; /* minstens 220px, groeit om de regel te vullen */
} Verwerk wat je hierboven las met de onderdelen hieronder. Ze horen bij deze theorie.
🧪 Oefeningen — Flexbox
Typ je code in het vak en klik op "Controleer". Je code wordt nagekeken op de vereiste onderdelen (waar een Voorbeeld-knop staat, kan je je pagina ook meteen bekijken). Je code wordt bewaard als je aangemeld bent.
Maak van nav een flex-container met justify-content: space-between en align-items: center (met padding: 12px 24px en achtergrond #e2e8f0). Maak ook de lijst nav ul een flex-container met gap: 20px, list-style: none en margin: 0, padding: 0.
Zet .scherm op display: flex, centreer de inhoud horizontaal (justify-content: center) én verticaal (align-items: center) en geef het een height van 300px en een achtergrond #e0f2fe. Geef .doos een witte achtergrond en padding: 16px 24px.
Maak van .kaarten een flex-container die naar een volgende regel gaat als het niet past (flex-wrap: wrap) en gap: 16px heeft. Elke .kaart krijgt flex: 1 1 200px, padding: 16px en achtergrond #fef9c3.
🔍 Opzoekwerk — Flexbox
Zoek het antwoord zelf op (internet, cursus, ...) en typ het hieronder. Wordt automatisch bewaard.
Tip: zoek naar "Flexbox Froggy".
✓ opgeslagenTip: zoek naar "flexbox vs grid when to use".
✓ opgeslagen✅ Testjezelf-quiz — Flexbox
Beantwoord alle vragen en klik daarna op "Controleer". Je mag zo vaak opnieuw proberen als je wil.
Flexbox werkt in één richting. Grid werkt in rijen én kolommen tegelijk: ideaal voor de indeling van een hele pagina of een galerij.
Wat is Grid?
CSS Grid verdeelt een container in een raster van rijen en kolommen. Net als bij flexbox zet je display: grid op de ouder; de directe kinderen vallen dan in de cellen van het raster.
| Flexbox | Grid |
|---|---|
| één richting (rij of kolom) | twee richtingen (rijen én kolommen) |
| de inhoud bepaalt de layout | de layout bepaalt waar de inhoud komt |
| menu’s, rijen, uitlijnen | pagina-indeling, galerijen, dashboards |
Flexbox en Grid zijn geen concurrenten. Vaak gebruik je Grid voor de grote indeling en Flexbox binnen de onderdelen (een menu, een kaart).
Kolommen maken met grid-template-columns
Met grid-template-columns geef je de breedte van elke kolom op. Handig is de eenheid fr (fractie): een deel van de beschikbare ruimte.
.raster {
display: grid;
grid-template-columns: 1fr 1fr 1fr; /* drie gelijke kolommen */
gap: 16px; /* ruimte tussen rijen en kolommen */
}
/* korter: */
grid-template-columns: repeat(3, 1fr);
/* zijbalk + inhoud: */
grid-template-columns: 250px 1fr; /* 250px vast, de rest voor de inhoud */
grid-template-columns: 1fr 2fr; /* tweede kolom is dubbel zo breed */Rijen ontstaan vanzelf: elke keer als een rij vol zit, begint er een nieuwe. Wil je de hoogte van rijen sturen, dan gebruik je grid-auto-rows (bv. minmax(100px, auto)).
Responsieve kaartjes zonder media queries
Met repeat(auto-fit, minmax(…, 1fr)) maak je een raster dat zelf beslist hoeveel kolommen er passen. Elke kolom is minstens 200px breed en de kolommen vullen samen de rij. Wordt het venster smaller, dan verdwijnen er kolommen.
.galerij {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
}Onthoud dit patroon: het is een responsieve galerij in drie regels, zonder één media query.
Elementen over meerdere cellen
Een kind kan meerdere kolommen of rijen innemen met grid-column en grid-row:
.breed { grid-column: span 2; } /* neemt twee kolommen in */
.hoog { grid-row: span 2; } /* neemt twee rijen in */
.kop { grid-column: 1 / -1; } /* van de eerste tot de laatste kolomlijn: de volledige rij */ Een hele pagina met grid-template-areas
Met grid-template-areas teken je je pagina als ASCII-schets. Elk kind krijgt met grid-area een naam en gaat naar de juiste plek.
.pagina {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"kop kop"
"zijbalk inhoud"
"voet voet";
min-height: 100vh;
}
header { grid-area: kop; }
aside { grid-area: zijbalk; }
main { grid-area: inhoud; }
footer { grid-area: voet; }Zo lees je meteen aan de CSS hoe de pagina eruitziet. Voor een gsm-versie wijzig je in een media query enkel de grid-template-areas (zie volgend hoofdstuk).
Uitlijnen in het raster
Ook Grid kent uitlijn-eigenschappen, met dezelfde namen als bij flexbox: justify-items / align-items (cel-inhoud), justify-content / align-content (het hele raster). Met place-items: center centreer je in één regel alles in zijn cel.
Verwerk wat je hierboven las met de onderdelen hieronder. Ze horen bij deze theorie.
🧪 Oefeningen — CSS Grid
Typ je code in het vak en klik op "Controleer". Je code wordt nagekeken op de vereiste onderdelen (waar een Voorbeeld-knop staat, kan je je pagina ook meteen bekijken). Je code wordt bewaard als je aangemeld bent.
Maak van .raster een grid met drie gelijke kolommen (repeat(3, 1fr)) en een gap van 12px. Geef de cellen (.raster div) een lichtblauwe achtergrond #dbeafe, padding: 16px en gecentreerde tekst.
Maak .galerij een grid dat automatisch het aantal kolommen kiest: grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)) met een gap van 16px. Geef .galerij div een padding: 30px, achtergrond #fef9c3 en border-radius: 8px.
Maak .pagina een grid met kolommen 200px 1fr, een gap van 8px en deze grid-template-areas: rij 1 "kop kop", rij 2 "zijbalk inhoud", rij 3 "voet voet". Wijs daarna met grid-area de vier elementen (header, aside, main, footer) hun gebied toe.
🔍 Opzoekwerk — CSS Grid
Zoek het antwoord zelf op (internet, cursus, ...) en typ het hieronder. Wordt automatisch bewaard.
Tip: zoek naar "CSS Grid Garden".
✓ opgeslagenTip: zoek naar "CSS fr unit vs percentage".
✓ opgeslagen✅ Testjezelf-quiz — CSS Grid
Beantwoord alle vragen en klik daarna op "Controleer". Je mag zo vaak opnieuw proberen als je wil.
Een website moet er goed uitzien op een gsm, een tablet en een groot scherm. Met media queries pas je de opmaak aan de schermbreedte aan.
Waarom responsive?
Meer dan de helft van het webverkeer komt van gsm’s. Een pagina die enkel op een groot scherm werkt, is voor die bezoekers onbruikbaar. Responsive design betekent: één website die zich aanpast aan het scherm van de bezoeker. Drie bouwstenen:
- De viewport-meta in je HTML;
- Flexibele maten (%, rem, max-width, flex/grid) in plaats van vaste pixels;
- Media queries om de layout te wijzigen op bepaalde breedtes.
De viewport-meta
Zonder deze regel in je head denkt een gsm dat je pagina 980px breed is en toont hij een uitgezoomde versie. Zet ze altijd:
in de <head> van elke pagina<meta name="viewport" content="width=device-width, initial-scale=1">Ze zegt: “gebruik de echte breedte van het toestel en zoom niet uit”.
Media queries
Een media query past CSS-regels enkel toe als een voorwaarde klopt, meestal een schermbreedte:
/* enkel op schermen tot 600px breed (gsm) */
@media (max-width: 600px) {
.rij {
flex-direction: column;
}
h1 {
font-size: 1.75rem;
}
}
/* enkel op schermen vanaf 900px breed */
@media (min-width: 900px) {
.container {
width: 80%;
}
}max-width: 600px: geldt tot en met 600px breed;min-width: 900px: geldt vanaf 900px breed;- Binnen de accolades van de query staan gewone CSS-regels, met hun eigen selectors.
Mobile first
De beste aanpak is mobile first: schrijf eerst de opmaak voor de kleinste schermen (zonder media query) en voeg met min-width verbeteringen toe voor grotere schermen.
/* basis: gsm — één kolom */
.kaarten {
display: grid;
gap: 16px;
grid-template-columns: 1fr;
}
/* tablet: twee kolommen */
@media (min-width: 600px) {
.kaarten { grid-template-columns: repeat(2, 1fr); }
}
/* desktop: vier kolommen */
@media (min-width: 1000px) {
.kaarten { grid-template-columns: repeat(4, 1fr); }
}Er zijn geen heilige getallen. Vaak zie je 600px (gsm → tablet), 900–1000px (tablet → laptop) en 1200px (groot scherm). Stel liever een breekpunt in waar je layout stuk gaat dan bij een bepaald toestel.
Handige extra’s
Menu verbergen op een gsm en een menu-knop tonen (met JavaScript eronder):
.menu-knop { display: none; } /* op groot scherm niet nodig */
@media (max-width: 700px) {
.menu-knop { display: block; }
nav ul { display: none; } /* menu verborgen tot je op de knop klikt */
nav ul.open { display: block; } /* JavaScript zet de klasse 'open' aan */
}Donkere modus: volg de voorkeur van de gebruiker:
@media (prefers-color-scheme: dark) {
body {
background: #0f172a;
color: #e2e8f0;
}
}Ook afdrukken kan je aanpassen met @media print (bv. menu’s verbergen). Test altijd op een echt toestel of met de toestelmodus in de DevTools (F12 → icoon met gsm en tablet).
Verwerk wat je hierboven las met de onderdelen hieronder. Ze horen bij deze theorie.
🧪 Oefeningen — Responsive design
Typ je code in het vak en klik op "Controleer". Je code wordt nagekeken op de vereiste onderdelen (waar een Voorbeeld-knop staat, kan je je pagina ook meteen bekijken). Je code wordt bewaard als je aangemeld bent.
Maak .rij een flex-container met gap: 10px; elk kind (.rij div) krijgt flex: 1 en padding: 16px. Zorg met een media query dat de blokken op schermen tot en met 600px onder elkaar staan (flex-direction: column).
Werk mobile first: .kaarten is een grid met gap: 10px en één kolom (grid-template-columns: 1fr). Vanaf 600px (min-width) worden het twee kolommen (repeat(2, 1fr)); vanaf 1000px worden het vier kolommen (repeat(4, 1fr)).
Geef body een lichte basis: achtergrond #ffffff en tekstkleur #0f172a. Voeg een media query voor prefers-color-scheme: dark toe die de body donker maakt: achtergrond #0f172a, tekstkleur #e2e8f0.
🔍 Opzoekwerk — Responsive design
Zoek het antwoord zelf op (internet, cursus, ...) en typ het hieronder. Wordt automatisch bewaard.
Tip: Chrome DevTools -> Toggle device toolbar (Ctrl+Shift+M).
✓ opgeslagenTip: zoek naar "mobile first vs desktop first CSS".
✓ opgeslagen✅ Testjezelf-quiz — Responsive design
Beantwoord alle vragen en klik daarna op "Controleer". Je mag zo vaak opnieuw proberen als je wil.
Laat je pagina tot leven komen: zachte overgangen bij hover, verschuiven, draaien en zelfstandig bewegende animaties, allemaal zonder JavaScript.
Transities: zacht veranderen
Normaal springt een eigenschap meteen naar zijn nieuwe waarde (een knop wordt in één klap rood bij hover). Met een transitie gebeurt de verandering geleidelijk. Je zet de transitie op het element in zijn gewone toestand, de nieuwe waarde zet je in de hover-regel:
.knop {
background-color: #2563eb;
transition: background-color 0.3s ease; /* wat, hoe lang, hoe */
}
.knop:hover {
background-color: #1d4ed8;
}| Onderdeel | Betekenis |
|---|---|
transition-property | welke eigenschap (bv. background-color, of all) |
transition-duration | hoe lang, bv. 0.3s of 300ms |
transition-timing-function | het tempo: ease (standaard), linear, ease-in-out |
transition-delay | wachttijd voor het begint |
Zet transition in .knop en niet in .knop:hover. Dan animeert het ook terug als je de muis wegneemt.
Transform: verschuiven, schalen, draaien
Met transform verplaats je een element zonder de rest van de pagina te beïnvloeden:
| Functie | Effect |
|---|---|
translateX(20px) / translateY(-4px) | verschuiven |
scale(1.1) | vergroten (1 = normaal, 0.5 = half) |
rotate(15deg) | draaien |
translateY(-4px) scale(1.05) | meerdere na elkaar |
Combineer ze met een transitie voor de klassieke “kaart die opveert bij hover”:
.kaart {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.kaart:hover {
transform: translateY(-4px);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
}Een transform verandert de layout niet: andere elementen blijven staan, en de browser animeert het heel vloeiend. Animeer daarom liever transform en opacity dan width of margin.
Animaties met @keyframes
Een transitie gaat van A naar B als er iets gebeurt (hover). Een animatie beweegt uit zichzelf en kan meerdere stappen hebben. In twee stappen:
1. Definieer de animatie met @keyframes en geef ze een naam:
@keyframes pulseer {
0% { transform: scale(1); }
50% { transform: scale(1.15); }
100% { transform: scale(1); }
}2. Pas ze toe met de eigenschap animation: naam, duur, tempo, aantal herhalingen.
.hartje {
animation: pulseer 1s ease-in-out infinite; /* naam duur tempo herhaling */
}Met from en to (of percentages) beschrijf je de stappen. infinite herhaalt eindeloos; een getal (3) herhaalt zo vaak.
Een laadicoon
@keyframes draai {
to { transform: rotate(360deg); }
}
.laden {
width: 40px;
height: 40px;
border: 4px solid #cbd5e1;
border-top-color: #2563eb; /* één gekleurde kant */
border-radius: 50%;
animation: draai 0.8s linear infinite;
} Met mate: toegankelijkheid en prestaties
- Overdrijf niet. Animaties die de aandacht opeisen vermoeien en leiden af. Kort (0,2 tot 0,4 seconden) en subtiel werkt het best.
- Sommige mensen worden onwel van bewegende beelden. Respecteer hun instelling:
@media (prefers-reduced-motion: reduce) {
* {
animation: none !important;
transition: none !important;
}
}Dit is een van de zeldzame plaatsen waar !important verdedigbaar is.
Verwerk wat je hierboven las met de onderdelen hieronder. Ze horen bij deze theorie.
🧪 Oefeningen — Transities en animaties
Typ je code in het vak en klik op "Controleer". Je code wordt nagekeken op de vereiste onderdelen (waar een Voorbeeld-knop staat, kan je je pagina ook meteen bekijken). Je code wordt bewaard als je aangemeld bent.
Maak .knop: achtergrond #2563eb, witte tekst, padding: 12px 24px, border: none, border-radius: 6px, cursor: pointer en een transitie transition: background-color 0.3s ease. Bij hover (.knop:hover) wordt de achtergrond #dc2626.
Geef .kaart: width: 220px, padding: 20px, margin: 20px, witte achtergrond, border-radius: 10px, box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2) en transition: transform 0.2s ease. Bij hover verschuift de kaart 4px omhoog (transform: translateY(-4px)).
Schrijf een animatie @keyframes pulseer die op 0% en 100% transform: scale(1) heeft en op 50% transform: scale(1.3). Pas ze toe op .hartje met animation: pulseer 1s ease-in-out infinite. Zet ook display: inline-block en font-size: 50px op .hartje.
🔍 Opzoekwerk — Transities en animaties
Zoek het antwoord zelf op (internet, cursus, ...) en typ het hieronder. Wordt automatisch bewaard.
Tip: zoek naar "CSS easing functions".
✓ opgeslagenTip: DevTools -> Elements -> Styles zie je transition en animation.
✓ opgeslagen✅ Testjezelf-quiz — Transities en animaties
Beantwoord alle vragen en klik daarna op "Controleer". Je mag zo vaak opnieuw proberen als je wil.
Schrijf onderhoudbare CSS: kleuren en maten één keer definiëren met variabelen, een reset gebruiken en je stylesheet netjes opbouwen.
Het probleem: herhaling
Stel: de hoofdkleur van je site is #2563eb en je gebruikt ze op 30 plaatsen. Wil je morgen een andere kleur, dan moet je 30 keer zoeken en vervangen. Ook lastig: welke blauwtint was het ook alweer?
De oplossing zijn CSS-variabelen (officieel custom properties): je definieert een waarde één keer en gebruikt ze overal.
Variabelen maken en gebruiken
Een variabele begint met twee streepjes. Je zet ze meestal in :root (het hoogste element, zodat ze overal beschikbaar zijn) en gebruikt ze met var():
:root {
--kleur-primair: #2563eb;
--kleur-tekst: #1e293b;
--kleur-achtergrond: #f8fafc;
--ruimte: 16px;
--straal: 8px;
}
body {
color: var(--kleur-tekst);
background-color: var(--kleur-achtergrond);
}
.knop {
background-color: var(--kleur-primair);
padding: var(--ruimte);
border-radius: var(--straal);
}- Namen zijn vrij te kiezen maar beginnen met
--; kies een duidelijke naam (hoofdlettergevoelig). var(--naam, reserve)laat je een reservewaarde opgeven voor als de variabele niet bestaat.- Variabelen kunnen ook binnen een selector staan en gelden dan enkel daar.
Thema’s: een donkere modus met variabelen
Omdat variabelen overschreven kunnen worden, zijn ze ideaal voor thema’s. Je gebruikt overal var(...) en wisselt enkel de waarden:
:root {
--achtergrond: #ffffff;
--tekst: #0f172a;
}
.donker {
--achtergrond: #0f172a;
--tekst: #e2e8f0;
}
body {
background: var(--achtergrond);
color: var(--tekst);
}Zet je met JavaScript de klasse donker op de <body>, dan wisselen alle kleuren in één keer. Ook Bootstrap 5 werkt zo achter de schermen.
Een reset: gelijke startpunten
Elke browser heeft eigen standaardstijlen (marges op body, grootte van koppen, …). Veel ontwikkelaars beginnen hun stylesheet met een korte reset zodat alles overal hetzelfde start:
bovenaan stijl.css*, *::before, *::after {
box-sizing: border-box;
}
body {
margin: 0;
font-family: system-ui, sans-serif;
line-height: 1.6;
}
img {
max-width: 100%;
height: auto;
display: block;
}Bootstrap bevat een eigen, uitgebreidere reset (Reboot). Gebruik je Bootstrap, dan hoef je dit niet zelf te schrijven.
Een stylesheet organiseren
Een stylesheet groeit snel. Geef het een vaste volgorde, van algemeen naar specifiek, en zet commentaarkoppen:
stijl.css/* 1. Variabelen */
:root { … }
/* 2. Reset en basis */
*, *::before, *::after { … }
body { … }
h1, h2, h3 { … }
/* 3. Layout */
.container { … }
.kop { … }
.voet { … }
/* 4. Componenten */
.knop { … }
.kaart { … }
/* 5. Hulpklassen */
.verborgen { display: none; }
/* 6. Media queries (onderaan, of bij hun component) */
@media (max-width: 600px) { … }Goede gewoontes
- Gebruik klassen, geen id’s, om op te maken: dat blijft flexibel en overschrijfbaar.
- Beschrijvende namen die zeggen wat iets is, niet hoe het eruitziet:
.waarschuwingin plaats van.rode-tekst. - Kies één naamconventie: kleine letters met streepjes (
.product-kaart). Voor grotere projecten bestaat BEM:.kaart,.kaart__titel,.kaart--groot. - Herhaal je jezelf? Maak een variabele of een gedeelde klasse.
- Verdeel grote projecten in meerdere bestanden (
reset.css,layout.css,componenten.css) of gebruik een tool zoals Sass.
Verwerk wat je hierboven las met de onderdelen hieronder. Ze horen bij deze theorie.
🧪 Oefeningen — CSS-variabelen en organisatie
Typ je code in het vak en klik op "Controleer". Je code wordt nagekeken op de vereiste onderdelen (waar een Voorbeeld-knop staat, kan je je pagina ook meteen bekijken). Je code wordt bewaard als je aangemeld bent.
Definieer in :root drie variabelen: --kleur-primair: #2563eb, --kleur-tekst: #1e293b en --straal: 8px. Gebruik ze daarna met var(): body krijgt color: var(--kleur-tekst); h1 krijgt color: var(--kleur-primair); .knop krijgt background-color: var(--kleur-primair), border-radius: var(--straal), witte tekst en geen rand.
Definieer in :root de variabelen --achtergrond: #ffffff en --tekst: #0f172a. Overschrijf ze in .donker met --achtergrond: #0f172a en --tekst: #e2e8f0. .pagina gebruikt ze: background-color: var(--achtergrond), color: var(--tekst) en padding: 20px.
Schrijf een reset: (1) *, *::before, *::after krijgen box-sizing: border-box; (2) body krijgt margin: 0, font-family: system-ui, sans-serif en line-height: 1.6; (3) img krijgt max-width: 100%, height: auto en display: block.
🔍 Opzoekwerk — CSS-variabelen en organisatie
Zoek het antwoord zelf op (internet, cursus, ...) en typ het hieronder. Wordt automatisch bewaard.
Tip: zoek naar "BEM naming convention" (getbem.com).
✓ opgeslagenTip: zoek naar "Sass vs CSS variables".
✓ opgeslagen✅ Testjezelf-quiz — CSS-variabelen en organisatie
Beantwoord alle vragen en klik daarna op "Controleer". Je mag zo vaak opnieuw proberen als je wil.
Je hebt de HTML van een portfolio-pagina. Nu maak je ze mooi en responsief met alles wat je in deze cursus leerde.
De opdracht
Onderaan vind je de HTML van een portfolio: een menubalk, een introductieblok, een galerij projectkaarten en een voet. Jij schrijft de volledige CSS. Doel: een verzorgde, responsieve pagina.
Eisen:
- Variabelen in
:rootvoor je kleuren (--primair,--tekst,--achtergrond) en gebruik ze; - een reset met
box-sizing: border-boxen een leesbaarbody(lettertype, regelafstand); - een menubalk met flexbox (logo links, links rechts, verticaal gecentreerd, plakkend bovenaan);
- een hero met kleurverloop, gecentreerde witte tekst en een knop met hover-effect en transitie;
- een kaartengalerij met grid dat automatisch het aantal kolommen kiest, kaarten met schaduw en een opveer-effect bij hover;
- een media query die de menubalk op een gsm (max. 600px) onder elkaar zet.
Werkwijze
- Begin met de variabelen en de reset.
- Bouw dan van boven naar onder: menubalk → hero → kaarten → voet.
- Bekijk na elk onderdeel het ▶ Voorbeeld en klik op Controleer.
- Test op een smal venster of in de toestelmodus van de DevTools.
- Controleer of de contrast van je kleuren voldoende is.
De klassen zijn: .kop (menubalk), .logo, .hero, .knop, .projecten, .kaarten, .kaart en .voet. Gebruik in de oefening de Voorbeeld-knop om de HTML te zien werken met jouw CSS.
Mogelijke uitwerking
Probeer eerst zelf! Zit je vast, dan zie je hier één van de vele mogelijke oplossingen:
css/stijl.css/* ---------- Variabelen ---------- */
:root {
--primair: #2563eb;
--tekst: #1e293b;
--achtergrond: #f8fafc;
--straal: 10px;
}
/* ---------- Reset en basis ---------- */
*, *::before, *::after {
box-sizing: border-box;
}
body {
margin: 0;
font-family: system-ui, sans-serif;
line-height: 1.6;
color: var(--tekst);
background-color: var(--achtergrond);
}
/* ---------- Menubalk ---------- */
.kop {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
background-color: white;
position: sticky;
top: 0;
z-index: 10;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}
.kop nav ul {
display: flex;
gap: 20px;
list-style: none;
margin: 0;
padding: 0;
}
.kop a {
color: var(--tekst);
text-decoration: none;
}
/* ---------- Hero ---------- */
.hero {
background: linear-gradient(to right, var(--primair), #8b5cf6);
color: white;
text-align: center;
padding: 60px 20px;
}
.knop {
display: inline-block;
background-color: white;
color: var(--primair);
padding: 12px 24px;
border-radius: var(--straal);
text-decoration: none;
transition: transform 0.2s ease;
}
.knop:hover {
transform: translateY(-2px);
}
/* ---------- Kaarten ---------- */
.kaarten {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 16px;
padding: 24px;
}
.kaart {
background-color: white;
padding: 20px;
border-radius: var(--straal);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
transition: transform 0.2s ease;
}
.kaart:hover {
transform: translateY(-4px);
}
/* ---------- Voet ---------- */
.voet {
text-align: center;
padding: 20px;
}
/* ---------- Gsm ---------- */
@media (max-width: 600px) {
.kop {
flex-direction: column;
gap: 8px;
}
} Wat nu?
Gefeliciteerd: je kan nu een volledige website opmaken. Enkele mogelijke vervolgstappen:
- Bootstrap: een kant-en-klaar raamwerk dat veel van dit werk voor je doet;
- JavaScript en jQuery: je pagina reageert op klikken, zoals een uitklapbaar menu;
- Sass en Tailwind CSS: hulpmiddelen voor grote projecten;
- Oefenen: bouw na wat je op het web mooi vindt, bv. de homepage van een bekend merk.
Verwerk wat je hierboven las met de onderdelen hieronder. Ze horen bij deze theorie.
🧪 Oefeningen — Eindproject: de portfolio-site opmaken
Typ je code in het vak en klik op "Controleer". Je code wordt nagekeken op de vereiste onderdelen (waar een Voorbeeld-knop staat, kan je je pagina ook meteen bekijken). Je code wordt bewaard als je aangemeld bent.
Schrijf de CSS volgens de eisen in De opdracht. Namen van de variabelen: --primair, --tekst, --achtergrond. Test met ▶ Voorbeeld en maak het venster smaller om de media query te zien.
🔍 Opzoekwerk — Eindproject: de portfolio-site opmaken
Zoek het antwoord zelf op (internet, cursus, ...) en typ het hieronder. Wordt automatisch bewaard.
Tip: F12 -> Elements en Styles, of de Computed-weergave.
✓ opgeslagenTip: getbootstrap.com -> Components.
✓ opgeslagen✅ Testjezelf-quiz — Eindproject: de portfolio-site opmaken
Beantwoord alle vragen en klik daarna op "Controleer". Je mag zo vaak opnieuw proberen als je wil.
⚠️ Je verliet deze pagina
Je wisselde van tabblad (of verliet de pagina) terwijl je bezig was met een oefening, opdracht of zelftest. Dit werd geregistreerd als het verlaten van de oefening en kan als vals spelen bestempeld worden.