JavaScript Vibration API Table

PieceWhat it doesField note
navigator.vibrate(ms)The one methodBuzz for a duration or pattern array ([100,50,100] = on/off/on, ms) - the platform's only direct haptic
cancel = 0The stopvibrate(0), [] or falsy stops a running buzz - the cancel/error path call everyone forgets
10s capThe truncationSingle call capped at 10 seconds - haptics punctuate interactions, they are not ringtones
iOS absenceThe hard truthSafari never shipped it - Taptic Engine has no web path; iOS users get a silent no-op, forever
no promptThe behavioral gateNo dialog - Chrome blocks spammy sites via site settings; restraint is the permission model
haptic grammarThe design10-20ms ticks on confirm, 30/60/30 doubles on warning - felt, not noticed; rhythm over violence
background deathThe hidden-tab ruleChrome throttles/blocks hidden-tab vibration - buzz-after-leave is the Notification API's job
pair itThe fallback lawEvery buzz has a visual/audible twin that carries the meaning alone - vibration is garnish
Reference: the MDN Vibration API. One method, one pattern format, and the platform's clearest support table: Android Chrome yes, iOS never - the rare API whose headline fact is where it does not work.
Bottom line: there is no permission prompt, which means the gate is behavioral - short event-anchored pulses (10-30ms on taps, distinct rhythm per action class) never trip Chrome's abuse blocking, while startup buzzes and eternal patterns earn a site-settings mute. Design for the subset that feels it: feature-detect, cancel what you started, respect the 10-second cap, and pair every buzz with a visual or audible cue that carries the meaning alone - because the iPhone half of your audience never feels a thing.
Related tools: the visibility table (the background-tab rules that kill hidden buzzes), the notifications table (the vibration-capable path after the tab is left), the touch events table (the gestures worth ticking), and the timers table (the re-trigger loop for long alerts).

The Vibration API is one method: navigator.vibrate(pattern) buzzes the phone's motor for a duration or an on/off pattern array ([100, 50, 100] = buzz, pause, buzz, in milliseconds). It is the platform's only direct haptic control, and it is a mobile-only, Android-mostly, honest-by-absence API - the rare spec whose most important fact is a support table with iOS missing entirely.

Bottom line: design for permission by behavior, not by prompt. There is no permission dialog; instead the platform polices abuse structurally - a single vibrate() call is capped at 10 seconds, Firefox requires a user gesture in some contexts, and Chrome lets users block a site's vibrations entirely after the spam threshold. The haptics that feel native are short event-anchored pulses (10-30ms on taps, distinct durations per action class), never patterns that outlive the interaction they confirm.

The honest part: iOS Safari has never implemented the Vibration API - not behind a flag, not partially, since 2011. Every iOS user gets a silent no-op, and no web API can reach the Taptic Engine (there is no iOS haptics web path, full stop). Production code therefore treats vibration as progressive enhancement for a subset of Android users: feature-detect ('vibrate' in navigator), pair it with a visual or audible cue that carries the meaning alone, and never let a UX depend on the buzz arriving.

How to use

  1. Fire the simplest useful pulse: navigator.vibrate(20) on a confirmed action - under 30ms reads as a tick, not an alert. The pattern array alternates vibrate/pause in ms: navigator.vibrate([30, 40, 30]) is a double-tick for 'done but check this'.
  2. Cancel what you started: navigator.vibrate(0) (also [] or any falsy value) stops a running vibration - the cancellation call belongs in your cancel/error paths too, because a stuck motor is the API's most common production bug.
  3. Respect the caps: a single call cannot vibrate longer than 10 seconds (longer patterns get truncated), and repeating alerts need re-triggering per event, not one eternal pattern - which is the browser quietly enforcing that haptics respond to interactions rather than replace ringtones.
  4. Anchor every buzz to a user event or a state change the user caused: form error on submit, step complete in a wizard, timer finished while the tab is hidden (paired with the Notification, since vibration alone in a background tab is Chrome-blockable and easily missed).
  5. Feature-detect and pair: if ('vibrate' in navigator) navigator.vibrate(15); - and ship the visual/auditory equivalent unconditionally. The vibration is a garnish on the signal, never the signal: iOS users, desktop users, and Android users with system-wide haptics disabled all get the same information without it.

Frequently asked questions

Does the Vibration API work on iPhone?

No - and it never has. iOS Safari has omitted navigator.vibrate since the API appeared; the Taptic Engine is reserved for OS-level and native-app haptics, and there is no web path to it (no flag, no prefix, no workaround). Every iOS visitor receives a silent no-op, which makes the API's real audience Android Chrome users. The production consequence is architectural: haptic feedback on the web is progressive enhancement for a platform subset, and the meaning you wanted the buzz to carry must arrive through channels that work everywhere - visual state changes, sounds, notifications. Any check that treats 'vibration supported' as 'iOS device' will be wrong in both directions.

Why does my long vibration pattern get cut off?

The spec caps a single vibrate() call at 10 seconds: longer durations and longer patterns are truncated at the cap. The design intent is that haptics punctuate interactions - they are not ringtones, and a 60-second buzz is a usability hazard the platform refuses to host. If you genuinely need longer signaling (a timer running out, an alarm), the honest pattern is periodic short pulses re-triggered by your timer code, which also lets the user's own actions cancel cleanly. And remember vibration dies with the page: background tabs get throttled or blocked by Chrome entirely, so anything that must buzz after the user leaves the tab is a Notification's job - notifications can carry vibration patterns the OS delivers.

Is there a permission prompt for vibration?

No dialog exists - the gate is behavioral. Chrome tracks whether a site's vibrations are wanted: spammy usage gets the site's haptics blocked from the site-settings menu, and some browsers require the vibration to originate from a user gesture context. The practical design rule is the one native apps learned years ago: short, event-anchored, user-predictable pulses (a tick on confirmation, a double-tap on error) never trip the abuse circuits; startup buzzes, unskippable long patterns, and vibration-as-advertising do. The absence of a prompt is not permission to vibrate - it is the platform betting on your restraint, with a mute button as the backstop.

How do I design vibration patterns that feel native?

Steal the native grammar: ticks are short and relative - 10-20ms for confirmation, a 30/60/30 double-pulse for warnings, and distinct-but-subtle durations per action class so users learn your vocabulary (success differs from error by rhythm, not by violence). Keep everything under 100ms except deliberate alerts; resonate with the visual change at the same instant rather than after it; and never stack patterns back-to-back (the 10-second cap exists because someone did). The subtlety budget matters: haptics are felt, not noticed - if a user can describe your pattern, it is too long. And test on real hardware: desktop Chrome's silent no-op means every 'works on my machine' vibration claim was never tested at all.

Related tools