⏱️ Leestijd: ca. 5 min.

Geavanceerde Pseudo-elementen & Pseudo-klassen

Tot nu toe heb je in CSS voornamelijk elementen gestijld die letterlijk in je HTML-structuur geschreven staan. Maar wat als je decoratieve lijntjes of ikoontjes wilt toevoegen zonder je HTML te bevuilen met nutteloze <div>-tags? Of wat als je een specifiek patroon van elementen wilt stylen, of de volledige achtergrond van een kaart wilt laten oplichten zodra een bezoeker in een invoerveld typt?

Hier komen geavanceerde pseudo-elementen en pseudo-klassen in beeld!

In deze les ontdek je hoe je met ::before, ::after, :nth-child() en :focus-within de controle over je lay-outs naar een professioneel niveau tilt.


1. Het Verschil: Pseudo-klasse vs. Pseudo-element

Voordat we de diepte in duiken, is het belangrijk om het verschil tussen beide begrippen goed te onthouden:


2. Virtuele Elementen Maken met ::before en ::after

De pseudo-elementen ::before en ::after laten je toe om content aan een element toe te voegen via CSS, zonder dat je daar extra HTML voor hoeft te schrijven.

┌─────────────────────────────────────────┐
│ <button class="btn">                    │
│   ::before  <─── (Wordt hier ingevoegd) │
│   "Klik hier"                           │
│   ::after   <─── (Wordt hier ingevoegd) │
│ </button>                               │
└─────────────────────────────────────────┘

De Gouden Regel: content is Verplicht!

Een ::before of ::after verschijnt alleen op de pagina als je de CSS-eigenschap content opgeeft. Zelfs als je een leeg vakje wilt maken voor een decoratieve achtergrond, moet je content: ""; schrijven!

/* Voorbeeld: Een strakke decoratieve onderstreping bij een titel */
.section-title {
    position: relative;
    font-size: 2rem;
    color: #0f172a;
}

.section-title::after {
    content: ""; /* VERPLICHT! */
    display: block;
    width: 60px;
    height: 4px;
    background-color: #2563eb;
    margin-top: 8px;
    border-radius: 2px;
}
💡 Waarvoor gebruik je ::before en ::after?
perfect voor decoratieve accenten, gekleurde lijntjes onder titels, opvallende 'quotes' rond getuigenissen, badges ("Nieuw!"), of handige overlays over afbeeldingen.

3. Slimme Patroonselecties met :nth-child()

Met de pseudo-klasse :nth-child() kun je elementen selecteren op basis van hun volgorde binnen hun ouder-container. Dit bespaart je het handmatig toevoegen van tientallen extra classes in je HTML.

A. Eenvoudige Getallen & Trefwoorden

/* Selecteert exact het 3e item */
li:nth-child(3) {
    color: #2563eb;
}

/* Selecteert alle EVEN items (2, 4, 6, ...) - Ideaal voor tabelrijen! */
tr:nth-child(even) {
    background-color: #f8fafc;
}

/* Selecteert alle ONEVEN items (1, 3, 5, ...) */
tr:nth-child(odd) {
    background-color: #ffffff;
}

B. Formules ($an + b$) voor Slimme Patronen

Door een formule te gebruiken waarin $n$ een teller is (die begint bij 0, 1, 2, ...), kun je complexe reeksen selecteren:

/* De eerste 3 kaarten in een webshop extra opvallend maken */
.product-card:nth-child(-n + 3) {
    border-top: 4px solid #ef4444;
}

4. Slimme Formulier-interactie met :focus-within

De bekende pseudo-klasse :focus werkt enkel op het element waar de gebruiker op dat moment actief mee bezig is (bijvoorbeeld het tekstveld waarin getypt wordt).

De krachtige pseudo-klasse :focus-within reageert op de ouder-container zodra één van de kinderen de focus krijgt!

/* Zodra de gebruiker in het <input> veld typt, kleurt het hele OUDER-blok mee! */
.input-card {
    background-color: #ffffff;
    border: 2px solid #e2e8f0;
    padding: 20px;
    border-radius: 10px;
    transition: all 0.3s ease;
}

/* Krijgt focus-within zodra het input-veld IN de .input-card focus krijgt */
.input-card:focus-within {
    border-color: #2563eb;
    box-shadow: 0 10px 25px rgba(37, 99, 235, 0.15);
    background-color: #eff6ff;
}
Waarom :focus-within fantastisch is voor UX:
Je kunt een compleet formulierblok, een hele zoekbalk-groep, of een navigatiemenu geavanceerd laten oplichten en transformeren zodra de bezoeker erin navigeert met muis of toetsenbord, wat de toegankelijkheid (accessibility) enorm verhoogt!

