Complete CSS-schaduwgids: box-shadow, drop-shadow en text-shadow uitgelegd
Beheers alle drie CSS-schaduwtechnieken — syntaxis, parameters, renderingverschillen, praktijkpatronen en prestatie-implicaties.
Schaduwen zijn een van de eenvoudigste tools in CSS, maar de meeste tutorials raken slechts het oppervlak. Deze gids behandelt alle drie schaduwmechanismen grondig — syntaxis, parameters, renderingverschillen, praktijkcases en prestatie-implicaties — zodat je altijd de juiste techniek kiest.
Waarom heeft CSS drie schaduweigenschappen?
Elk schaduwmechanisme bestaat om een ander probleem op te lossen. Ze zijn op verschillende momenten in de CSS-geschiedenis ontstaan en richten zich op fundamenteel verschillende renderingdoelen:
box-shadow— schaduwen voor rechthoekige boxen (het CSS box model). Beschikbaar sinds CSS 2.1, gestandaardiseerd in CSS3.filter: drop-shadow()— schaduwen die de werkelijke zichtbare vorm van een element volgen, inclusief transparantie. Onderdeel van de CSS Filter Effects Level 1-specificatie.text-shadow— schaduwen die rechtstreeks op glyphcontouren worden toegepast. Technisch de oudste van de drie, geïntroduceerd in CSS 2, kort verwijderd en hergestandaardiseerd in CSS3.
De verwarring ontstaat omdat alle drie produceren wat het menselijk oog waarneemt als "een schaduw", maar de rendering-engine ze behandelt in volledig verschillende fasen van de schilderpipeline.
Gebruik box-shadow voor UI-elementen met effen achtergronden. Gebruik drop-shadow voor PNG's, SVG's of alles met transparantie. Gebruik text-shadow uitsluitend op tekst.
box-shadow: het werkpaard
Tekent een of meer schaduwen achter (of binnen) de border box van een element — de meest veelzijdige en meest gebruikte schaduweigenschap.
Syntaxis
box-shadow: [inset] offset-x offset-y [blur-radius] [spread-radius] color; Elke waarde doet precies een ding:
| Parameter | Standaard | Wat het regelt |
|---|---|---|
inset | weggelaten (buiten) | Tekent de schaduw binnen het element in plaats van erachter |
offset-x | vereist | Horizontale afstand. Positief = rechts, negatief = links |
offset-y | vereist | Verticale afstand. Positief = omlaag, negatief = omhoog |
blur-radius | 0 | Gaussiaanse vervagingshoeveelheid. Hoger = zachter en diffuser |
spread-radius | 0 | Vergroot (+) of verkleint (–) de schaduw voor het vervagen |
color | currentColor | Schaduwkleur — gebruik altijd rgba() of hsla() voor realisme |
De spread radius: de ondergebruikte parameter
De meeste ontwikkelaars gebruiken offset + blur en stoppen daar. De spread radius ontgrendelt een compleet andere klasse effecten. Met spread: 0 en blur: 0 wordt het een perfecte, stapelbare CSS-rand die de layout niet beïnvloedt:
/* Layered outline rings — no layout impact */
box-shadow:
0 0 0 4px rgba(201,184,154,.4),
0 0 0 8px rgba(201,184,154,.1); Met een negatieve spread kun je een wazige schaduw omvormen tot een directionele die alleen onder een element verschijnt:
/* Shadow only at the bottom — more realistic */
box-shadow: 0 12px 24px -8px rgba(0,0,0,.6); Live voorbeelden
4px 4px 8px rgba(0,0,0,.7) 0 0 0 4px accent inset 0 4px 12px 0 2px 4px + 0 8px 24px + ring 0 0 24px + 0 0 48px light + dark inset pair backdrop-blur + shadow Meerdere schaduwen: de volgorde telt
Je kunt een onbeperkt aantal schaduwen stapelen met een kommagescheiden lijst. De renderer verwerkt ze van voor naar achter — de eerste schaduw in de lijst staat bovenaan. Dit maakt het mogelijk om omgevings- en directionele schaduwen te combineren voor natuurlijke diepte in lichte en donkere thema's.
/* Three-layer system used in serious design systems */
box-shadow:
0 1px 2px rgba(0,0,0,.3), /* close shadow: sharp, small */
0 4px 16px rgba(0,0,0,.25), /* mid shadow: soft ambient */
0 0 0 1px rgba(255,255,255,.05); /* subtle highlight ring */ Inset-schaduwen: diepte en ingedrukte staten
Het inset-sleutelwoord verplaatst de schaduw naar binnen de rand van het element. De offsetrichting keert intuïtief om: een positieve Y-offset plaatst de schaduw langs de binnenste bovenrand. Essentieel voor ingedrukte knoppen, verzonken inputs en neumorfisme:
/* Input focus state — depth without a visible border */
input:focus {
box-shadow:
inset 0 2px 6px rgba(0,0,0,.5),
0 0 0 2px rgba(201,184,154,.4);
} Gratis Tool Box Shadow Generator Pas alle zes parameters visueel aan en kopieer productieklaar CSS filter: drop-shadow() — vormvolgende schaduwen
filter: drop-shadow() is geen eigenschap — het is een CSS-filterfunctie. Filters worden na het schilderen toegepast, werkend op de uiteindelijk gerenderde pixels van een element en zijn afstammelingen. Dit onderscheid heeft twee belangrijke gevolgen:
- De schaduw volgt de werkelijke zichtbare contour, respecteert alpha-transparantie in PNG's en de vorm van SVG-paden.
- Het filter beïnvloedt de gehele subboom, inclusief kinderen. Dit betekent dat het automatisch werkt op groepen elementen.
Syntaxis
filter: drop-shadow(offset-x offset-y blur-radius color); Let op: geen spread-radius en geen inset-sleutelwoord. De specificatie heeft ze opzettelijk weggelaten. Als je spread nodig hebt in een vormvolgende schaduw, stapel twee drop-shadow()-aanroepen met verschillende blur-radii.
Waar box-shadow faalt en drop-shadow uitblinkt
Stel je een transparant PNG-logo voor op een gekleurde achtergrond. Pas box-shadow toe en je krijgt een rechthoekige schaduw rond het onzichtbare begrenzingsvak — de schaduw lekt in de transparante gebieden. Pas drop-shadow() toe en de schaduw volgt de werkelijke zichtbare vorm van het logo.
Dezelfde logica geldt voor:
- SVG-elementen — paden, polygonen, samengestelde vormen
- CSS clip-path — de schaduw volgt de clipgrens
- Geroteerde of getransformeerde elementen — de schaduw volgt correct de post-transformatievorm
- Componentgroepen — een filter op de ouder creëert schaduw op alle kinderen als eenheid
/* SVG icon with proper shadow */
.icon-wrapper {
filter: drop-shadow(0 4px 8px rgba(0,0,0,.6));
}
/* PNG logo — shadow follows logo shape, not its bounding box */
.logo {
filter: drop-shadow(2px 4px 12px rgba(0,0,0,.5));
}
/* Stacked for a glow effect on an irregular shape */
.neon-svg {
filter:
drop-shadow(0 0 6px rgba(201,184,154,.8))
drop-shadow(0 0 20px rgba(201,184,154,.4));
} Het belangrijkste compromis: stapelcontext
Het toepassen van filter creëert een nieuwe stapelcontext en een nieuwe compositielaag. Normaal geen probleem, maar het betekent dat het element niet meer correct kan overlappen met andere compositielagen — wat soms z-index-problemen veroorzaakt.
text-shadow: typografische diepte
text-shadow wordt uitsluitend toegepast op de glyphcontouren van tekst — niet op de box van het element. Het wordt in dezelfde fase als de tekst geschilderd, achter de glyphs, waardoor het de juiste keuze is voor diepte of leesbaarheid in typografische elementen.
Syntaxis
text-shadow: offset-x offset-y [blur-radius] color; Vergeleken met box-shadow, geen spread-radius en geen inset. Meerdere schaduwen worden gescheiden door komma's, met dezelfde voor-naar-achter volgorde.
Live voorbeelden
2px 2px 4px rgba(0,0,0,.8) 0 0 10px + 0 0 30px light + dark offset pair hard double offset Veelvoorkomende gebruikscases
Leesbaarheid over afbeeldingen: Een subtiele text-shadow: 0 1px 3px rgba(0,0,0,.6) maakt witte tekst leesbaar over heldere foto's zonder een donkere overlay.
Neon/glow-typografie: Stapel twee schaduwen met nul offset en oplopende blur-radii. De binnenste schaduw creëert de intense kern, de buitenste de atmosferische gloed:
.neon {
color: #c9b89a;
text-shadow:
0 0 8px rgba(201,184,154,.9),
0 0 24px rgba(201,184,154,.5),
0 0 60px rgba(201,184,154,.2);
} Letterpress / reliëf: Combineer een lichte schaduw linksboven met een donkere rechtsonder. De richting bepaalt of de tekst verhoogd of verzonken lijkt:
/* Raised (light = up-left, dark = down-right) */
text-shadow: -1px -1px 0 rgba(255,255,255,.15), 1px 1px 0 rgba(0,0,0,.6);
/* Recessed (reversed) */
text-shadow: 1px 1px 0 rgba(255,255,255,.1), -1px -1px 0 rgba(0,0,0,.5); Harde schaduw (retro/stripstijl): Zonder blur, grotere offset, gestapelde harde schaduwen:
.retro {
text-shadow: 3px 3px 0 #7a5c38, 6px 6px 0 rgba(0,0,0,.25);
} Gratis Tool Text Shadow Generator Ontwerp en exporteer text-shadow-effecten met live voorbeeld Vergelijking naast elkaar
| Kenmerk | box-shadow | drop-shadow() | text-shadow |
|---|---|---|---|
| Doel | Box model van element | Vorm van gerenderde pixels | Glyphcontouren van tekst |
| Respecteert transparantie | Nee — negeert alpha | Ja — volgt de vorm | N/B (alleen tekst) |
| spread-radius | Ja | Nee | Nee |
| Inset-sleutelwoord | Ja | Nee | Nee |
| Meerdere lagen | Ja, kommagescheiden | Ja, aaneengeschakelde functies | Ja, kommagescheiden |
| Stapelcontext | Geen nieuwe context | Creëert nieuwe context | Geen nieuwe context |
| Van toepassing op kinderen | Nee | Ja (gehele subboom) | Nee |
| Werkt op SVG | Alleen begrenzingsvak | Ja, per pad | N/B |
| CSS-animatie | Animeerbaar | Animeerbaar | Animeerbaar |
| GPU-compositie | Vaak, bij gepromote lagen | Ja, altijd | Zelden |
De vraag die bepaalt welke je moet gebruiken
Vraag jezelf af: heeft het element een rechthoekige, ondoorzichtige achtergrond? Zo ja, gebruik box-shadow — gemakkelijker te beredeneren en geen bijeffecten op de stapelcontext. Zo nee (transparante PNG, SVG, onregelmatige vorm, clip-path), gebruik drop-shadow(). Als het doel tekst is, gebruik text-shadow.
Recepten en patronen voor productie
Elevatiesysteem (Material-stijl)
In plaats van schaduwwaarden overal in de codebase hard te coderen, definieer een elevatieschaal als aangepaste CSS-eigenschappen. Dit maakt de diepte globaal consistent en eenvoudig bij te werken:
:root {
--shadow-1: 0 1px 2px rgba(0,0,0,.4);
--shadow-2: 0 2px 6px rgba(0,0,0,.35), 0 1px 2px rgba(0,0,0,.3);
--shadow-3: 0 4px 16px rgba(0,0,0,.3), 0 2px 4px rgba(0,0,0,.3);
--shadow-4: 0 8px 32px rgba(0,0,0,.28), 0 4px 8px rgba(0,0,0,.25);
--shadow-5: 0 16px 48px rgba(0,0,0,.25), 0 8px 16px rgba(0,0,0,.2);
}
.card { box-shadow: var(--shadow-2); }
.card:hover { box-shadow: var(--shadow-4); transition: box-shadow .2s ease; }
.modal { box-shadow: var(--shadow-5); } Gekleurde schaduwen
Een van de meest ondergebruikte technieken: in plaats van zwarte schaduwen, kleur de schaduw met de dominante kleur van het element. Ziet er natuurlijker uit in lichte en donkere thema's:
/* Button with colored shadow matching brand color */
.btn-primary {
background: #c9b89a;
box-shadow: 0 4px 20px rgba(201,184,154,.4), 0 2px 6px rgba(201,184,154,.3);
}
.btn-primary:hover {
box-shadow: 0 6px 28px rgba(201,184,154,.55), 0 3px 8px rgba(201,184,154,.4);
} Glasmorfisme met schaduw
Glasmorfisme vereist een zorgvuldig gekalibreerde interactie tussen backdrop-filter, doorschijnende achtergrond, semi-transparante rand en box-shadow om de kaart van de achtergrond te scheiden:
.glass-card {
background: rgba(255, 255, 255, 0.06);
backdrop-filter: blur(16px) saturate(1.2);
-webkit-backdrop-filter: blur(16px) saturate(1.2);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 16px;
box-shadow:
0 8px 32px rgba(0,0,0,.4), /* ambient depth */
inset 0 1px 0 rgba(255,255,255,.08); /* top highlight */
} PixCode Glassmorphism Generator Genereer visueel met de, die de volledige CSS exporteert inclusief vendor-prefixen.
Focusringen met box-shadow
Het vervangen van de standaard outline van de browser door box-shadow geeft volledige controle over de stijl met behoud van toegankelijkheid. De truc is een schaduw met alleen spread en blur 0:
:focus-visible {
outline: none;
box-shadow:
0 0 0 2px var(--bg), /* gap between element and ring */
0 0 0 4px rgba(201,184,154,.7); /* visible ring */
} Neumorfisme
Neumorfisme gebruikt paren van inset- en outer-schaduwen afgeleid van de achtergrondkleur. Het element, de schaduw en de achtergrond moeten nauw verwante tinten gebruiken — extreem contrast verbreekt de illusie:
/* Element bg = slightly lighter than page bg */
.neumorphic {
background: #1c1c1c;
border-radius: 16px;
box-shadow:
8px 8px 16px #0a0a0a, /* dark shadow: down-right */
-8px -8px 16px #2e2e2e; /* light shadow: up-left */
}
.neumorphic.pressed {
box-shadow:
inset 4px 4px 10px #0a0a0a,
inset -4px -4px 10px #2e2e2e;
} Prestatieoverwegingen
Schaduwen zijn een van de renderingbewerkingen waar ontwikkelaars zich het meest zorgen over maken, vaak onterecht. Dit is wat er echt gebeurt:
✓ Snelle paden
box-shadow op GPU-compositielagen (position:fixed, will-change:transform). filter: drop-shadow() is altijd GPU-versneld. box-shadow animeren via CSS-transities op gepromote elementen.
✗ Langzame paden
box-shadow animeren op niet-gepromote elementen veroorzaakt layout + paint elk frame. Grote blur-radii bij filter: drop-shadow() zijn duur. text-shadow met zeer grote blur op veel elementen.
Bij het animeren van schaduwen
Het veiligste patroon voor geanimeerde schaduwen (elevaties bij hover, laadstaten) is het element eerst promoten en dan de schaduw transiteren:
.card {
will-change: transform; /* promote to compositing layer */
transform: translateZ(0); /* trigger layer in older browsers */
transition: box-shadow .2s ease, transform .2s ease;
box-shadow: var(--shadow-2);
}
.card:hover {
transform: translateY(-2px); /* move on GPU — free */
box-shadow: var(--shadow-4); /* re-composite — also fast */
} Pas will-change niet willekeurig toe — elke gepromote laag verbruikt GPU-geheugen. Gebruik het alleen op elementen die daadwerkelijk gaan animeren.
Prestaties: blur-radius vs spread-radius
Het verhogen van blur-radius is duurder dan het verhogen van spread-radius, omdat blur een Gaussiaanse convolutie vereist die schaalt met het pixeloppervlak.
Interactieve schaduwgeneratoren op PixCode.io
Alle drie schaduwtechnieken hebben speciale interactieve generatoren op PixCode — pas parameters aan met sliders, bekijk het resultaat live en kopieer de productie-klare CSS met een klik.