← Terug naar tutorials

Responsieve webdesigns maken met CSS (voor beginners)

responsief webdesigncssmedia queriesflexboxcss gridmobile-firstwebontwikkelingbeginners

Responsieve webdesigns maken met CSS (voor beginners)

Responsief webdesign betekent dat je website zich automatisch aanpast aan verschillende schermformaten: van een kleine telefoon tot een groot bureaubladscherm. In deze tutorial leer je stap voor stap hoe je dat met CSS opbouwt. Je krijgt niet alleen regels om te kopiëren, maar ook uitleg waarom je bepaalde keuzes maakt, welke valkuilen er zijn, en hoe je je ontwerp test.


Inhoud

  1. Wat is responsief webdesign?
  2. Basisprincipes: vloeibare layouts en flexibele media
  3. Een kleine projectstructuur opzetten
  4. Mobiel-eerst ontwerpen
  5. CSS-units die je echt moet kennen
  6. Media queries: de kern van responsiviteit
  7. Flexbox: responsieve rijen en kolommen
  8. CSS Grid: complete pagina-indelingen
  9. Responsieve typografie
  10. Responsieve afbeeldingen en video
  11. Navigatie responsief maken
  12. Veelgemaakte fouten en hoe je ze voorkomt
  13. Testen en debuggen
  14. Mini-project: een responsieve landingspagina
  15. Checklist voor je eigen projecten

Wat is responsief webdesign?

Een responsieve website:

Waarom is dit belangrijk?


Basisprincipes: vloeibare layouts en flexibele media

Vloeibare layouts

Een vaste layout gebruikt bijvoorbeeld width: 960px;. Dat kan op een klein scherm problemen geven: je krijgt horizontaal scrollen of alles wordt te klein.

Een vloeibare layout gebruikt bijvoorbeeld:

Voorbeeld:

.container {
  width: min(100% - 2rem, 1100px);
  margin-inline: auto;
}

Uitleg:

Flexibele media

Afbeeldingen hebben vaak een vaste breedte in HTML of komen in een te grote resolutie binnen. Basisregel:

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

Dit voorkomt dat media buiten hun container “uitsteken”.


Een kleine projectstructuur opzetten

Maak een map voor je project, bijvoorbeeld responsief-beginner/ met deze bestanden:

Je kunt dit aanmaken met echte terminalcommando’s.

Op Windows (PowerShell)

mkdir responsief-beginner
cd responsief-beginner
ni index.html
ni styles.css

Op macOS of Linux (Terminal)

mkdir responsief-beginner
cd responsief-beginner
touch index.html styles.css

Open de map in je editor. In index.html zetten we een basisstructuur.


Mobiel-eerst ontwerpen

Mobiel-eerst betekent:

  1. Je schrijft eerst CSS voor kleine schermen.
  2. Daarna voeg je uitbreidingen toe voor grotere schermen met media queries.

Waarom is dit slim?

Een mobiel-eerst media query ziet er zo uit:

/* Basis: mobiel */
.card-list {
  display: grid;
  gap: 1rem;
}

