# Responsive development

Mobile first met Flexbox, Grid, media queries, container queries en relatieve eenheden

Multimedia & Creatieve Technologie · 2.1 Web production · Les 4 · versie 2.0.0 · 2026-10-14

Tags: css, responsive, html, accessibility

Slides: <https://slides.mctantwerp.be/nl/web-production/04-responsive>

Speaker notes: <https://slides.mctantwerp.be/nl/web-production/04-responsive.notes.md>

<!-- slide 2 -->

## Agenda

1. Zonder media query
2. Mobile first
3. Breakpoints
4. Container queries
5. Meer dan breedte
6. Eenheden

<!-- slide 3 -->

## Wat breekt er?

Een nieuwssite in een venster dat je smaller en breder kan maken. Op een breed scherm ziet ze er goed uit, smaller loopt alles uit het venster.

<!-- slide 4 -->

## Wat er brak

- De pagina is breder dan de telefoon, dus je scrolt horizontaal
- De navigatie loopt uit het venster
- Drie kolommen cards, elk een paar woorden breed
- De sidebar blijft naast main staan, ook zonder plaats

<!-- slide 5 -->

## Wie kijkt er mee?

59%

van de pageviews wereldwijd komt van een telefoon

50%

in België, tegenover 48% desktop

2024

sinds juli indexeert Google elke site via de mobiele versie