5. Vergelijkingstabel

SelectorTypeWat doet het?Veelgebruikte toepassing
::beforePseudo-elementVoegt virtuele content toe aan het begin van een element.Decoratieve iconen, vlaggetjes, quotes.
::afterPseudo-elementVoegt virtuele content toe aan het einde van een element.Decoratieve onderlijnen, pijl-iconen, clears.
:nth-child()Pseudo-klasseSelecteert elementen op basis van hun index/positie.Zebra-tabellen, speciale grids, patronen.
:focus-withinPseudo-klasseActiveert op de parent als een kind-element focus heeft.Actieve formulieren, toegankelijke menu's.

6. Compleet Praktijkvoorbeeld

In dit praktijkvoorbeeld combineren we al deze geavanceerde technieken in een interactief formulier met een dynamische lijst.

HTML (index.html)

<!DOCTYPE html>
<html lang="nl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Geavanceerde Pseudo Selectors</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>

    <main class="container">
        <h1 class="title">Inschrijven Workshop</h1>

        <!-- Formuliergroep met :focus-within -->
        <form class="form-card">
            <div class="form-group">
                <label for="naam">Volledige Naam</label>
                <input type="text" id="naam" placeholder="bijv. Alex Peeters">
            </div>

            <div class="form-group">
                <label for="email">E-mailadres</label>
                <input type="email" id="email" placeholder="alex@voorbeeld.be">
            </div>
        </form>

        <!-- Lijst met :nth-child en ::before -->
        <section class="info-section">
            <h2>Belangrijke Regels</h2>
            <ul class="styled-list">
                <li>Breng je eigen laptop en lader mee.</li>
                <li>Zorg dat je Visual Studio Code vooraf geïnstalleerd is.</li>
                <li>Meld je 15 minuten voor aanvang aan bij de receptie.</li>
                <li>Lunch en verfrissingen worden voorzien door de school.</li>
            </ul>
        </section>
    </main>

</body>
</html>

CSS (style.css)

/* Reset & Basis */
*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    font-family: 'Inter', system-ui, sans-serif;
    background-color: #f1f5f9;
    color: #0f172a;
    padding: 40px 20px;
}

.container {
    max-width: 600px;
    margin: 0 auto;
}

/* 1. TITEL MET ::after (DECORATIEVE LIJN) */
.title {
    position: relative;
    font-size: 2.25rem;
    margin-bottom: 32px;
}

.title::after {
    content: "";
    display: block;
    width: 80px;
    height: 5px;
    background-color: #2563eb;
    margin-top: 8px;
    border-radius: 3px;
}

/* 2. FORMULIER MET :focus-within */
.form-card {
    background-color: #ffffff;
    padding: 24px;
    border-radius: 12px;
    border: 2px solid #cbd5e1;
    margin-bottom: 40px;
    transition: all 0.3s ease;
}

/* Als een input binnen het formulier focus krijgt, licht de hele kaart op! */
.form-card:focus-within {
    border-color: #2563eb;
    box-shadow: 0 12px 24px rgba(37, 99, 235, 0.12);
    transform: translateY(-2px);
}

.form-group {
    margin-bottom: 16px;
}

.form-group:last-child {
    margin-bottom: 0;
}

label {
    display: block;
    font-weight: 600;
    margin-bottom: 6px;
    font-size: 0.9rem;
}

input {
    width: 100%;
    padding: 12px;
    border: 1px solid #94a3b8;
    border-radius: 6px;
    outline: none;
    transition: border-color 0.2s;
}

input:focus {
    border-color: #2563eb;
}

/* 3. LIJST STYLING MET ::before EN :nth-child() */
.info-section h2 {
    font-size: 1.5rem;
    margin-bottom: 16px;
}

.styled-list {
    list-style: none;
}

.styled-list li {
    position: relative;
    padding: 14px 16px 14px 44px;
    margin-bottom: 8px;
    border-radius: 8px;
    background-color: #ffffff;
}

/* Custom opsommingsteken maken met ::before */
.styled-list li::before {
    content: "✓";
    position: absolute;
    left: 16px;
    top: 50%;
    transform: translateY(-50%);
    font-weight: bold;
    color: #2563eb;
}

/* :nth-child(): Even en Oneven rijen een subtiele achtergrondafwijking geven */
.styled-list li:nth-child(even) {
    background-color: #f8fafc;
}

/* :nth-child(): Het allereerste lijstitem een speciale accentkleur geven */
.styled-list li:nth-child(1) {
    border-left: 4px solid #2563eb;
}

Samenvatting