CSS Box Shadow & Text Shadow
CSS shadows give elements and text a shadow effect to create depth, elevation, and visual emphasis. box-shadow works on the element's box, while text-shadow works on text.
Shadows are one of the most powerful tools for making a design feel "alive" — separating elements from the background, giving a 3D impression, and drawing attention to specific content.
Box-shadow components:
- offset-x — horizontal offset (required)
- offset-y — vertical offset (required)
- blur-radius — how blurry the shadow is (optional, default 0)
- spread-radius — how much the shadow expands (optional, default 0)
- color — shadow color (optional, default inherit)
- inset — creates the shadow inside the element
The text-shadow components are similar but without spread-radius.
Code Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Box Shadow & Text Shadow</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f0f2f5;
padding: 40px 20px;
}
h1 {
text-align: center;
color: #1a1a2e;
margin-bottom: 10px;
}
.subtitle {
text-align: center;
color: #888;
margin-bottom: 50px;
}
.section {
max-width: 900px;
margin: 0 auto 60px;
}
.section h2 {
color: #1a1a2e;
margin-bottom: 25px;
text-align: center;
font-size: 1.3rem;
}
/* ===== Box Shadow Variations ===== */
.shadow-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 30px;
}
.shadow-item {
background: white;
border-radius: 12px;
padding: 30px 20px;
text-align: center;
}
.shadow-item h4 {
font-size: 0.8rem;
color: #667eea;
margin-bottom: 8px;
font-family: monospace;
}
.shadow-item p {
font-size: 0.7rem;
color: #aaa;
font-family: monospace;
}
.shadow-box {
width: 80px;
height: 80px;
background: white;
border-radius: 12px;
margin: 15px auto 0;
}
.sb-simple {
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.sb-medium {
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
}
.sb-large {
box-shadow: 0 15px 50px rgba(0, 0, 0, 0.2);
}
.sb-colored {
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
}
.sb-spread {
box-shadow: 0 0 0 8px rgba(102, 126, 234, 0.15);
}
.sb-inset {
box-shadow: inset 0 4px 12px rgba(0, 0, 0, 0.15);
}
/* ===== Multiple Box Shadows ===== */
.multi-shadow-section {
background: white;
border-radius: 16px;
padding: 40px;
box-shadow: 0 2px 10px rgba(0,0,0,0.06);
}
.multi-shadow-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 30px;
}
.ms-item {
text-align: center;
}
.ms-item h4 {
font-size: 0.8rem;
color: #667eea;
margin-bottom: 15px;
}
.ms-box {
width: 100px;
height: 100px;
margin: 0 auto;
border-radius: 16px;
background: linear-gradient(135deg, #667eea, #764ba2);
}
.ms-layered {
box-shadow:
0 2px 4px rgba(0,0,0,0.1),
0 8px 16px rgba(0,0,0,0.1),
0 24px 48px rgba(0,0,0,0.1);
}
.ms-colorful {
box-shadow:
-5px -5px 20px rgba(102, 126, 234, 0.4),
5px 5px 20px rgba(118, 75, 162, 0.4);
}
.ms-neon {
box-shadow:
0 0 10px rgba(102, 126, 234, 0.5),
0 0 20px rgba(102, 126, 234, 0.3),
0 0 40px rgba(102, 126, 234, 0.2),
0 0 80px rgba(102, 126, 234, 0.1);
}
.ms-soft {
box-shadow:
0 2px 2px rgba(0,0,0,0.04),
0 4px 4px rgba(0,0,0,0.04),
0 8px 8px rgba(0,0,0,0.04),
0 16px 16px rgba(0,0,0,0.04),
0 32px 32px rgba(0,0,0,0.04);
}
/* ===== Card Shadow Examples ===== */
.card-shadow-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 30px;
}
.card-shadow {
border-radius: 16px;
padding: 30px;
background: white;
transition: box-shadow 0.4s ease, transform 0.4s ease;
cursor: pointer;
}
.card-flat {
box-shadow: 0 1px 3px rgba(0,0,0,0.08);
}
.card-raised {
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.card-floating {
box-shadow: 0 12px 40px rgba(0,0,0,0.12);
}
.card-shadow:hover {
transform: translateY(-8px);
}
.card-flat:hover {
box-shadow: 0 4px 12px rgba(0,0,0,0.12);
}
.card-raised:hover {
box-shadow: 0 12px 40px rgba(0,0,0,0.18);
}
.card-floating:hover {
box-shadow: 0 20px 60px rgba(0,0,0,0.2);
}
.card-shadow h3 {
color: #1a1a2e;
margin-bottom: 10px;
}
.card-shadow p {
color: #666;
font-size: 0.85rem;
line-height: 1.6;
}
.elevation-label {
display: inline-block;
padding: 4px 10px;
background: #f0f2f5;
border-radius: 4px;
font-size: 0.7rem;
font-family: monospace;
color: #667eea;
margin-bottom: 15px;
}
/* ===== Elevated Buttons ===== */
.btn-elevated-grid {
display: flex;
gap: 20px;
justify-content: center;
flex-wrap: wrap;
}
.btn-elevated {
padding: 14px 28px;
border: none;
border-radius: 8px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-elev-1 {
background: #667eea;
color: white;
box-shadow: 0 4px 0 #4a5fd4, 0 6px 12px rgba(102, 126, 234, 0.3);
}
.btn-elev-1:hover {
transform: translateY(-2px);
box-shadow: 0 6px 0 #4a5fd4, 0 10px 20px rgba(102, 126, 234, 0.4);
}
.btn-elev-1:active {
transform: translateY(2px);
box-shadow: 0 2px 0 #4a5fd4, 0 3px 6px rgba(102, 126, 234, 0.2);
}
.btn-elev-2 {
background: #f5576c;
color: white;
box-shadow: 0 4px 0 #d43f52, 0 6px 12px rgba(245, 87, 108, 0.3);
}
.btn-elev-2:hover {
transform: translateY(-2px);
box-shadow: 0 6px 0 #d43f52, 0 10px 20px rgba(245, 87, 108, 0.4);
}
.btn-elev-2:active {
transform: translateY(2px);
box-shadow: 0 2px 0 #d43f52, 0 3px 6px rgba(245, 87, 108, 0.2);
}
.btn-elev-3 {
background: #43e97b;
color: #1a1a2e;
box-shadow: 0 4px 0 #2bc763, 0 6px 12px rgba(67, 233, 123, 0.3);
}
.btn-elev-3:hover {
transform: translateY(-2px);
box-shadow: 0 6px 0 #2bc763, 0 10px 20px rgba(67, 233, 123, 0.4);
}
.btn-elev-3:active {
transform: translateY(2px);
box-shadow: 0 2px 0 #2bc763, 0 3px 6px rgba(67, 233, 123, 0.2);
}
/* ===== Text Shadow ===== */
.text-shadow-section {
background: linear-gradient(135deg, #1a1a2e, #16213e);
border-radius: 16px;
padding: 50px 30px;
text-align: center;
}
.ts-basic {
font-size: 2.5rem;
font-weight: 900;
color: white;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
margin-bottom: 25px;
}
.ts-long-shadow {
font-size: 2.5rem;
font-weight: 900;
color: #667eea;
text-shadow:
1px 1px 0 #5a6fd4,
2px 2px 0 #4e67c8,
3px 3px 0 #425fbc,
4px 4px 0 #3657b0,
5px 5px 0 #2a4fa4;
margin-bottom: 25px;
}
.ts-neon {
font-size: 2.5rem;
font-weight: 900;
color: #fff;
text-shadow:
0 0 10px #667eea,
0 0 20px #667eea,
0 0 40px #667eea,
0 0 80px #764ba2;
margin-bottom: 25px;
}
.ts-glow {
font-size: 2.5rem;
font-weight: 900;
color: #43e97b;
text-shadow: 0 0 20px rgba(67, 233, 123, 0.8), 0 0 40px rgba(67, 233, 123, 0.4);
margin-bottom: 25px;
}
.ts-outline {
font-size: 2.5rem;
font-weight: 900;
color: transparent;
-webkit-text-stroke: 2px #f5576c;
text-shadow:
3px 3px 0 rgba(245, 87, 108, 0.3),
-1px -1px 0 rgba(245, 87, 108, 0.1);
margin-bottom: 25px;
}
.ts-soft {
font-size: 2rem;
font-weight: 700;
color: #fa709a;
text-shadow: 0 2px 10px rgba(250, 112, 154, 0.5);
}
/* ===== Interactive Shadow Playground ===== */
.playground {
background: white;
border-radius: 16px;
padding: 40px;
box-shadow: 0 2px 10px rgba(0,0,0,0.06);
}
.playground-preview {
display: flex;
justify-content: center;
margin-bottom: 30px;
}
.playground-box {
width: 150px;
height: 150px;
background: white;
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.8rem;
color: #aaa;
transition: box-shadow 0.2s ease;
}
.playground-controls {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
}
.control-group {
display: flex;
flex-direction: column;
}
.control-group label {
font-size: 0.8rem;
font-weight: 600;
color: #555;
margin-bottom: 5px;
}
.control-group input[type="range"] {
accent-color: #667eea;
}
.control-group .value-display {
font-size: 0.75rem;
color: #667eea;
font-family: monospace;
}
</style>
</head>
<body>
<h1>CSS Box Shadow & Text Shadow</h1>
<p class="subtitle">Shadow effects for depth and visual emphasis</p>
<div class="section">
<h2>Box Shadow Variations</h2>
<div class="shadow-grid">
<div class="shadow-item">
<h4>Simple</h4>
<div class="shadow-box sb-simple"></div>
<p>0 4px 6px rgba(0,0,0,0.1)</p>
</div>
<div class="shadow-item">
<h4>Medium</h4>
<div class="shadow-box sb-medium"></div>
<p>0 8px 25px rgba(0,0,0,0.15)</p>
</div>
<div class="shadow-item">
<h4>Large</h4>
<div class="shadow-box sb-large"></div>
<p>0 15px 50px rgba(0,0,0,0.2)</p>
</div>
<div class="shadow-item">
<h4>Colored</h4>
<div class="shadow-box sb-colored"></div>
<p>0 8px 25px rgba(102,126,234,0.4)</p>
</div>
<div class="shadow-item">
<h4>Spread</h4>
<div class="shadow-box sb-spread"></div>
<p>0 0 0 8px rgba(102,126,234,0.15)</p>
</div>
<div class="shadow-item">
<h4>Inset</h4>
<div class="shadow-box sb-inset"></div>
<p>inset 0 4px 12px rgba(0,0,0,0.15)</p>
</div>
</div>
</div>
<div class="section">
<h2>Multiple (Layered) Box Shadows</h2>
<div class="multi-shadow-section">
<div class="multi-shadow-grid">
<div class="ms-item">
<h4>Layered</h4>
<div class="ms-box ms-layered"></div>
</div>
<div class="ms-item">
<h4>Colorful</h4>
<div class="ms-box ms-colorful"></div>
</div>
<div class="ms-item">
<h4>Neon Glow</h4>
<div class="ms-box ms-neon"></div>
</div>
<div class="ms-item">
<h4>Soft Stacked</h4>
<div class="ms-box ms-soft"></div>
</div>
</div>
</div>
</div>
<div class="section">
<h2>Card Elevation Levels</h2>
<div class="card-shadow-grid">
<div class="card-shadow card-flat">
<span class="elevation-label">elevation: flat</span>
<h3>Flat</h3>
<p>Minimal shadow — the card feels close to the background. Good for cards that do not need to stand out.</p>
</div>
<div class="card-shadow card-raised">
<span class="elevation-label">elevation: raised</span>
<h3>Raised</h3>
<p>Medium shadow — the card feels lifted. Most commonly used for dashboard cards.</p>
</div>
<div class="card-shadow card-floating">
<span class="elevation-label">elevation: floating</span>
<h3>Floating</h3>
<p>Large shadow — the card feels floating. Good for modals, dropdowns, or prominent elements.</p>
</div>
</div>
</div>
<div class="section">
<h2>Elevated Buttons (3D Effect)</h2>
<div class="btn-elevated-grid">
<button class="btn-elevated btn-elev-1">Primary</button>
<button class="btn-elevated btn-elev-2">Danger</button>
<button class="btn-elevated btn-elev-3">Success</button>
</div>
</div>
<div class="section">
<h2>Text Shadow Effects</h2>
<div class="text-shadow-section">
<div class="ts-basic">Bayangan Dasar</div>
<div class="ts-long-shadow">Long Shadow</div>
<div class="ts-neon">Neon Glow</div>
<div class="ts-glow">Soft Glow</div>
<div class="ts-outline">Outline Text</div>
<div class="ts-soft">Subtle & Clean</div>
</div>
</div>
<div class="section">
<h2>Interactive Shadow Playground</h2>
<div class="playground">
<div class="playground-preview">
<div class="playground-box" id="previewBox">Preview</div>
</div>
<div class="playground-controls">
<div class="control-group">
<label>Offset X: <span class="value-display" id="oxVal">0</span>px</label>
<input type="range" min="-30" max="30" value="0" id="ox" oninput="updateShadow()">
</div>
<div class="control-group">
<label>Offset Y: <span class="value-display" id="oyVal">4</span>px</label>
<input type="range" min="-30" max="30" value="4" id="oy" oninput="updateShadow()">
</div>
<div class="control-group">
<label>Blur: <span class="value-display" id="blurVal">10</span>px</label>
<input type="range" min="0" max="60" value="10" id="blur" oninput="updateShadow()">
</div>
<div class="control-group">
<label>Spread: <span class="value-display" id="spreadVal">0</span>px</label>
<input type="range" min="-20" max="20" value="0" id="spread" oninput="updateShadow()">
</div>
</div>
</div>
</div>
<script>
function updateShadow() {
const ox = document.getElementById('ox').value;
const oy = document.getElementById('oy').value;
const blur = document.getElementById('blur').value;
const spread = document.getElementById('spread').value;
document.getElementById('oxVal').textContent = ox;
document.getElementById('oyVal').textContent = oy;
document.getElementById('blurVal').textContent = blur;
document.getElementById('spreadVal').textContent = spread;
const shadow = `${ox}px ${oy}px ${blur}px ${spread}px rgba(0,0,0,0.3)`;
document.getElementById('previewBox').style.boxShadow = shadow;
}
</script>
</body>
</html>
Code Explanation
box-shadow Syntax
box-shadow: offset-x offset-y blur-radius spread-radius color;
The first two parameters are required (offset-x and offset-y). The rest are optional:
/* Basic */
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
/* x y blur color */
/* With spread */
box-shadow: 0 4px 6px 2px rgba(0,0,0,0.1);
/* x y blur spread color */
/* Inset (inner shadow) */
box-shadow: inset 0 4px 6px rgba(0,0,0,0.1);
Offset X and Y
- Positive
offset-x= shadow to the right, negative = to the left - Positive
offset-y= shadow below, negative = above 0 0= shadow directly behind the element
box-shadow: 4px 4px 10px rgba(0,0,0,0.2); /* bottom-right */
box-shadow: -4px -4px 10px rgba(0,0,0,0.2); /* top-left */
box-shadow: 0 0 10px rgba(0,0,0,0.2); /* center glow */
Blur Radius
Larger values = a blurrier, more spread-out shadow. Default is 0 (sharp edges).
box-shadow: 0 4px 0px rgba(0,0,0,0.2); /* sharp */
box-shadow: 0 4px 20px rgba(0,0,0,0.2); /* blurred */
box-shadow: 0 4px 50px rgba(0,0,0,0.2); /* very blurred */
Spread Radius
Uniformly enlarges or shrinks the shadow. Positive = the shadow grows larger, negative = it shrinks.
box-shadow: 0 0 0 5px rgba(102,126,234,0.3); /* border-like effect */
box-shadow: 0 0 0 -3px rgba(102,126,234,0.3); /* shadow shrinks */
Multiple Box Shadows
You can add multiple shadows separated by commas — they are rendered in order (the first shadow is closest):
.box {
box-shadow:
0 2px 4px rgba(0,0,0,0.1), /* close */
0 8px 16px rgba(0,0,0,0.1), /* middle */
0 24px 48px rgba(0,0,0,0.1); /* far */
}
Inset Box Shadow
The inset keyword creates the shadow inside the element — useful for "sunken" effects or inner glows:
.input {
box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
}
/* Neumorphism: combination of inset and outset */
.neumorphic {
box-shadow:
6px 6px 12px rgba(0,0,0,0.15),
-6px -6px 12px rgba(255,255,255,0.7);
}
text-shadow Syntax
text-shadow: offset-x offset-y blur-radius color;
Similar to box-shadow but without spread-radius and inset:
h1 {
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
/* x y blur color */
}
Multiple Text Shadows
.neon-text {
text-shadow:
0 0 10px #667eea,
0 0 20px #667eea,
0 0 40px #667eea;
}
Everyday Use Cases
1. Card Elevation System
Creating a consistent elevation system for cards:
/* Material Design-like elevation */
.elevation-0 { box-shadow: none; }
.elevation-1 { box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.08); }
.elevation-2 { box-shadow: 0 3px 6px rgba(0,0,0,0.12), 0 2px 4px rgba(0,0,0,0.08); }
.elevation-3 { box-shadow: 0 10px 20px rgba(0,0,0,0.12), 0 3px 6px rgba(0,0,0,0.08); }
.elevation-4 { box-shadow: 0 14px 28px rgba(0,0,0,0.18), 0 5px 10px rgba(0,0,0,0.12); }
2. 3D Button Effect
A shadow that moves when the button is pressed — creating a 3D effect:
.btn-3d {
background: #667eea;
box-shadow: 0 6px 0 #4a5fd4, 0 8px 15px rgba(102,126,234,0.3);
transition: all 0.1s ease;
}
.btn-3d:hover {
box-shadow: 0 8px 0 #4a5fd4, 0 12px 20px rgba(102,126,234,0.4);
}
.btn-3d:active {
transform: translateY(4px);
box-shadow: 0 2px 0 #4a5fd4, 0 3px 6px rgba(102,126,234,0.2);
}
3. Glowing Text for Headings
Glowing text for prominent headings:
h1.glow {
color: #667eea;
text-shadow: 0 0 20px rgba(102, 126, 234, 0.6), 0 0 40px rgba(102, 126, 234, 0.3);
}
4. Neumorphism Design
Neumorphism design uses a combination of inset and outset shadows:
.neumorphic {
background: #f0f0f0;
box-shadow:
8px 8px 16px #d1d1d1,
-8px -8px 16px #ffffff;
}
.neumorphic-inset {
box-shadow:
inset 4px 4px 8px #d1d1d1,
inset -4px -4px 8px #ffffff;
}
5. Focus Ring on Forms
A shadow as a focus indicator — more flexible than outline:
.input {
border: 2px solid #ddd;
transition: box-shadow 0.3s ease;
}
.input:focus {
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.25);
}
Conclusion
box-shadow takes the parameters: offset-x, offset-y, blur-radius, spread-radius, and color. The inset keyword creates the shadow inside the element. Multiple shadows can be added, separated by commas, for a layered effect. text-shadow is similar but without spread-radius. Shadows are most often used for: card elevation, 3D button effects, glow effects, focus indicators, and neumorphism. Keys to good shadow design: use rgba() for transparency, stay consistent within an elevation system, and match the blur to the elevation size — the farther the shadow, the blurrier it should be.