/* Vanaf 768px: tablet en groter */
@media (min-width: 768px) {
  .card-list {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* Vanaf 1024px: desktop */
@media (min-width: 1024px) {
  .card-list {
    grid-template-columns: repeat(3, 1fr);
  }
}

CSS-units die je echt moet kennen

px (pixels)

Handig, maar niet altijd flexibel. Pixels zijn prima voor kleine details zoals borders, maar minder ideaal voor complete layouts.

% (percentages)

Relatief aan de breedte (of hoogte) van de oudercontainer.

.sidebar {
  width: 30%;
}

rem en em

Waarom rem vaak beter is: je kunt de schaal van je hele site aanpassen door de basisfontgrootte te wijzigen.

Voorbeeld:

html { font-size: 16px; }
h1 { font-size: 2rem; } /* 32px */

vw en vh

Handig voor hero-secties, maar pas op: op mobiele browsers kan de zichtbare hoogte variëren door de adresbalk.

clamp()

Een moderne manier om een waarde responsief te maken binnen grenzen:

h1 {
  font-size: clamp(1.8rem, 3vw + 1rem, 3rem);
}

Uitleg:


Media queries: de kern van responsiviteit

Een media query past CSS toe op basis van eigenschappen van het apparaat, meestal de breedte.

Basisvorm

@media (min-width: 600px) {
  /* CSS die geldt vanaf 600px breedte */
}

Veelgebruikte breekpunten

Er is geen “magische” set breekpunten, maar dit zijn vaak bruikbare richtlijnen:

Belangrijk: kies breekpunten op basis van je ontwerp, niet op basis van specifieke apparaten. Je merkt vaak vanzelf wanneer een layout “breekt”.

Media queries slim organiseren

Zet je CSS in deze volgorde:

  1. Basis (mobiel)
  2. @media (min-width: 600px)
  3. @media (min-width: 900px)
  4. @media (min-width: 1200px)

Zo voorkom je dat je later weer terug moet om regels te overschrijven.


Flexbox: responsieve rijen en kolommen

Flexbox is ideaal voor:

Voorbeeld: kaarten die op mobiel onder elkaar staan

HTML:

<section class="features">
  <article class="feature">Snel</article>
  <article class="feature">Veilig</article>
  <article class="feature">Schaalbaar</article>
</section>

CSS (mobiel-eerst):

.features {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.feature {
  padding: 1rem;
  border: 1px solid #ddd;
  border-radius: 12px;
}

Vanaf tablet:

@media (min-width: 768px) {
  .features {
    flex-direction: row;
  }
  .feature {
    flex: 1;
  }
}

Uitleg:

Veelgebruikte flex-eigenschappen

Voorbeeld met wrap:

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
}

CSS Grid: complete pagina-indelingen

Grid is ideaal voor tweedimensionale layouts: rijen én kolommen tegelijk.

Voorbeeld: een productoverzicht

HTML:

<section class="products">
  <article class="product">Product 1</article>
  <article class="product">Product 2</article>
  <article class="product">Product 3</article>
  <article class="product">Product 4</article>
</section>

CSS:

.products {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
}

.product {
  border: 1px solid #e5e5e5;
  border-radius: 12px;
  padding: 1rem;
}

Vanaf 600px:

@media (min-width: 600px) {
  .products {
    grid-template-columns: repeat(2, 1fr);
  }
}

Vanaf 1024px:

@media (min-width: 1024px) {
  .products {
    grid-template-columns: repeat(4, 1fr);
  }
}

Automatisch kolommen laten ontstaan

Je kunt Grid ook “zelf” kolommen laten kiezen:

.products {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

Uitleg:

Dit is vaak een van de krachtigste responsieve patronen, omdat je minder media queries nodig hebt.


Responsieve typografie

Tekst moet leesbaar blijven. Op mobiel wil je niet dat regels te lang zijn, en op desktop wil je niet dat alles te klein oogt.

Basisinstellingen

html {
  font-size: 16px;
}

body {
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  line-height: 1.6;
  color: #1a1a1a;
}

Regellengte beperken

Een veelvoorkomend probleem op brede schermen is dat tekstregels te lang worden. Een prettige regellengte ligt vaak rond 60–80 tekens. Je kunt dit sturen met max-width:

.prose {
  max-width: 65ch;
}

ch is een unit gebaseerd op de breedte van het teken “0”. Het is handig om tekstbreedte te sturen.

Koppen responsief maken met clamp()

h1 {
  font-size: clamp(2rem, 4vw + 1rem, 3.5rem);
  line-height: 1.1;
}

Hierdoor schaalt de kop mee, zonder extreem groot of klein te worden.


Responsieve afbeeldingen en video

Afbeeldingen die netjes schalen

Basisregel (herhaling, maar essentieel):

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

display: block voorkomt kleine “witruimte” onder afbeeldingen die ontstaat door inline-uitlijning.

Afbeeldingen in een vaste verhouding

Soms wil je dat kaarten allemaal dezelfde beeldverhouding hebben. Gebruik aspect-ratio:

.card img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: 12px;
}

Uitleg:

Video responsief insluiten

Voor een video in een container:

.video {
  aspect-ratio: 16 / 9;
}

.video iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

Een navigatie is vaak het eerste dat “breekt” op mobiel. Een eenvoudige aanpak:

Hier doen we een simpele variant zonder ingewikkelde logica: op mobiel stapelen, op desktop in een rij.

HTML:

<header class="site-header">
  <a class="logo" href="#">MijnSite</a>
  <nav class="nav">
    <a href="#features">Functies</a>
    <a href="#prijzen">Prijzen</a>
    <a href="#contact">Contact</a>
  </nav>
</header>

CSS:

.site-header {
  display: flex;
  flex-direction: column;
  gap: .75rem;
  padding: 1rem;
  border-bottom: 1px solid #eee;
}

.nav {
  display: flex;
  flex-direction: column;
  gap: .5rem;
}

.nav a {
  text-decoration: none;
  color: inherit;
  padding: .5rem .75rem;
  border-radius: 10px;
}

.nav a:hover {
  background: #f3f3f3;
}

Vanaf 768px:

@media (min-width: 768px) {
  .site-header {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }

  .nav {
    flex-direction: row;
    align-items: center;
  }
}

Uitleg:


Veelgemaakte fouten en hoe je ze voorkomt

1) Vaste breedtes die niet kunnen krimpen

Fout:

.card { width: 500px; }

Oplossing:

.card { width: min(100%, 500px); }

2) Geen box-sizing: border-box

