Skip to content
ExamsLibraryFor agentsConnect your agent

Shadows, borders and corners

beginner·8 min·Markdown for agents

What this lesson teaches

Lift surfaces with shadows that whisper, separate them with borders, nest rounded corners correctly, and trust your eye over the ruler.

  1. 1Shadows should whisper
  2. 2Shadows raise; borders separate
  3. 3Corners: a scale, and the nesting rule
  4. 4Trust your eye over the ruler

Four ways to lift the same card. Start on "The default", then try "Whisper".

Mira Okafor

Commented on Homepage v3

RenameDuplicateMove to…
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);

Not wrong, just everywhere. One flat blur at 10% reads as a template.

The heavy one announces. The whisper you feel without seeing.

0 2px 8px rgba(0, 0, 0, 0.1) is the most copied shadow on the web. Nothing is wrong with it except that it is everywhere, so it reads as "template".

Shadows should whisper

A shadow's job is to hint that a surface floats, which designers call . If you can clearly see a soft gray blur, it's too strong.

The fix is a : several faint shadows stacked in one declaration.

--shadow-md:
  0 1px 2px  rgba(17, 17, 17, 0.05),
  0 4px 8px  rgba(17, 17, 17, 0.05),
  0 8px 24px rgba(17, 17, 17, 0.04);

What makes it work:

  • Several layers at different blurs (2px, 8px, 24px) read as physical depth. One big blur looks flat.
  • Opacity at 4–6%, not 10%. This is the part most people get wrong.
  • A near-black base like #111, not pure black.
  • The y-offset never bigger than the blur.

Build at least three, for three heights: cards (+1), dropdowns and popovers (+2), dialogs (+3).

Shadows raise; borders separate

Pick by the job the line is doing.

  • Raised things (cards, menus, popovers, dialogs) get a shadow. Because a shadow is see-through, one token works over any background.
  • Separated things (table rows, list dividers, input edges) keep a border. A visible input edge is an accessibility feature.

The rule is about elevation, not every line. An agent that reads "use shadows instead of borders" and strips the edges off inputs and table cells has made the UI worse. And use one depth cue per surface: border plus shadow plus ring plus gradient on one card is hedging.

A few finishing lines from Emil Kowalski's practice:

  • at 0.5px on high-density screens, 1px elsewhere. Retina dividers at 1px look heavy.
  • Every image gets a 1px inset outline in pure black (or white in dark) at 10%. A tinted gray picks up the background and looks like grime.
  • Fade with mask-image, not a gradient laid on top, and never fade content people are scrolling toward.

Corners: a scale, and the nesting rule

is a personality dial. The same radius on everything is lazy; a small scale used on purpose looks crafted.

--radius-sm: 4px;   /* badges */
--radius-md: 8px;   /* inputs, small buttons */
--radius-lg: 12px;  /* cards */
--radius-xl: 16px;  /* modals */
--radius-full: 9999px; /* pills, avatars */

Mixing far-apart sizes (4px badges in a 16px modal) is fine. Mixing near ones (4px and 8px side by side) looks like a mistake. And if a button is a pill, everything inside it commits to the pill too.

Now the rule people miss most. When a rounded box sits inside another, the inner radius isn't the same as the outer one. It's smaller, by the gap:

inner radius = outer radius − padding

inner = 20px (copied)
Turn the rule off and watch the corners pinch. Past about 24px of gap, the two surfaces read as separate.

With equal radii, the gap between the two curves gets thinner at each corner and the inner box seems to bulge. With the subtraction, the curves run parallel. Copying the parent's radius is the single most frequent giveaway of an unpolished UI.

Trust your eye over the ruler

Perfect math sometimes looks wrong. A triangle centered by its bounding box looks shoved left, because most of its box is empty. A circle the same height as a square looks smaller, because it doesn't fill its corners.

Box centered: the triangle looks shoved left
Same 48px height: the circle looks smaller
Mathematical versus optical. The guides show the math; the right-hand version is what designers ship.

The fix is : nudge until it looks right. The play glyph moves a pixel or two right; the circle grows about 5%. If it looks wrong, it is wrong.

The same idea, a little imperfection on purpose, extends further on marketing pages: a faint paper-grain texture instead of a flat fill, a hand-drawn stroke, an asymmetric layout that feels composed. Keep it there. Inside the product (forms, tables, settings) consistency wins, and "imperfect" just means "broken".

Fix shadows and corners· for your agent
Review the surfaces in this component:
- Replace any single-blur box-shadow with our layered tokens (--shadow-sm/md/lg: 2–3 layers, 4–6% opacity, base #111, y-offset ≤ blur).
- Shadows only on raised surfaces (cards, menus, dialogs). Keep borders on inputs, table cells and dividers.
- One depth cue per surface.
- Nested rounded elements: inner radius = outer radius − padding.
- Images get outline: 1px solid rgb(0 0 0 / .1) with outline-offset: -1px.
Return a Before | After | Why table.

Quick check

A dialog has border-radius 16px and padding 6px. What radius should the panel inside it get?

What this lesson builds on and leads to, across every course.

  • Routing the job
  • Make the skill yours
  • Color you can do math with
  • Designing a dark theme
  • The page frame, on every screen
  • Glass and layers