Chapter 48: Canvas Shadows
Canvas Shadows in the clearest, most patient, step-by-step way possible.
Imagine I’m sitting right next to you with my screen open. We’re going to build every concept together — slowly, with tiny complete runnable examples you can copy-paste immediately. No skipping steps, no magic, just plain English explanations, visual thinking, common beginner traps, and repeated patterns until shadows feel completely natural and easy to control.
Canvas Shadows – From Zero to Confident
1. The single most important sentence about shadows in Canvas
Shadows in Canvas are painted automatically whenever you draw any filled or stroked shape — but only if you first set the shadow properties.
Canvas has a built-in shadow engine that works on every fill(), stroke(), fillRect(), strokeRect(), fillText(), strokeText(), arc(), etc. You don’t create a separate “shadow object”. You just tell the painter:
“From now on, every shape I draw should have a soft black shadow offset a little down and right.”
And the painter will draw that shadow under every filled/stroked shape — until you turn the shadow off or change its settings.
2. The four shadow properties you must set (all live in the context)
| Property | What it controls | Common values | Default value | Very useful? |
|---|---|---|---|---|
| shadowColor | Color of the shadow | ‘#000’, ‘rgba(0,0,0,0.4)’, ‘#333’ | transparent black | ★★★★★ |
| shadowBlur | How soft/blurry the shadow is | 0 (sharp), 4–12 (soft), 20+ (very soft) | 0 | ★★★★★ |
| shadowOffsetX | How far right (positive) or left (negative) | 4, 8, -3 | 0 | ★★★★★ |
| shadowOffsetY | How far down (positive) or up (negative) | 4, 6, -2 | 0 | ★★★★★ |
Golden rule (memorize this):
Shadows are only drawn when all four properties are set and shadowBlur > 0.
If any one is missing or zero, no shadow appears.
3. Minimal complete shadow example (copy → run)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Canvas – First Shadow</title> <style> canvas { border: 1px solid #ccc; background: #f8f9fa; display: block; margin: 40px auto; } </style> </head> <body> <canvas id="c" width="600" height="400"></canvas> <script> const canvas = document.getElementById('c'); const ctx = canvas.getContext('2d'); // Step 1: Turn shadow ON by setting all four properties ctx.shadowColor = 'rgba(0, 0, 0, 0.5)'; // semi-transparent black ctx.shadowBlur = 12; // softness ctx.shadowOffsetX = 8; // right shift ctx.shadowOffsetY = 8; // down shift // Step 2: Draw something → shadow appears automatically ctx.fillStyle = '#4CAF50'; ctx.fillRect(120, 120, 200, 140); ctx.beginPath(); ctx.arc(420, 200, 90, 0, Math.PI*2); ctx.fillStyle = '#2196F3'; ctx.fill(); // Label ctx.font = 'bold 28px Arial'; ctx.fillStyle = '#333'; ctx.textAlign = 'center'; ctx.fillText('Shadows appear under everything', 300, 340); // Turn shadow OFF (important!) ctx.shadowColor = 'transparent'; ctx.shadowBlur = 0; ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; </script> </body> </html> |
What you should see & remember forever:
- Green rectangle and blue circle both have soft black shadows
- Shadows are automatically drawn under every filled/stroked shape
- Shadows follow the shape exactly (even curves, text, images)
- Shadows are drawn before the shape itself (so shape sits on top)
4. Example 2 – Different shadow styles (copy-paste & play)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
<canvas id="c2" width="900" height="500"></canvas> <script> const canvas = document.getElementById('c2'); const ctx = canvas.getContext('2d'); // Helper: draw labeled shape with shadow function drawWithShadow(x, y, label, shadowColor, blur, offsetX, offsetY, shapeColor) { ctx.shadowColor = shadowColor; ctx.shadowBlur = blur; ctx.shadowOffsetX = offsetX; ctx.shadowOffsetY = offsetY; ctx.beginPath(); ctx.arc(x, y, 60, 0, Math.PI*2); ctx.fillStyle = shapeColor; ctx.fill(); ctx.shadowColor = 'transparent'; // reset after ctx.shadowBlur = 0; ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; ctx.fillStyle = '#333'; ctx.font = '16px Arial'; ctx.textAlign = 'center'; ctx.fillText(label, x, y + 90); } // 1. Soft black shadow (classic) drawWithShadow(150, 120, 'Soft black (default)', 'rgba(0,0,0,0.5)', 12, 6, 6, '#4CAF50'); // 2. Sharp shadow (blur = 0) drawWithShadow(350, 120, 'Sharp shadow (no blur)', '#000', 0, 8, 8, '#2196F3'); // 3. Colored shadow drawWithShadow(550, 120, 'Purple shadow', '#673AB7', 10, 4, 6, '#FF9800'); // 4. Glow effect (negative offset + blur) drawWithShadow(150, 300, 'Outer glow', 'rgba(33,150,243,0.6)', 20, -5, -5, '#FFFFFF'); // 5. Inner glow (draw shape twice) ctx.shadowColor = 'rgba(255,255,255,0.8)'; ctx.shadowBlur = 15; ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; ctx.beginPath(); ctx.arc(350, 300, 80, 0, Math.PI*2); ctx.fillStyle = '#F44336'; ctx.fill(); ctx.shadowColor = 'transparent'; ctx.beginPath(); ctx.arc(350, 300, 80, 0, Math.PI*2); ctx.fillStyle = '#D32F2F'; ctx.fill(); ctx.fillStyle = '#333'; ctx.font = '16px Arial'; ctx.fillText('Inner glow (double draw)', 350, 420); </script> |
Key lessons from this example:
- shadowBlur = 0 → hard/flat shadow
- Colored shadows → very modern look (purple, blue, etc.)
- Glow effect → set offset to 0 or negative + large blur + light color
- Inner glow trick → draw larger blurred light shape → then smaller solid shape on top
6. Your three tiny practice tasks (10–15 min each)
Task 1 – Simple shadow button Draw a rounded rectangle (use roundRect or manual path) Fill it with blue Add soft black shadow offset down-right
Task 2 – Glowing orb Draw a white circle Add blue radial gradient fill Add large soft white shadow around it (glow effect)
Task 3 – Floating cards Draw three small rectangles at different positions Give each a different colored shadow (red, green, purple)
Paste any of them here when you finish — I’ll review it like we’re pair-programming together.
Which part still feels a little slippery?
- Why shadows appear automatically on every shape?
- Difference between shadowBlur = 0 vs 10 vs 30?
- How to make colored shadows vs black ones?
- Creating glow/outer glow effect?
- Inner glow trick?
- Something else?
Tell me — we’ll stay on shadows until you feel super confident adding realistic depth to any Canvas drawing.
You’re doing really well — shadows are one of the things that instantly make Canvas graphics look polished and professional! 🚀
