This episode covers filter, shadow, and modern visual effects: box-shadow and text-shadow for depth, the filter property for altering how images and elements look, backdrop-filter for glass effects, and drop-shadow that follows the true shape.

Episode 14 introduced transform and transitions for motion. Episode 17 adds the visual effects layer: shadows, blur, and color adjustments that give depth and atmosphere to an interface.
box-shadow and text-shadow create a sense of height and hierarchy. filter changes how an element renders — blurring it, shifting its saturation, or moving its hue. backdrop-filter processes the area behind an element, producing the modern glass effect.
Why does it matter? Visual effects are the main differentiator between flat design and design that feels alive. But effects are also expensive in performance when overused. This episode teaches both: how to use them and how to use them sparingly.
box-shadow takes a horizontal offset, vertical offset, blur, spread, and color:
.kartu {
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.1);
}
.kartu-terangkat {
box-shadow: 0 10px 24px rgba(15, 23, 42, 0.15);
}
.tombol {
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.35);
}Small, soft shadows give a subtly raised flat look; large, spread shadows lift the element off the surface. Shadow colors that follow the element's color create a consistent feel. Several shadows can be combined with commas:
.hero {
box-shadow:
0 2px 4px rgba(0, 0, 0, 0.1),
0 8px 24px rgba(0, 0, 0, 0.15);
}
.dalam {
box-shadow: inset 0 2px 4px rgba(15, 23, 42, 0.1);
}Layered shadows mimic real lighting more closely. The inset keyword flips the shadow inward, creating an indent — common for inputs and buttons that look "pressed".
text-shadow works similarly but for text:
.judul {
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
}
.teks-embos {
color: #f8fafc;
text-shadow: 0 1px 2px rgba(15, 23, 42, 0.2);
}Use text-shadow sparingly — large shadows make text blurry. A subtle one or two pixel effect is enough for depth; avoid striking colored shadows on long text.
The filter property applies processing functions to an entire element:
.abu {
filter: grayscale(100%);
}
.kabur {
filter: blur(4px);
}
.cerah {
filter: brightness(1.2);
}
.kontras {
filter: contrast(1.1) saturate(1.3);
}grayscale removes color, blur blurs, brightness and contrast adjust lighting. Several functions can be combined in a single filter, separated by spaces. A common effect: a grayscale image that becomes colorful on :hover:
.gambar {
filter: grayscale(80%);
transition: filter 0.3s ease;
}
.gambar:hover {
filter: grayscale(0%);
}Transitions work on filter like any other property. The example above makes an image look muted, then "come alive" when the cursor touches it.
backdrop-filter applies a filter to the area behind the element, not the element itself:
.navbar {
background-color: rgba(255, 255, 255, 0.6);
backdrop-filter: blur(8px);
}
.dialog {
background-color: rgba(15, 23, 42, 0.4);
backdrop-filter: blur(12px) saturate(1.2);
}Combining a semi-transparent background with blur produces the frosted glass effect. Content scrolled behind the navbar looks blurred yet stays readable.
.logo {
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3));
}drop-shadow inside filter casts a shadow that follows the element's true shape — including the transparency of PNG images and SVGs. This differs from box-shadow, which is always rectangular.
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<title>Kartu Efek</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<article class="kartu">
<img
class="gambar"
src="https://picsum.photos/seed/efek/640/360"
alt="Ilustrasi kartu"
width="640"
height="360"
>
<h2>Judul Kartu</h2>
<p>Deskripsi singkat yang menampilkan efek visual pada kartu.</p>
</article>
</body>
</html>* { box-sizing: border-box; }
body { margin: 0; padding: 48px; font-family: system-ui, sans-serif; background-color: #f1f5f9; }
.kartu { max-width: 360px; margin-inline: auto; background-color: white; border-radius: 16px; overflow: hidden; box-shadow: 0 2px 4px rgba(15, 23, 42, 0.08), 0 12px 32px rgba(15, 23, 42, 0.12); transition: transform 0.2s ease, box-shadow 0.2s ease; }
.kartu:hover { transform: translateY(-4px); box-shadow: 0 4px 8px rgba(15, 23, 42, 0.1), 0 20px 48px rgba(15, 23, 42, 0.18); }
.gambar { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; filter: saturate(0.9); transition: filter 0.3s ease; }
.kartu:hover .gambar { filter: saturate(1.1); }
.kartu h2, .kartu p { padding-inline: 24px; }
.kartu p { padding-bottom: 24px; color: #475569; }Run npx serve . and hover over the card. The shadow grows and the card lifts through transform, while the image sharpens on hover. Both are compositor-run properties, so they stay smooth.
Many large shadows and blurs weigh down rendering. Limit effects to important elements and remove them when no longer visible.
For PNG logos and SVGs with transparency, box-shadow looks wrong in shape. Use drop-shadow, which follows the true contours.
filter affects the entire element including text, and backdrop-filter needs a semi-transparent background to be visible. Apply both deliberately, not haphazardly.
Key takeaways:
box-shadow adds depth with offset, blur, spread, and color.inset flips the shadow inward.filter applies grayscale, blur, brightness, and saturation.backdrop-filter processes the area behind an element for glass effects.drop-shadow follows the true shape of transparent images.transform, opacity, and filter to stay smooth.
In the next episode, episode 18, we'll cover form styling and interactive controls — making inputs, selects, and checkboxes look consistent and easy to use.