Claymorphism Design Language System
Soft polymer surfaces, tinted shadows, and generous curves for web and mobile. Tokens ship as CSS custom properties, a Tailwind config, and Figma effect styles.
1. Design philosophy
Every element is soft polymer clay, extruded and pressed onto a sheet of the same material. Light comes from the top-left; the bottom-right curves into tinted shade.
Friendly
Rounded everything. Warm, conversational copy. No hard black lines.
Tactile
Raised means actionable. Hover lifts, press squashes into the surface.
Playful
Spring motion, pastel accents, slightly exaggerated proportions.
Accessible
Softness lives in surfaces. Text and state signals stay high-contrast.
Six principles
| Principle | Rule |
|---|---|
| One light source | Top-left, always. Highlights top-left, shade bottom-right. |
| Three shadows | Outer drop + inner shade + inner highlight on every clay object. |
| Tint shadows | Shadow color comes from the surface hue, never plain grey or black. |
| Round generously | When in doubt, add more radius. |
| Depth means something | Raised = actionable, flat = passive, inset = input or pressed. |
| Depth never stands alone | Pair every shadow cue with a border, icon, label, or color that meets WCAG. |
2. Color & surface tokens
Surfaces
| Token | Light | Dark | Role |
|---|---|---|---|
--clay-bg | #EFEDFA | #1B1930 | Page canvas |
--clay-bg-muted | #E6E3F6 | #15132A | Wells, bands |
--clay-surface | #F7F5FF | #2A2748 | Cards, buttons |
--clay-surface-raised | #FBFAFF | #34315A | Modals, popovers |
--clay-surface-sunken | #E9E6F8 | #201E3C | Inputs, pressed |
--clay-border | #807BA8 | #9A96C8 | Functional borders (3:1+) |
--clay-border-subtle | #D9D5F0 | #3B3866 | Decorative dividers |
--clay-text | #2D2A4A | #EDEBFF | Primary text, ~11.7:1 |
--clay-text-secondary | #5B5780 | #B9B5E0 | Secondary text, ~5.8:1 |
--clay-shadow | 93 80 170 | 6 4 22 | Shadow RGB triplet |
Pastel accents
Use pastel fills with dark text. Each accent carries its own shadow triplet so the shading matches the hue.
Solid actions (white text)
3. Clay effect math & layering
Every clay shadow is three layers. Let D be the elevation distance in px.
| Layer | Offset | Blur | Alpha (light) | Alpha (dark) |
|---|---|---|---|---|
| A. Outer drop | D, D | 2.2 × D | 0.16 to 0.24 | 0.45 to 0.60 |
| B. Inner shade | inset -0.6D -0.6D | 1.2 × D | 0.12 to 0.20 | 0.30 to 0.40 |
| C. Inner highlight | inset 0.6D 0.6D | 1.2 × D | 0.80 to 0.95 | 0.06 to 0.10 |
Elevation scale
Toggle dark mode to watch the shadows deepen while the highlight fades to a rim light.
Token code
--clay-elev-2:
10px 10px 24px rgb(var(--clay-shadow) / .20), /* outer drop */
inset -6px -6px 12px rgb(var(--clay-shadow) / .16), /* inner shade */
inset 6px 6px 12px rgb(var(--clay-highlight) / .90); /* inner highlight */
--clay-pressed:
2px 2px 6px rgb(var(--clay-shadow) / .12),
inset 6px 6px 14px rgb(var(--clay-shadow) / .28),
inset -4px -4px 10px rgb(var(--clay-highlight) / .70);
--clay-inset:
inset 5px 5px 12px rgb(var(--clay-shadow) / .20),
inset -5px -5px 12px rgb(var(--clay-highlight) / .90);
/* Tint per accent */
.clay-tint-mint { --clay-shadow: 60 160 120; }The full set of light and dark tokens, the Tailwind config, and the Figma mapping are in the downloadable markdown.
Border radius
Radius is at least 35% of the shorter side. Controls up to 64px tall are pills. Nested radius equals outer radius minus padding (minimum 8px). No sharp corners anywhere.
Tailwind usage
<button class="h-12 px-7 rounded-full bg-clay-primary text-white font-bold
shadow-clay-2 hover:-translate-y-0.5 hover:shadow-clay-3
active:translate-y-0.5 active:shadow-clay-pressed">
Get started
</button>4. Typography & hierarchy
Fredoka for display, Nunito for body and UI, JetBrains Mono for code. Body weight stays at 500 or above because soft backgrounds already lower perceived contrast.
60 / 1.05Squishy
36 / 1.15Section title
30 / 1.2Subsection title
24 / 1.25Card title
18 / 1.6Lead paragraph with comfortable rhythm.
16 / 1.6Default text for interface and reading.
14 / 1.5Helper text and secondary detail.
14 / 1.2Button and form label
12 / 1.4Badge and meta text
Readability rules
- Never place text on inner-shadow zones; keep 16px or more of padding from edges.
- Hold lines to 60 to 72 characters. Skip text-shadow entirely.
- Use
remandmin-heightso text scales with user settings. - Quicksand works only at weight 600+ and 16px+; thin strokes vanish on pastel.
5. Components
Everything below is live. Hover, press, tab through, and toggle dark mode.
Buttons
| State | Transform | Shadow | Surface |
|---|---|---|---|
| Default | none | elev-2 | primary, white text |
| Hover | translateY(-2px) scale(1.02) | elev-3 | primary-hover |
| Active | translateY(2px) scale(.98) | pressed | primary-pressed |
| Focus-visible | none | unchanged | 3px outline, 3px offset |
| Disabled | none | flat | sunken, secondary text |
Cards & containers
Elevated
elev-2, lifts to elev-3 on hover and sinks on press. Use for clickable tiles.
Flat
Soft rim only. Use for passive groupings and settings sections.
Hero / modal
elev-4 with a 40px radius. Use for dialogs and sheets.
Tinted
Pastel fill, matching shadow hue, dark text.
Inputs & textareas
Badges, tags & switch
6. Accessibility & usability
Shadows are decoration. Contrast, borders, icons, and text carry meaning.
Verified pairs
| Foreground | Background | Ratio | Result |
|---|---|---|---|
| #2D2A4A | #EFEDFA | 11.7:1 | Pass (AAA) |
| #5B5780 | #EFEDFA | 5.8:1 | Pass (AA) |
| #FFFFFF | #6355E0 | 5.4:1 | Pass (AA) |
| #2D2A4A | #C9C1F7 | 8.1:1 | Pass (AAA) |
| #C0264B | #EFEDFA | 5.0:1 | Pass (AA) |
| #1F7A55 | #EFEDFA | 4.6:1 | Pass (AA) |
| #807BA8 border | #EFEDFA | 3.4:1 | Pass (non-text) |
| #3B2FC9 focus | #EFEDFA | 7.4:1 | Pass (non-text) |
| #FFFFFF | #C9C1F7 | ~1.8:1 | Fail: never white on pastel |
Ratios are rounded estimates. Re-verify final values with a contrast checker.
Focus rings and error states
Focus uses outline
Clay shadows already use box-shadow, so focus is a 3px outline with a 3px offset. It stays independent of elevation and survives forced-colors mode.
Errors use four cues
A 2px status border, a 20px icon, message text linked with aria-describedby, and an optional light tint. Never color alone.
Keep soft surfaces distinct
Give inputs and toggles a 3:1 border. Keep a 4 to 6% luminance gap between surface and background. Pair selection with a fill change or aria-pressed.
Respect preferences
Handle prefers-reduced-motion, prefers-contrast, and forced-colors. Shadows vanish in forced colors, so borders must exist.
Checklist
- Text meets 4.5:1 (3:1 large) on the actual surface, including tinted cards.
- No white text on pastel fills.
- Inputs, toggles, and checkboxes have 3:1+ borders.
- Focus uses outline, 3px or more, with offset.
- Touch targets are 44px or larger with 8px spacing.
- Dark-mode shadows are darker than the surface.
- Hover, pressed, and focus read without shadows.
- Max three shadow layers per element; animate
transform, notbox-shadow, in long lists. - Test on OLED at low brightness and outdoors.