[StatCounter](https://gs.statcounter.com/platform-market-share/desktop-mobile-tablet/worldwide/), september 2026 · [Google Search Central](https://developers.google.com/search/blog/2024/06/mobile-indexing-vlast-final-final.doc)

<!-- slide 6 -->

## Na deze les kan je

- Een layout responsive maken zonder media query
- Uitleggen waarom we mobile first bouwen
- Een breakpoint kiezen op je content en er een media query voor schrijven
- Een card bouwen die zelf haar layout kiest met een container query
- Kiezen tussen px, rem, vw en cqi, en uitleggen waarom

<!-- slide 7 -->

## 1. Zonder media query

<!-- slide 8 -->

### Flexbox of Grid

|   | Flexbox | Grid |
| --- | --- | --- |
| Richting | Eén rij of één kolom | Rijen en kolommen samen |
| Typisch | Navigatie, knoppen, tags | Paginalayout, cardoverzicht |
| Zonder media query | flex-wrap: wrap | repeat(auto-fit, minmax(...)) |

- **[Flexbox Froggy](https://flexboxfroggy.com/#nl)**: justify-content, align-items en flex-wrap
- **[Grid Garden](https://cssgridgarden.com/#nl)**: grid-template-columns, fr en kolommen overspannen

<!-- slide 9 -->

### Een maximum, geen vaste breedte

Een telefoon van 390px met een .page container erin. Met width: 1100px loopt .page uit het scherm en scrolt de pagina horizontaal. Met max-width: 1100px past .page, maar steekt de afbeelding van 480px er nog uit. Met max-width: 100% op de afbeelding past alles.

<!-- slide 10 -->

### Bovenaan elke stylesheet

```css
* {
  box-sizing: border-box;
}

img {
  max-width: 100%;
  height: auto;
}
```

- box-sizing: padding valt binnen de breedte, dus width: 100% blijft 100%
- img: nooit breder dan haar container, en de verhouding blijft

> [!TIP]
> **Ook een maximum voor je content**
>
> De 1100px van `.page` in de demo is een voorbeeld. Geef je content wel ergens een `max-width`, anders worden tekstregels en cards op een breed scherm eindeloos breed.

<!-- slide 11 -->

### Een rij die niet past, wrapt

```css
.items {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}
```

Passen de items niet meer op één rij, dan gaan ze naar de volgende. De browser kiest per breedte hoeveel er op een rij passen.

Zes genummerde boxes van 200px in een flex container. Met nowrap lopen ze uit de container, met wrap gaan ze naar een volgende rij.

<!-- slide 12 -->

### Grid kiest zelf het aantal kolommen

```css
.items {
  display: grid;
  gap: 16px;
  grid-template-columns:
    repeat(auto-fit, minmax(250px, 1fr));
}
```

Elke kolom is minstens 250px. auto-fit maakt er zoveel als er passen.

Zes genummerde boxes in een grid. Met repeat(3, 1fr) blijven het altijd drie kolommen, met repeat(auto-fit, minmax(250px, 1fr)) kiest de grid zelf hoeveel er passen.

<!-- slide 13 -->

### Hoeveel kolommen in een container van 600px?

```css
.items {
  display: grid;
  gap: 16px;
  grid-template-columns:
    repeat(auto-fit, minmax(250px, 1fr));
}
```

- A. Eén
- B. Twee
- C. Drie

**Antwoord:** B. Twee

Drie kolommen van minstens 250px met twee gaps van 16px vragen 782px, dat past niet. Twee vragen 516px, dat past. De 84px die overblijven, verdeelt 1fr over de twee kolommen.

<!-- slide 14 -->

### Oefening 1: Responsive zonder media query

*10 minuten, Alleen*

1. Open de starter in CodePen, bewaar hem en sleep de preview smal
2. Geef .page een max-width in plaats van een width
3. Laat de navigatie wrappen
4. Laat de cards zelf hun kolommen kiezen met auto-fit

Een knop die een nieuwe pen op CodePen opent met de starter "Oefening 1: responsive zonder media query" (HTML en CSS).

> [!NOTE]
> **Een CodePen-account**
>
> Zonder account kan je een pen niet bewaren en is je werk weg na een refresh.
>
> **[CodePen](https://slides.mctantwerp.be/nl/web-production/codepen)**: Een account aanmaken en je pen bewaren

<!-- slide 15 -->

## 2. Mobile first

<!-- slide 16 -->

**Begin bij het smalle scherm**

Op een telefoon staat alles onder elkaar en vult het de breedte. Dat doet de browser al zonder één regel layout-CSS. Pas als er meer ruimte is, zet je er een indeling bij.

<!-- slide 17 -->

### Desktop first of mobile first

#### Desktop first

```css
.page-layout {
  display: grid;
  grid-template-columns: 1fr 300px;
}

@media (width < 1024px) {
  .page-layout { grid-template-columns: 1fr; }
}
```

Eerst twee kolommen, daarna een query die ze voor kleine schermen weer ongedaan maakt.

#### Mobile first

```css
.page-layout {
  display: grid;
}

@media (width >= 1024px) {
  .page-layout {
    grid-template-columns: 1fr 300px;
  }
}
```

Eén kolom is de default van grid. De query zet de sidebar erbij vanaf 1024px.

<!-- slide 18 -->

### Waarom mobile first

- Voor de smalle versie schrijf je bijna niets: alles staat al onder elkaar
- Elke query zet er iets bij, je maakt nooit een desktop-regel ongedaan
- Minder overrides, dus minder plekken waar een bug kan zitten
- Een trage telefoon laadt geen layout die hij toch niet gebruikt
- Op een smal scherm kies je eerst wat echt belangrijk is

<!-- slide 19 -->

### Denkoefening: Wat komt er bovenaan

*5 minuten, Per 2*

1. Op een breed scherm staan er: logo en navigatie, een uitgelicht artikel, zes cards, een sidebar met de agenda, een inschrijving voor de nieuwsbrief en een footer
2. Zet ze in volgorde voor een telefoon van 390px breed
3. Wat klap je in of laat je weg?

<!-- slide 20 -->

### Viewport meta tag

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

Zonder deze tag rendert een telefoon de pagina vaak op 980px breed en zoomt hij uit. Dan reageren je media queries niet op de echte breedte.

> [!WARNING]
> **Zoom nooit blokkeren**
>
> Geen `user-scalable=no` en geen `maximum-scale=1`.

<!-- slide 21 -->

### Media queries

```css
.site-header {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

@media (width >= 768px) {
  .site-header {
    flex-direction: row;
    justify-content: space-between;
  }
}

/* dezelfde query, de oude schrijfwijze */
@media (min-width: 768px) { ... }
```

- Buiten de query: geldt op elke breedte, ook op een telefoon
- In de query: geldt vanaf 768px, bovenop de basis
- min-width kom je nog overal tegen, het betekent hetzelfde

<!-- slide 22 -->

### Welke kleur krijgt de titel op 700px?

```css
.page-title { color: black; }

@media (width >= 640px) {
  .page-title { color: blue; }
}

@media (width >= 960px) {
  .page-title { color: red; }
}
```

- A. Zwart
- B. Blauw
- C. Rood

**Antwoord:** B. Blauw

700px is breder dan 640px en smaller dan 960px, dus enkel de eerste query doet mee: blauw. Op 1000px doen beide mee, met dezelfde specificiteit, en wint de laatste in de file: rood.

<!-- slide 23 -->

## 3. Breakpoints

<!-- slide 24 -->

**Fluid tot het breekt**

Begin smal en maak het venster breder tot de content er slecht uitziet: links die naast elkaar passen, tekstregels die te lang worden, een card die uitrekt. Daar ligt je breakpoint. Een iPad mini is 744px breed, een laptopvenster in split screen 640px: een lijst met devices vertelt je dat niet.

<!-- slide 25 -->

### Een breakpoint kiezen

- Welke content begint te botsen of uit te rekken?
- Welke indeling werkt daar beter?
- Werkt die ook met langere tekst?

Een header met logo en navigatie. Maak je het venster smaller, dan botsen de links op een bepaalde breedte. Met langere labels gebeurt dat vroeger.

<!-- slide 26 -->

### De header per breakpoint

```css
.site-header {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

@media (width >= 768px) {
  .site-header {
    flex-direction: row;
    justify-content: space-between;
  }
}
```

Een header met logo en navigatie. Onder 768px staan ze onder elkaar, daarboven zet een media query flex-direction op row.

<!-- slide 27 -->

### Van Flexbox naar Grid

```css
.page-layout {
  display: flex;
  flex-direction: column;
}

@media (width >= 1024px) {
  .page-layout {
    display: grid;
    grid-template-columns: 1fr 300px;
    grid-template-areas:
      "header header"
      "main   aside"
      "footer footer";
  }
}
```

Een paginalayout met header, main, aside en footer. Onder 1024px staat alles onder elkaar met Flexbox, daarboven wordt het een Grid met areas.

<!-- slide 28 -->

### Hoeveel kolommen op 1200px?

```css
@media (width >= 1024px) {
  .items { grid-template-columns: 1fr 1fr 1fr; }
}

@media (width >= 768px) {
  .items { grid-template-columns: 1fr 1fr; }
}
```

- A. Drie, de query van 1024px
- B. Twee, de query van 768px
- C. Eén, geen van beide

**Antwoord:** B. Twee, de query van 768px

Op 1200px doen beide queries mee. Een media query verandert de specificiteit niet, dus de regel die het laatst in de file staat wint: die van 768px. Bij mobile first zet je de queries van klein naar groot.

<!-- slide 29 -->

### Oefening 2: Header en sidebar

*15 minuten, Alleen*

1. Open de starter in CodePen en bewaar hem. De smalle layout is al klaar
2. Zet logo en navigatie naast elkaar zodra er plaats is
3. Zet main en aside naast elkaar met Grid, vanaf een tweede breakpoint
4. width >= queries in px, van klein naar groot
5. Leg in één zin uit waarom je breakpoints daar liggen

Een knop die een nieuwe pen op CodePen opent met de starter "Oefening 2: header en sidebar" (HTML en CSS).

<!-- slide 31 -->

## 4. Container queries

<!-- slide 32 -->

**Dezelfde card in main en in de sidebar**

In main heeft ze plaats voor een afbeelding naast de tekst, in de sidebar niet. Een media query ziet voor allebei dezelfde viewport.

<!-- slide 33 -->

### De query container

```html
<div class="story-slot">
  <article class="story-card">
    <img src="campus.jpg" alt="...">
    <div class="story-card__body">
      <h2>Een nieuwe studieruimte</h2>
      <p>Meer stopcontacten, minder lawaai.</p>
    </div>
  </article>
</div>
```

```css
.story-slot {
  container: story / inline-size;
}
```

`story` is de naam, `inline-size` meet de breedte.

[MDN: container queries](https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Containment/Container_queries)

<!-- slide 34 -->

### De card past zich aan

```css
.story-card {
  display: grid;
  gap: 16px;
}

@container story (width >= 450px) {
  .story-card {
    grid-template-columns: 1fr 2fr;
  }
}
```

- De basis is een verticale card
- Is de container 450px of breder, dan komt de afbeelding naast de tekst
- De viewport doet er niet toe

<!-- slide 35 -->

### Eén viewport, twee cards

Een pagina van 1280px met dezelfde card in main en in de sidebar. De slider verandert enkel de breedte van de sidebar. Vanaf 450px wordt de card daar horizontaal, de viewport blijft gelijk.

<!-- slide 36 -->

### Waarom verandert de card niet?

```css
.story-card {
  container: story / inline-size;
}

@container story (width >= 450px) {
  .story-card {
    grid-template-columns: 1fr 2fr;
  }
}
```

- A. Een element kan zichzelf niet stylen met zijn eigen container query
- B. De naam story klopt niet
- C. width >= werkt niet in een container query

**Antwoord:** A. Een element kan zichzelf niet stylen met zijn eigen container query

Een container query kijkt naar een ancestor. De card zoekt boven zich een container met de naam story en vindt er geen. Zet de container op de wrapper .story-slot.

<!-- slide 37 -->

### Media query of container query

|   | Media query | Container query |
| --- | --- | --- |
| Kijkt naar | De viewport | De container rond je component |
| Goed voor | Je paginalayout: sidebar, navigatie | Een component: een card, een widget |
| Wat je nodig hebt | Niets extra | container-type op een parent |
| Kan ook | Hover, dark mode, print | Enkel de maat van de container |

<!-- slide 38 -->

### Oefening 3: Eén card, twee plekken

*10 minuten, Alleen*

1. Open de starter in CodePen en bewaar hem
2. Maak van .story-slot een query container
3. Zet de afbeelding naast de tekst zodra de container breed genoeg is
4. Maak de sidebar breder in .layout en kijk of de card daar mee verandert

Een knop die een nieuwe pen op CodePen opent met de starter "Oefening 3: één card, twee plekken" (HTML en CSS).

<!-- slide 39 -->

## 5. Meer dan breedte

<!-- slide 40 -->

### Media features

| Media feature | Vraagt | Gebruik je voor |
| --- | --- | --- |
| `width` | Hoe breed is de viewport? | Je layout |
| `hover, pointer` | Muis of duim? | Hover-effecten, grotere knoppen |
| `prefers-color-scheme` | Light of dark mode? | Je kleuren |
| `prefers-reduced-motion` | Minder beweging gevraagd? | Animaties uitzetten |
| `print` | Wordt de pagina geprint? | Navigatie weg, zwarte tekst |

<!-- slide 41 -->

### Hover en pointer

```css
@media (hover: hover) {
  .card:hover {
    transform: translateY(-4px);
  }
}

@media (pointer: coarse) {
  .button {
    min-height: 44px;
  }
}
```

- hover: hover: de primaire invoer kan hoveren
- pointer: coarse: een duim, dus grotere knoppen
- Alles wat belangrijk is, werkt ook zonder hover

<!-- slide 42 -->

### Dark mode

```css
body {
  background: #ffffff;
  color: #1d1d1b;
}

@media (prefers-color-scheme: dark) {
  body {
    background: #1d1d1b;
    color: #f2f2f2;
  }
}
```

Staat je OS op dark mode, dan krijg je de donkere kleuren. Elke kleur die je wil wisselen, zet je opnieuw in de query.

[MDN: prefers-color-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@media/prefers-color-scheme)

<!-- slide 43 -->

### Inzoomen is ook een smal scherm

- Op 400% zoom is een venster van 1280px nog 320 CSS-pixels breed
- Wie inzoomt, krijgt dus je mobiele layout en je breakpoints
- Op 320px scrol je enkel verticaal, ook ingezoomd
- Knoppen minstens 24 bij 24 pixels (WCAG), wij spreken 44 af

**[Reflow](https://www.w3.org/WAI/WCAG22/Understanding/reflow.html)**: WCAG 1.4.10

**[Target size](https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html)**: WCAG 2.5.8

<!-- slide 44 -->

### Oefening 4: Probeer het in DevTools

*5 minuten, Alleen*

1. Open de starter in CodePen
2. Kies: een dark mode met prefers-color-scheme, of het hover-effect van de cards in een (hover: hover) query
3. Zet in Chrome DevTools de Rendering-tab open (Cmd/Ctrl + Shift + P, typ Rendering) en emuleer dark mode, of kies een telefoon in de device toolbar

Een knop die een nieuwe pen op CodePen opent met de starter "Oefening 4: meer dan breedte" (HTML en CSS).

[Chrome: Emulate CSS media features](https://developer.chrome.com/docs/devtools/rendering/emulate-css)

<!-- slide 45 -->

## 6. Eenheden

<!-- slide 46 -->

### Waar rekent een eenheid mee

| Eenheid | Rekent met | Goed voor |
| --- | --- | --- |
| `px` | Niets, een vaste maat | Randen, schaduwen |
| `rem` | De tekstgrootte uit de browser | Tekst, spacing, breakpoints |
| `%` | De parent | Een afbeelding die haar container vult |
| `vw, vh` | Het venster | Iets dat meegroeit met het venster |
| `dvh` | Het venster, met de browserbalken die in beeld zijn | Een hero van één scherm hoog op een telefoon |
| `cqi` | De breedte van de query container | Een titel die meegroeit met zijn card |

<!-- slide 47 -->

### Viewport, container en tekstgrootte

Een verstelbare viewport met echte CSS voor 25vw, 25vh, 25cqi en 10rem. Wissel tussen smal, breed en lager, verander de containerbreedte en de root-tekstgrootte, en voorspel welke maten veranderen.

<!-- slide 48 -->

### Van px naar rem

```css
/* 768px / 16 = 48rem */
@media (width >= 48rem) {
  .site-header {
    flex-direction: row;
  }
}
```

`48rem` is 768px bij de standaard tekstgrootte van 16px.

Zet iemand de tekstgrootte in zijn browser hoger, dan schuift het breakpoint mee en krijgt de tekst de ruimte.

<!-- slide 49 -->

### Een titel die meegroeit

```css
.page-title {
  font-size:
    clamp(2rem, 1rem + 3vw, 4rem);
}
```

clamp(minimum, voorkeur, maximum)

Groeit mee met het venster, maar nooit kleiner dan 2rem of groter dan 4rem.

Een titel met een vaste font-size van 4rem, met een media query die van 2rem naar 4rem springt, en met clamp(2rem, 1rem + 3vw, 4rem). De font-size staat erbij terwijl je het venster smaller en breder maakt.

<!-- slide 50 -->

### Welke eenheid gebruik je?

De titel van de story card moet groter worden als de card breder wordt, in main en in de sidebar.

- A. vw
- B. rem
- C. cqi

**Antwoord:** C. cqi

De card staat in main en in de sidebar, bij hetzelfde venster. vw ziet enkel het venster en geeft beide titels dezelfde grootte. rem groeit met de tekstinstelling, niet met de card. cqi rekent met de breedte van de query container, dus met de card. In clamp() met een rem erbij: clamp(1.25rem, 0.5rem + 5cqi, 2rem).

<!-- slide 51 -->

### Wat breekt er, en wat helpt

| Wat je zag | Wat helpt |
| --- | --- |
| De pagina scrolt horizontaal | Geen query: max-width en img met max-width: 100% |
| De navigatie loopt uit het venster | Geen query: flex-wrap |
| De cards worden piepklein | Geen query: Grid met auto-fit |
| De sidebar blijft naast main staan | Mobile first, een media query waar er plaats is |
| Dezelfde card in een smalle sidebar | Container query |
| Een getapte card blijft in hover hangen | (hover: hover) |
| Grotere tekst botst met je layout | Breakpoints en tekst in rem |

<!-- slide 52 -->

### Opdracht volgt op Canvas

Later deze week komt er een opdracht rond responsive development op Canvas.

**[Canvas](https://canvas.kdg.be/courses/61109/assignments)**: Opdrachten van Web production

**[Naslagwerk](https://mctantwerp.github.io/web-production/responsive-development/)**: Op de site van het vak

## Begrippen

- **Viewport**: De ruimte waarin de browser je pagina toont, gemeten in CSS-pixels. Zonder viewport meta tag rendert een telefoon de pagina vaak op een bredere virtuele viewport (meestal rond 980px) en zoomt hij uit. (slide 20)
- **Mobile first**: Je schrijft eerst de CSS voor een smal scherm, waar alles onder elkaar staat. Met min-width queries zet je er voor bredere schermen iets bij, zoals een tweede kolom. Zo schrijf je geen overrides om een desktop-layout klein te krijgen. (slide 16)
- **Media query**: Een @media regel die CSS enkel toepast als een voorwaarde klopt: een minimale breedte, een muis die kan hoveren, dark mode, print. (slide 21)
- **Range syntax**: De nieuwere schrijfwijze van een media query met vergelijkingstekens: (width >= 768px) in plaats van (min-width: 768px). Werkt ook in container queries. (slide 21)
- **Breakpoint**: De breedte waarop je layout verandert. Je kiest hem waar je content begint te botsen of uit te rekken, niet waar een device begint. (slide 25)
- **auto-fit**: Maakt in repeat() zoveel kolommen als er passen. Met repeat(auto-fit, minmax(250px, 1fr)) kiest een grid zelf zijn aantal kolommen. (slide 12)
- **Container query**: Een @container regel die een component laat reageren op de breedte van zijn container in plaats van op de viewport. Zo werkt dezelfde card in main en in een smalle sidebar. (slide 34)
- **Query container**: Het element met container-type of container. Zijn descendants kunnen erop reageren, het element zelf niet. (slide 33)
- **prefers-color-scheme**: Media feature die zegt of iemand op zijn OS light of dark mode gebruikt. In die query geef je je pagina donkere kleuren. (slide 42)
- **prefers-reduced-motion**: Media feature die zegt of iemand op zijn OS minder beweging vraagt. Hoe je je animaties daarop afstemt, komt bij Animatie. (slide 40)
- **Rendering-tab**: De tab in Chrome DevTools waar je print, dark mode, minder beweging en contrast emuleert. Open hem met Cmd of Ctrl Shift P en typ Rendering. (slide 44)
- **Reflow**: WCAG-criterium: op 320 CSS-pixels breed, of 400% zoom, moet je content bruikbaar blijven zonder in twee richtingen te scrollen. (slide 43)
- **rem**: Een lengte relatief aan de font-size van het root-element, doorgaans 16px. Zet iemand de standaard tekstgrootte in zijn browserinstellingen hoger, dan schaalt alles in rem mee. In een media query rekent rem met die browserinstelling, niet met de font-size die je CSS op html zet. (slide 48)
- **dvh**: Eén procent van de hoogte van de viewport zoals ze nu is, met of zonder de browserbalken van een telefoon. 100vh is op een telefoon vaak hoger dan wat je ziet. (slide 46)
- **cqi**: Eén procent van de inline size, bij gewone tekst de breedte, van de dichtste query container. Zo groeit een titel mee met zijn card. (slide 46)
- **clamp()**: Een waarde met een minimum, een voorkeur en een maximum. Een titel groeit mee met het scherm, maar nooit kleiner of groter dan de grenzen. (slide 49)

## Links en bronnen

### In de presentatie

- [StatCounter: Desktop vs Mobile vs Tablet market share](https://gs.statcounter.com/platform-market-share/desktop-mobile-tablet/worldwide/) (slide 5): September 2026: 59% mobile, 39% desktop
- [Google Search Central: mobile-first indexing, juli 2024](https://developers.google.com/search/blog/2024/06/mobile-indexing-vlast-final-final.doc) (slide 5): Vanaf 5 juli 2024 crawlt Google elke site met de smartphone-crawler
- [Flexbox Froggy](https://flexboxfroggy.com/#nl) (slide 8)
- [Grid Garden](https://cssgridgarden.com/#nl) (slide 8)
- [MDN: Container queries](https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Containment/Container_queries) (slide 33)
- [MDN: prefers-color-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@media/prefers-color-scheme) (slide 42)
- [W3C: Understanding reflow](https://www.w3.org/WAI/WCAG22/Understanding/reflow.html) (slide 43)
- [W3C: Understanding target size (minimum)](https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html) (slide 43)
- [Chrome: Emulate CSS media features](https://developer.chrome.com/docs/devtools/rendering/emulate-css) (slide 44)
- [Canvas](https://canvas.kdg.be/courses/61109/assignments) (slide 52)
- [Web production: Responsive development](https://mctantwerp.github.io/web-production/responsive-development/) (slide 52): Het naslagwerk bij deze les, ook voor responsive images, range syntax en lange content

### Bronnen

- [StatCounter: Desktop vs Mobile vs Tablet market share Belgium](https://gs.statcounter.com/platform-market-share/desktop-mobile-tablet/belgium): September 2026: 50% mobile, 48% desktop
- [MDN: Responsive design](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/CSS_layout/Responsive_Design)
- [MDN: Viewport meta tag](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/meta/name/viewport)
- [MDN: Media queries](https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Media_queries)
- [MDN: CSS length units](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/length)
- [MDN: clamp()](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/clamp)
- [MDN: Responsive images](https://developer.mozilla.org/en-US/docs/Web/HTML/Guides/Responsive_images)