Zonder dit tellen padding en border op bij de breedte, wat onverwachte overflow kan geven.

Gebruik dit bijna altijd:

*,
*::before,
*::after {
  box-sizing: border-box;
}

3) Horizontaal scrollen door overflow

Soms veroorzaakt een lang woord, een grote afbeelding of een element met width: 100vw horizontale scroll.

Tips:

.prose {
  overflow-wrap: anywhere;
}

4) Te veel breekpunten

Als je voor elk klein probleem een media query maakt, wordt je CSS onoverzichtelijk. Probeer eerst:

5) Klikdoelen te klein op mobiel

Links en knoppen moeten makkelijk te raken zijn. Richtlijn: voldoende padding.

button, .btn, .nav a {
  padding: .6rem .9rem;
}

Testen en debuggen

In je browser: responsieve modus

De meeste browsers hebben ontwikkelaarshulpmiddelen:

Test echte interactie

Let op:

Snelle lokale server starten

Sommige dingen werken beter via een server (bijvoorbeeld bepaalde imports). Je kunt een simpele server starten.

Als je een omgeving hebt met Python:

python -m http.server 5173

Open daarna in je browser:

Als je een omgeving hebt met Node.js en je wilt een snelle server via een pakket:

npm init -y
npm install --save-dev serve
npx serve .

Mini-project: een responsieve landingspagina

We bouwen een eenvoudige pagina met:

Stap 1: HTML (index.html)

<!doctype html>
<html lang="nl">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Responsief beginner</title>
  <link rel="stylesheet" href="styles.css" />
