Apple Design — Fluid Interfaces for the Web
Translates Apple's approach to fluid, physical motion for the web, based on WWDC 2018
"Designing Fluid Interfaces" and Apple HIG. Use when building or reviewing gesture-driven
UI, spring animations, drag/swipe/sheet interactions, momentum physics, or translucent
materials.
17 Design Principles
Feedback & Response
- Instant visual feedback —
:active { transform: scale(0.98) } on every press
- Haptics-approximating — spring response 0.3–0.5s mimics physical feel
- Push, don't jump — content transitions use push/cover semantic directions
Physics
- Spring default: critical damping —
damping: 1.0, response: 0.4 for standard moves
- Sheets and drawers — lighter:
damping: 0.8, response: 0.3
- Momentum projection —
project(velocity, decay=0.998) for gesture release
- Velocity transfer —
relativeVelocity = gestureVelocity / (targetPosition − currentPosition)
Interruptibility
- All animations must be gesture-interruptible — never
await animation.finished alone
- Rubber-band at boundaries — scroll/pan resistance at edges, not hard stops
- Cancel previous —
animation.cancel() before starting a new one on the same property
Spatial Consistency
- Mirror-path transitions — enter animation path = reverse of exit path
- Consistent source of motion — elements appear from and return to their origin
Materials & Depth
- Translucency over opacity —
backdrop-filter: blur(24px) saturate(180%) for nav bars
- Content scrolls under material — not over it; use
position: sticky on shell
- Three depth planes — foreground (gestures), midground (content), background (chrome)
Typography
- Optical sizing — large display text tighter tracking (
-0.03em), body near zero
- Dynamic type scale — respect user's preferred content size where possible
Spring Parameters Reference
| Component |
Damping |
Response |
Mass |
| Standard move |
1.0 |
0.4 |
1.0 |
| Sheet / Drawer |
0.8 |
0.3 |
1.0 |
| Light bounce |
0.7 |
0.45 |
1.0 |
| Snappy |
1.0 |
0.2 |
1.0 |
Formula for spring-to-css: stiffness = mass × (2π / response)², dampingRatio = dampingCoefficient / (2 × √(mass × stiffness))
Material Specs
| Layer |
Backdrop Blur |
Saturation |
Background |
| Toolbar / Nav |
24px |
180% |
rgba(255,255,255,0.72) |
| Sheet / Card surface |
12px |
150% |
rgba(255,255,255,0.60) |
| System chrome |
8px |
120% |
rgba(0,0,0,0.08) |
Dark mode: swap white backgrounds for rgba(28,28,30,0.82) with same blur values.
Reduced Motion
@media (prefers-reduced-motion: reduce) {
* { animation-duration: 0.01ms !important; }
}
Always provide a cross-fade alternative instead of slide/spring when motion is reduced.
Interactive Gesture Targets
| Target size |
Minimum |
Recommended |
| Touch |
44×44px |
48×48px |
| Pointer |
24×24px |
32×32px |
Compatibility
See references/compatibility.md for orthogonality with taste-anti-slop, gsap-animation,
and improve-animations. Load order: taste-anti-slop → apple-design → gsap-animation.
Checklist
1---2name: apple-design3description: Apple's approach to interface design and fluid, physical motion, translated for the web. Use when building or reviewing gesture-driven UI, spring animations, drag/swipe/sheet interactions, momentum and interruptible transitions, translucent materials and depth, typography (optical sizing, tracking, leading), reduced-motion, or the design foundations (feedback, spatial consistency, restraint) behind Apple-style interfaces. Also applies to any HTML-rendered output with interactive elements — investor decks, annual reports, product pages, slide presentations (Reveal.js, Guizang PPT), interactive documents, and landing pages that need premium feel beyond static aesthetics. Not for static Word/PDF generation (typography rules only).4---56# Apple Design — Fluid Interfaces for the Web78Translates Apple's approach to fluid, physical motion for the web, based on WWDC 20189"Designing Fluid Interfaces" and Apple HIG. Use when building or reviewing gesture-driven10UI, spring animations, drag/swipe/sheet interactions, momentum physics, or translucent11materials.1213## 17 Design Principles1415### Feedback & Response161. **Instant visual feedback** — `:active { transform: scale(0.98) }` on every press172. **Haptics-approximating** — spring response 0.3–0.5s mimics physical feel183. **Push, don't jump** — content transitions use push/cover semantic directions1920### Physics214. **Spring default: critical damping** — `damping: 1.0, response: 0.4` for standard moves225. **Sheets and drawers** — lighter: `damping: 0.8, response: 0.3`236. **Momentum projection** — `project(velocity, decay=0.998)` for gesture release247. **Velocity transfer** — `relativeVelocity = gestureVelocity / (targetPosition − currentPosition)`2526### Interruptibility278. **All animations must be gesture-interruptible** — never `await animation.finished` alone289. **Rubber-band at boundaries** — scroll/pan resistance at edges, not hard stops2910. **Cancel previous** — `animation.cancel()` before starting a new one on the same property3031### Spatial Consistency3211. **Mirror-path transitions** — enter animation path = reverse of exit path3312. **Consistent source of motion** — elements appear from and return to their origin3435### Materials & Depth3613. **Translucency over opacity** — `backdrop-filter: blur(24px) saturate(180%)` for nav bars3714. **Content scrolls under material** — not over it; use `position: sticky` on shell3815. **Three depth planes** — foreground (gestures), midground (content), background (chrome)3940### Typography4116. **Optical sizing** — large display text tighter tracking (`-0.03em`), body near zero4217. **Dynamic type scale** — respect user's preferred content size where possible4344## Spring Parameters Reference4546| Component | Damping | Response | Mass |47|---|---|---|---|48| Standard move | 1.0 | 0.4 | 1.0 |49| Sheet / Drawer | 0.8 | 0.3 | 1.0 |50| Light bounce | 0.7 | 0.45 | 1.0 |51| Snappy | 1.0 | 0.2 | 1.0 |5253Formula for spring-to-css: `stiffness = mass × (2π / response)²`, `dampingRatio = dampingCoefficient / (2 × √(mass × stiffness))`5455## Material Specs5657| Layer | Backdrop Blur | Saturation | Background |58|---|---|---|---|59| Toolbar / Nav | 24px | 180% | rgba(255,255,255,0.72) |60| Sheet / Card surface | 12px | 150% | rgba(255,255,255,0.60) |61| System chrome | 8px | 120% | rgba(0,0,0,0.08) |6263Dark mode: swap white backgrounds for `rgba(28,28,30,0.82)` with same blur values.6465## Reduced Motion6667```css68@media (prefers-reduced-motion: reduce) {69 * { animation-duration: 0.01ms !important; }70}71```7273Always provide a cross-fade alternative instead of slide/spring when motion is reduced.7475## Interactive Gesture Targets7677| Target size | Minimum | Recommended |78|---|---|---|79| Touch | 44×44px | 48×48px |80| Pointer | 24×24px | 32×32px |8182## Compatibility8384See `references/compatibility.md` for orthogonality with `taste-anti-slop`, `gsap-animation`,85and `improve-animations`. Load order: taste-anti-slop → apple-design → gsap-animation.8687## Checklist8889- [ ] `:active` scale feedback on all tappable elements90- [ ] Spring defaults documented (damping, response) for each animation91- [ ] Gesture velocity transferred to animation on release92- [ ] All animations cancellable (interruptible)93- [ ] `prefers-reduced-motion` handled with cross-fade fallback94- [ ] Materials use `backdrop-filter`, not opacity95- [ ] Navigation ≤ 80px height, single row96- [ ] Touch targets ≥ 44×44px