watchOS Design Guidelines
Apple Watch is a personal, glanceable device worn on the wrist. Interactions are measured in seconds, not minutes. Every design decision must prioritize speed of comprehension and brevity of interaction.
1. Glanceable Design (CRITICAL)
The defining constraint of watchOS. If a user cannot extract the key information within 2 seconds of raising their wrist, the design has failed.
Rules
- W-GL-01: Primary information must be visible without scrolling. The first screen is the only guaranteed screen.
- W-GL-02: Target interaction sessions of 5 seconds or less. Design for raise-glance-lower.
- W-GL-03: Use large, high-contrast text. Minimum effective body text is 16pt (system font). Titles should be 18pt or larger.
- W-GL-04: Limit text to essential content. Truncate or abbreviate aggressively. Use SF Symbols instead of text labels where meaning is unambiguous.
- W-GL-05: Respect wrist-down time. When the wrist lowers, the app enters an inactive state. Do not assume continuous user attention.
- W-GL-06: Prioritize a single piece of information per screen. If showing multiple data points, establish clear visual hierarchy with size, weight, and color.
Screen Dimensions Reference
| Device |
Screen Width |
Screen Height |
Corner Radius |
| 41mm (Series 9) |
176px |
215px |
36px |
| 45mm (Series 9) |
198px |
242px |
39px |
| 42mm (Series 10) |
180px |
220px |
37px |
| 46mm (Series 10) |
205px |
251px |
40px |
| 49mm (Ultra 2) |
205px |
251px |
40px |
Anti-Patterns
- Walls of text requiring scroll to understand context
- Small, dense data tables
- Requiring multiple taps before showing useful information
- Replicating an iPhone screen layout on Watch
2. Digital Crown (HIGH)
The Digital Crown is the primary physical input for scrolling and precise value selection. It provides haptic feedback and should feel purposeful.
Rules
- W-DC-01: Use the Digital Crown as the primary scroll mechanism for vertical content. Do not rely solely on swipe gestures for scrolling.
- W-DC-02: For value pickers (time, quantity, sliders), bind the Crown to precise adjustments with haptic detents at each discrete value.
- W-DC-03: Do not override or conflict with system Crown behaviors. The system uses the Crown for volume control during media playback, scrolling in system UI, and Time Travel in complications.
- W-DC-04: Provide visual feedback synchronized with Crown rotation. The UI must respond frame-by-frame to Crown input with no perceptible lag.
- W-DC-05: Update on each Crown increment. Values, selection, and highlight states should move with each detent. Do not debounce Crown input until the gesture ends.
Correct โ Crown binding with haptic detents:
struct VolumePickerView: View {
@State private var volume: Double = 0.5
var body: some View {
VStack {
Text("\(Int(volume * 100))%")
.font(.title.bold())
Image(systemName: "speaker.wave.3")
}
.focusable()
.digitalCrownRotation(
$volume,
from: 0.0,
through: 1.0,
by: 0.05,
sensitivity: .medium,
isContinuous: false,
isHapticFeedbackEnabled: true
)
}
}
Incorrect โ ignoring the Crown and forcing touch-only interaction:
struct VolumePickerView: View {
@State private var volume: Double = 0.5
var body: some View {
Slider(value: $volume)
}
}
Anti-Patterns
- Ignoring the Crown and forcing all interaction through touch
- Custom Crown behaviors that conflict with system expectations
- Missing haptic feedback on discrete value changes
- Laggy or batched responses to Crown rotation
3. Navigation (HIGH)
Watch navigation must be shallow and predictable. Users should never feel lost or unable to return to a known state.
Rules
- W-NV-01: Use vertical page scrolling as the default content navigation pattern. Pages scroll top-to-bottom with the Digital Crown.
- W-NV-02: Use
TabView for top-level sections (max 5 tabs). Swipe horizontally between tabs. Each tab is a distinct functional area.
- W-NV-03: Use
NavigationStack for hierarchical drill-down. Limit hierarchy to 2-3 levels maximum. Every pushed view must have a back button (provided automatically by the system).
- W-NV-04: Avoid modal sheets for primary flows. Modals should be reserved for focused, single-purpose tasks (e.g., confirmation, quick input).
- W-NV-05: The app's most important action should be reachable within 1 tap from launch. Do not bury primary functionality behind menus or navigation.
Navigation Pattern Reference
| Pattern |
Use Case |
Gesture |
| Vertical scroll |
Long-form content within a single view |
Digital Crown / swipe up-down |
| TabView (horizontal pages) |
Top-level app sections |
Swipe left-right |
| NavigationStack (push/pop) |
Hierarchical drill-down |
Tap to push, swipe right or back button to pop |
| Modal sheet |
Confirmation, focused input |
Presented programmatically, dismiss via button or swipe down |
Anti-Patterns
- Deep navigation hierarchies (4+ levels)
- Hamburger menus or hidden navigation drawers
- Tab bars with more than 5 items
- Forcing users to scroll through long lists to find key actions
4. Complications (HIGH)
Complications are the most visible surface of a Watch app. They live on the watch face and provide at-a-glance data without launching the app.
Rules
- W-CP-01: Support multiple complication families to maximize watch face compatibility. At minimum support
accessoryCircular, accessoryCorner, and accessoryRectangular (WidgetKit, watchOS 9+).
- W-CP-02: Provide both tinted (single-color) and full-color variants. Tinted complications must remain legible when the system applies a single tint color.
- W-CP-03: Update complications via
TimelineProvider. Provide future timeline entries when data is predictable (e.g., next calendar event, weather forecast). Keep data fresh -- stale complications erode trust.
- W-CP-04: Complication content must be meaningful without context. A user glancing at their watch face should immediately understand the data (e.g., "72F" not "72").
- W-CP-05: Tapping a complication must launch the app to a relevant context, not just the app's root view.
Correct โ WidgetKit TimelineProvider for an accessoryCircular complication:
struct StepCountProvider: TimelineProvider {
func placeholder(in context: Context) -> StepEntry {
StepEntry(date: Date(), steps: 5000)
}
func getSnapshot(in context: Context, completion: @escaping (StepEntry) -> Void) {
completion(StepEntry(date: Date(), steps: HealthStore.shared.todaySteps))
}
func getTimeline(in context: Context, completion: @escaping (Timeline<StepEntry>) -> Void) {
let entry = StepEntry(date: Date(), steps: HealthStore.shared.todaySteps)
let nextUpdate = Calendar.current.date(byAdding: .minute, value: 15, to: Date())!
completion(Timeline(entries: [entry], policy: .after(nextUpdate)))
}
}
struct StepCountComplicationView: View {
let entry: StepEntry
var body: some View {
Gauge(value: Double(entry.steps), in: 0...10000) {
Image(systemName: "figure.walk")
} currentValueLabel: {
Text("\(entry.steps / 1000)k")
}
.gaugeStyle(.accessoryCircular)
}
}
Complication Family Reference
Use WidgetFamily values:
| Family |
Shape |
Typical Content |
accessoryCircular |
Small circle |
Single value, icon, or gauge |
accessoryCorner |
Curved, top corners |
Gauge with label, or text with icon |
accessoryRectangular |
Wide rectangle |
Multi-line text, chart, or detailed view |
accessoryInline |
Text row |
Short label or value |
Anti-Patterns
- Supporting only one complication family
- Stale data that does not update for hours
- Complication tap landing on generic app home instead of relevant content
- Illegible complications in tinted mode (insufficient contrast)
5. Always On Display (MEDIUM)
When the user's wrist is down, watchOS enters an Always On state showing a dimmed version of the current app. This must be handled intentionally.
Rules
- W-AO-01: Reduce visual complexity in the Always On state. Remove animations, secondary UI elements, and non-essential detail. Keep only the most critical information visible.
- W-AO-02: Hide sensitive or private data (e.g., message content, health details, financial information) in the dimmed state. Use redacted or placeholder content.
- W-AO-03: Reduce update frequency in Always On. Update the display no more than once per minute. Use
TimelineView with a .everyMinute schedule for time-sensitive content.
- W-AO-04: Use the system-provided dimming behaviors. Do not implement custom dimming. The sy