</head>
<body>
  <header class="site-header container">
    <a class="logo" href="#">MijnSite</a>
    <nav class="nav">
      <a href="#features">Functies</a>
      <a href="#prijzen">Prijzen</a>
      <a href="#contact">Contact</a>
    </nav>
  </header>

  <main>
    <section class="hero container">
      <div class="hero-text">
        <h1>Maak een responsieve website met moderne CSS</h1>
        <p class="lead">
          Leer mobiel-eerst, Flexbox, Grid en media queries. Bouw layouts die er goed uitzien op elk scherm.
        </p>
        <div class="hero-actions">
          <a class="btn primary" href="#features">Bekijk functies</a>
          <a class="btn" href="#prijzen">Bekijk prijzen</a>
        </div>
      </div>

      <div class="hero-media" aria-hidden="true">
        <div class="mock"></div>
      </div>
    </section>

    <section id="features" class="section container">
      <h2>Functies</h2>
      <div class="features">
        <article class="card">
          <h3>Mobiel-eerst</h3>
          <p>Begin klein, schaal op. Zo blijft je CSS overzichtelijk en je site snel.</p>
        </article>
        <article class="card">
          <h3>Flexbox</h3>
          <p>Perfect voor rijen, navigatie en componenten die moeten meebewegen.</p>
        </article>
        <article class="card">
          <h3>Grid</h3>
          <p>Ideaal voor pagina-indelingen en kaartenoverzichten met automatische kolommen.</p>
        </article>
      </div>
    </section>

    <section id="prijzen" class="section container">
      <h2>Prijzen</h2>
      <div class="pricing">
        <article class="price-card">
          <h3>Start</h3>
          <p class="price">€ 0</p>
          <ul>
            <li>1 project</li>
            <li>Basis templates</li>
            <li>Community support</li>
          </ul>
          <a class="btn primary" href="#contact">Kies Start</a>
        </article>

        <article class="price-card featured">
          <h3>Pro</h3>
          <p class="price">€ 9</p>
          <ul>
            <li>Onbeperkt</li>
            <li>Extra componenten</li>
            <li>Snellere feedback</li>
          </ul>
          <a class="btn primary" href="#contact">Kies Pro</a>
        </article>

        <article class="price-card">
          <h3>Team</h3>
          <p class="price">€ 29</p>
          <ul>
            <li>Team toegang</li>
            <li>Design review</li>
            <li>Prioriteit support</li>
          </ul>
          <a class="btn primary" href="#contact">Kies Team</a>
        </article>
      </div>
    </section>

    <section id="contact" class="section container">
      <h2>Contact</h2>
      <form class="contact">
        <label>
          Naam
          <input type="text" name="naam" autocomplete="name" />
        </label>
        <label>
          E-mail
          <input type="email" name="email" autocomplete="email" />
        </label>
        <label>
          Bericht
          <textarea name="bericht" rows="5"></textarea>
        </label>
        <button class="btn primary" type="submit">Verstuur</button>
      </form>
    </section>
  </main>

  <footer class="footer container">
    <p>© MijnSite</p>
  </footer>
</body>
</html>

Belangrijk voor responsiviteit: deze regel in de <head>:

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

Zonder deze meta-tag schalen mobiele browsers je pagina vaak alsof het een desktopsite is.


Stap 2: CSS (styles.css)

Plak dit als basis. Het is bewust mobiel-eerst opgebouwd.

/* 1) Basis reset en globale instellingen */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  font-size: 16px;
}

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  line-height: 1.6;
  color: #161616;
  background: #ffffff;
}

img, video {
  max-width: 100%;
  height: auto;
  display: block;
}

/* 2) Herbruikbare layout-hulp: container */
.container {
  width: min(100% - 2rem, 1100px);
  margin-inline: auto;
}

/* 3) Typografie */
h1 {
  font-size: clamp(2rem, 4vw + 1rem, 3.2rem);
  line-height: 1.1;
  margin: 0 0 1rem;
}

h2 {
  font-size: clamp(1.4rem, 1.6vw + 1rem, 2rem);
  margin: 0 0 1rem;
}

h3 {
  margin: 0 0 .5rem;
}

.lead {
  font-size: 1.05rem;
  color: #333;
  margin: 0 0 1.25rem;
  max-width: 65ch;
}

