Exercise 16
Add Visual Effects
Enhance your weather app with gradients, shadows, SVG filters, dynamic backgrounds, and more.
What you'll learn
Key takeaways from this exercise
- Applying CSS gradients to layouts and components with Tailwind
- Applying dynamic styling based on conditions
- Using drop shadows and inset shadows on containers and text
- Using gradients, shadows, and advanced filters in SVG
- Combining TypeScript, React, Tailwind, and SVG to build complex, dynamic icon systems
Introduction
Your weather app is functional — it shows real data with custom SVG icons that adapt to day and night. But it still looks a bit flat: solid colors, no depth, no atmosphere. This exercise is about adding the visual polish that transforms a working app into one that feels designed. Gradients, shadows, and filters are the tools that get you there.
Gradients
Gradients create smooth color transitions. A linear gradient transitions in a straight line — top to bottom, left to right, or any angle. A radial gradient transitions outward from a center point in a circular pattern. In Tailwind, you apply linear gradients with classes like bg-linear-to-b from-sky-600 to-blue-400 — specifying the direction, starting color, and ending color. You can add a via-* class for a middle color stop.
One of the most impactful uses of gradients in the weather app is dynamic backgrounds. Instead of a static color, the background changes based on weather conditions and time of day: a bright blue gradient for a clear day, a dark slate gradient for night, a gray gradient for overcast skies. This is handled by a utility function that takes the weather code and isNight flag and returns the appropriate Tailwind gradient classes. The result is an immersive experience that reflects the actual weather.
Shadows and depth
Shadows add depth and separation. Tailwind provides box-shadow utilities (shadow-sm through shadow-xl) for outer shadows and drop-shadow utilities for filter-based shadows. You can also use inset shadows (inset-shadow-xs through inset-shadow-sm) to create a pressed or recessed effect inside elements. Combining outer and inner shadows creates a rich, tactile appearance. Adding custom opacity to shadows (like shadow-black/30) gives you fine control over how subtle or dramatic the effect is.
Text shadows improve readability on gradient backgrounds — when white text sits on a colorful gradient, a subtle text shadow ensures it stays legible. Tailwind provides text-shadow-sm, text-shadow-md, and text-shadow-lg for this.
SVG gradients and filters
SVG has its own gradient system, separate from CSS. You define SVG gradients inside a <defs> section using <linearGradient> or <radialGradient> elements, each with an ID. Stop elements define the color at each point. Then you reference the gradient using fill="url(#gradientId)" on any shape. Radial gradients are especially useful for glow effects — a soft, circular fade that can make a sun icon feel luminous.
SVG filters go even further. They're visual effects like blur, shadow, and color manipulation defined in SVG markup. An inner shadow filter, for instance, combines a Gaussian blur, an offset, and a composite operation to create a highlight effect inside a shape. Filters are more powerful than CSS equivalents, though also more complex. You define them once and reference them by ID, just like gradients.
Managing effects
A practical pattern for managing all these SVG definitions is to centralize them in a single Effects component. This component renders a hidden SVG element with all your gradient and filter definitions. You include it once in your layout, and every icon in the app can reference those definitions by ID. One source of truth, no duplication.
CSS variables continue to be valuable here. Using Tailwind's variable names (like var(--color-amber-500)) inside SVG gradient definitions keeps your visual effects consistent with the rest of the design system. If you change a color in one place, it propagates everywhere.
Designer judgment
This is the kind of craft that AI can generate — but only a designer knows when it's right. The difference between a shadow that's too harsh and one that creates elegant depth, or a gradient that feels muddy versus one that feels atmospheric — that judgment is yours. Understanding how these tools work in code gives you the vocabulary to express that judgment precisely.
Create a free account to access the full course
In order to access full course content and track your progress, please sign in