FORK

Layout

Shadows, spacing scale, radius tokens, and the concentric corner radius formula

Shadows (non-glass fallback)

Small
Cards, list items, inline controls. Subtle lift.
Medium
Popovers, dropdown menus, floating action buttons.
Large
Sheets, modals, full-screen overlays. Maximum elevation.
When to use
  • Shadows/Fallback for iOS 16–25 and Reduce Transparency. Prefer glass when available.
  • Always pair/Shadow + 1px border (separator or cardBorder) for crisp edges on light backgrounds
Platform notes
  • iOS Shadows are fallback for iOS 16–25 and Reduce Transparency. On iOS 26+ prefer glass effects. Use CALayer.shadowPath for performance.
  • Android Use elevation (dp) for shadow: shadowSmall = 2dp, shadowMedium = 6dp, shadowLarge = 12dp. In Compose use Modifier.shadow(elevation = X.dp). In XML use android:elevation.
  • Web Use var(--shadowSmall) etc. via box-shadow. Pair with border: 1px solid var(--border) for crisp edges — shadows alone look soft on light backgrounds.

Spacing & Radius

248121624324864
6 10 14 20 24 full
Corner Curve
Always use Apple's continuous corner curve (CALayer.cornerCurve = .continuous) for all rounded corners. The superellipse produces softer, more organic rounding than circular arcs — a defining characteristic of Apple's visual language since iOS 7.
When to use
  • 2–4/Icon gaps, inline element margins, tight padding
  • 8/Default inner padding, gap between related items
  • 12–16/Card padding, section gaps, cell content insets
  • 24–32/Section spacing, screen margins, group separation
  • 48–64/Major section breaks, hero spacing, scroll content insets
  • radius 6/Small controls (badges, tags, checkboxes). 10 — buttons, inputs, text fields. 14 — list cells, inner cards. 20–24 — cards, sheets, modals. full — pills, avatars, circular buttons
  • cornerCurve/iOS Always .continuous — never circular. Nest with .containerRelative on iOS 26+. Web CSS border-radius is always circular — no superellipse equivalent. The visual difference is subtle at small radii; noticeable at 20px+.
Platform notes
  • iOS Spacing values map 1:1 to pt. Use layout constants, not hardcoded CGFloat. Corner curve must be .continuous — never circular.
  • Android Spacing values map 1:1 from px tokens to dp (space8 = 8dp). For radius, use RoundedCornerShape(X.dp) in Compose or cornerRadius in XML. Android uses circular arcs — no native superellipse, same as Web.
  • Web Use var(--space*) and var(--radius*) tokens. CSS border-radius is always circular — no superellipse equivalent. Visual difference is subtle below 14px.

Concentric Corner Radius

rinner = router − gap
Each nested layer subtracts its inset from the parent radius. All curves share a common center point — the device bezel, the sheet, the card inside it.
Device Screen Radius
iPhone 16 Pro 55pt
iPhone 16 47pt
iPad Pro 18pt
macCatalyst 8pt · 13pt with toolbar
Example — iPhone 16 Pro
Screen 55pt
Sheet (8pt inset) 55 − 8 = 47pt
Card (16pt inset) 47 − 16 = 31pt
Cell (12pt inset) 31 − 12 = 19pt
FenceKit (Bottom Sheet)
Minimum floor 32pt
Full-width = screen radius
Corner curve .continuous (always)
Dynamic read at runtime, never hardcode
API
scene .effectiveCornerRadius
view .concentricCornerRadius(minimumValue:)
view .updateConcentricCornerRadius()
iOS 26+ .containerRelative
When to use
  • Formula/Subtract the gap (padding between layers) from the parent radius. Never eyeball inner radii.
  • Runtime/Always read device radius via effectiveCornerRadius. Different devices, different values.
  • Floor/32pt minimum for sheets. The math can yield smaller values — clamp them.
  • .continuous/Concentric math requires superellipse corners. Circular arcs break the shared-center illusion.
  • iOS 26/.containerRelative does this automatically. Use it for new code, keep manual utilities for pre-26.
  • Web Apply the same rinner = router - gap formula manually in CSS. No container-relative equivalent — calculate and set border-radius per nesting level. Use CSS custom properties to keep it maintainable.
Platform notes
  • iOS Use effectiveCornerRadius to read device screen radius at runtime. iOS 26+ .containerRelative handles concentric math automatically.
  • Android Same formula applies — outer radius minus gap equals inner radius. Use RoundedCornerShape(X.dp) in Compose or cornerRadius in XML shapes. Calculate per nesting level; no automatic container-relative API.
  • Web No container-relative equivalent — calculate border-radius per nesting level manually. Use CSS custom properties to keep values maintainable across breakpoints.