/* 4) Knoppen */
.btn {
  display: inline-block;
  padding: .7rem 1rem;
  border-radius: 12px;
  border: 1px solid #d7d7d7;
  text-decoration: none;
  color: inherit;
  background: #fff;
}

.btn.primary {
  background: #111;
  color: #fff;
  border-color: #111;
}

.btn:hover {
  filter: brightness(0.97);
}

/* 5) Header en navigatie */
.site-header {
  display: flex;
  flex-direction: column;
  gap: .75rem;
  padding-block: 1rem;
}

.logo {
  font-weight: 700;
  text-decoration: none;
  color: inherit;
  font-size: 1.1rem;
}

.nav {
  display: flex;
  flex-direction: column;
  gap: .25rem;
}

.nav a {
  padding: .55rem .75rem;
  border-radius: 10px;
  text-decoration: none;
  color: inherit;
}

.nav a:hover {
  background: #f3f3f3;
}

/* 6) Secties */
.section {
  padding-block: 2.25rem;
}

/* 7) Hero */
.hero {
  display: grid;
  gap: 1.5rem;
  padding-block: 2rem;
  align-items: center;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
}

.hero-media .mock {
  aspect-ratio: 16 / 10;
  border-radius: 18px;
  background:
    linear-gradient(135deg, #111 0%, #444 45%, #888 100%);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15);
}

/* 8) Kaarten (features) */
.features {
  display: grid;
  gap: 1rem;
}

.card {
  border: 1px solid #e7e7e7;
  border-radius: 16px;
  padding: 1rem;
  background: #fff;
}

/* 9) Pricing grid */
.pricing {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;
}

.price-card {
  border: 1px solid #e7e7e7;
  border-radius: 16px;
  padding: 1rem;
  background: #fff;
}

.price-card.featured {
  border-color: #111;
}

.price {
  font-size: 2rem;
  margin: .25rem 0 1rem;
}

.price-card ul {
  margin: 0 0 1rem;
  padding-left: 1.1rem;
}

/* 10) Formulier */
.contact {
  display: grid;
  gap: .9rem;
  max-width: 520px;
}

.contact label {
  display: grid;
  gap: .35rem;
  font-weight: 600;
}

.contact input,
.contact textarea {
  font: inherit;
  padding: .7rem .85rem;
  border-radius: 12px;
  border: 1px solid #d7d7d7;
}

.contact input:focus,
.contact textarea:focus {
  outline: 2px solid #111;
  outline-offset: 2px;
}

/* 11) Footer */
.footer {
  padding-block: 2rem;
  border-top: 1px solid #eee;
  color: #444;
}

/* 12) Media queries: vanaf tablet */
@media (min-width: 768px) {
  .site-header {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }

  .nav {
    flex-direction: row;
    gap: .25rem;
  }

  .hero {
    grid-template-columns: 1.2fr .8fr;
    padding-block: 3rem;
  }

  .features {
    grid-template-columns: repeat(3, 1fr);
  }

  .pricing {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* 13) Media queries: vanaf desktop */
@media (min-width: 1024px) {
  .section {
    padding-block: 3rem;
  }

  .nav a {
    padding: .55rem .9rem;
  }
}

Wat gebeurt hier responsief?


Stap 3: Testen

  1. Start een lokale server (bijvoorbeeld met Python):

    python -m http.server 5173
  2. Open http://localhost:5173

  3. Verklein en vergroot je browser.

  4. Controleer of je nergens horizontaal hoeft te scrollen.

  5. Controleer of knoppen en links prettig klikbaar blijven.


Checklist voor je eigen projecten

Gebruik deze lijst om te beoordelen of je ontwerp echt responsief is:


Volgende stappen

Als je deze basis beheerst, kun je verder met:

Als je wilt, kan ik op basis van jouw huidige HTML/CSS een concreet responsief plan maken met breekpunten, Grid/Flex-structuur en verbeterde typografie.