AniUI Academy

Shadows, Borders and Gradients

border-radius including elliptical corners and pill/circle shortcuts, box-shadow syntax with inset and stacked shadows, radial-gradient(), and text-shadow.

8 min read

Flat rectangles with sharp corners are the default. A small set of properties is responsible for almost every piece of polish that makes an interface look deliberately designed rather than merely functional — rounded corners, soft depth, a glow, a radiating background.

border-radius

The basic case rounds all four corners equally:

.card {
  border-radius: 12px;
}

Two long-standing shortcut patterns come up constantly:

.pill   { border-radius: 9999px; } /* any value larger than half the height works */
.circle { border-radius: 50%; width: 60px; height: 60px; }

border-radius: 9999px on an element with a fixed height rounds the two ends into a full pill/stadium shape, because the radius is clamped to whatever the actual geometry allows — you don't need to calculate half the element's height by hand. border-radius: 50% on a perfectly square element (equal width and height) produces a true circle, since a 50% radius rounds each corner all the way to the center of its adjacent edge.

A less common but useful trick: each corner can take two values, separated by a slash — the first controls the corner's horizontal radius, the second its vertical radius, producing an elliptical rather than circular corner:

.leaf-shape {
  border-radius: 50px / 20px;
}

This rounds every corner with a wide, shallow ellipse (50px across, 20px tall) rather than a uniform circular curve — useful for organic, non-uniform shapes that a single-value border-radius can't produce.

box-shadow

box-shadow draws a shadow around an element's box. The full syntax is offset-x offset-y blur-radius spread-radius color:

.card {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

Reading each value:

  • offset-x — horizontal shift. 0 keeps the shadow centered left-right.
  • offset-y — vertical shift. Positive pushes it downward, which is the common "light source above" look.
  • blur-radius — how soft the shadow's edge is. 0 gives a hard-edged shadow; larger values feather it out.
  • spread-radius (optional) — grows or shrinks the shadow's shape before blurring, independent of the offset.
  • color — usually a low-opacity black or the surface's own darkened tone, since a fully opaque shadow tends to look harsh.

Adding the inset keyword flips the shadow to draw inside the element's border instead of outside it — useful for a pressed-in, recessed look:

.input-pressed {
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2);
}

You can stack multiple shadows on one element by separating them with commas, which lets you build up a more realistic, layered depth effect than one shadow alone usually achieves:

.elevated-card {
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.08),
    0 4px 12px rgba(0, 0, 0, 0.10),
    0 12px 24px rgba(0, 0, 0, 0.08);
}

Each shadow in the list is drawn independently, closest-to-the-element first; combining a tight, subtle shadow with a larger, softer one tends to read as more natural depth than a single broad shadow.

radial-gradient()

You've already met linear-gradient() for straight-line color transitions. radial-gradient() works the same way but radiates outward from a center point instead of along a line:

.spotlight {
  background-image: radial-gradient(circle, #fef08a, #f97316);
}

The same color-stop syntax from linear-gradient() applies — you can add as many stops as you like, and pin them to specific positions:

.glow {
  background-image: radial-gradient(
    circle at top left,
    rgba(59, 130, 246, 0.4) 0%,
    transparent 70%
  );
}

circle at top left moves the gradient's center away from the default (the element's own center) to a specific corner — useful for a soft directional glow rather than a centered spotlight.

text-shadow

text-shadow uses the exact same offset/blur/color syntax as box-shadow (minus spread-radius and inset, neither of which apply to text), but draws the shadow behind the glyphs of the text itself rather than around an element's box:

.hero-heading {
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}

Like box-shadow, multiple comma-separated shadows stack — a common trick for a subtle outline effect is two or more offset shadows in different directions layered on the same text.

Try it yourself

Try it yourself
Loading playground...

What to remember

  • border-radius rounds all four corners; 9999px makes a pill, 50% on a square makes a circle, and a slash (50px / 20px) rounds a corner elliptically.
  • box-shadow: offset-x offset-y blur-radius spread-radius color, with inset for a recessed look; comma-separate multiple shadows to stack them for realistic depth.
  • radial-gradient() uses the same color-stop syntax as linear-gradient() but radiates outward from a center point instead of along a line.
  • text-shadow uses the same offset/blur/color syntax as box-shadow, applied to the text itself rather than the element's box.

Discussion

Sign in to post
Sign in to join the conversation.Sign in

No comments yet. Be the first to say something.