Dennis Hackethal’s avatar

Article

web-haptics: Haptic Feedback Finally Comes to iOS Safari

#4511·​3rd of 4 versions·​latest

lochie just published a package bringing haptic feedback to the web on iOS: web-haptics. I spent four years at Apple working mostly on UIs, so I pay close attention to design and UX. In terms of presentation, use case, and attention to detail, this package comes as close to perfect as I’ve seen.

The problem

On Android, haptics have been available through navigator.vibrate(), but iOS does not support this API. There is a workaround, though – the input element with the switch attribute:

html
<input type="checkbox" switch>

See this switch input in action here. On iOS, the input renders not as a regular checkbox but as a switch that can be toggled on or off:

Switch input

Open the link on your iPhone, tap the switch, and you’ll feel haptic feedback. As far as I know, this is currently the only known practical workaround to trigger haptic feedback on the web in iOS.

Implementation

lochie cleverly bases his package on this single workaround and pushes it to its limits. The key lines are here, creating a switch input on the fly:

js (rendered as javascript)
const hapticCheckbox = document.createElement("input");
hapticCheckbox.type = "checkbox";
hapticCheckbox.setAttribute("switch", "");

The package also creates an associated label and clicks it to trigger haptic feedback on the connected input:

js (rendered as javascript)
this.hapticLabel.click();

(My understanding is that iOS will not trigger the haptic feedback when the input is programmatically clicked – so the ‘workaround within the workaround’ is to click the associated label instead.)

Custom haptics (!)

But web-haptics can do more than just trigger a single haptic ‘pulse’. The trigger function lets you pass in your own patterns with pulses of different duration and intensity, and even delays.

Want a simple success haptic? Trigger two pulses, as shown on the package homepage:

js (rendered as javascript)
trigger([
{ duration: 30 },
{ delay: 60, duration: 40, intensity: 1 },
])

Or simply call trigger('success') as a shortcut.

Here’s an error haptic I made based on Apple’s human interface guidelines:

js (rendered as javascript)
trigger([
{ duration: 40, intensity: 0.7 },
{ delay: 40, duration: 40, intensity: 0.7 },
{ delay: 40, duration: 40, intensity: 0.9 },
{ delay: 40, duration: 50, intensity: 0.6 },
])

lochie’s website even gives you an editor to make custom haptics. As you click and drag, both pulses and code update in real time. This experience is developer bliss:

Haptic editor

Usage

Importing the package is easy. In Rails, for example:

rb (rendered as ruby)
# config/importmap.rb
pin "web-haptics", to: "https://esm.sh/web-haptics@0.0.6"
js (rendered as javascript)
import { WebHaptics } from 'web-haptics';
// In a Stimulus controller somewhere
let haptics = new WebHaptics();
haptics.trigger('success'); // or 'error', 'warning', etc for built-in haptics
haptics.trigger([
{ duration: 40, intensity: 0.7 },
{ delay: 40, duration: 40, intensity: 0.7 },
])

Pass a debug option to the constructor to hear clicks in development/on desktop:

js (rendered as javascript)
new WebHaptics({ debug: true });

Again, this package comes as close to perfect as I’ve seen. In fact, I already use it on Veritula: as you type in a text field, an error haptic plays when you exceed the max length (#4473).

I highly recommend web-haptics by lochie.

Can you refute this article?

Nobody has criticized the article yet. One criticism nobody can answer is enough to make it no longer rationally adoptable.

More articles

Veritula for Programmers

Programmers already know the rule Veritula runs on. A pull request with unresolved review comments shouldn’t get merged. On Veritula, an idea is rationally adoptable only if it has no pending criticisms, and a criticism is pending if it…

Dennis Hackethal·​Nov 2, 2026·​No pending criticisms

5 Minute Creativity

TL;DR: When making a decision or working to solve a problem, spend 5 minutes (using a timer) just coming up with ideas. Managing your attention like this can supercharge your creativity. A few days ago I was helping a friend flesh out an…

Benjamin Davies·​Feb 28, 2026·​No pending criticisms

In Defense of Ambition

Until about a week ago, when I debated this with my friend Tom Hyde, it seemed incredibly obvious to me that wanting to be rich is rational but I could not explain why. Fundamentally I agree with Popper and Deutsch that all life is problem…

Moritz Wallawitsch·​Oct 17, 2026·​No pending criticisms
  • Rationally adoptable.
  • Not rationally adoptable.
  • Older versions with pending criticisms.
  • Ideas are blue, criticisms red, comments small and gray.
  • Hover over ideas to expand them.
  • Click on ideas to jump to their place in the discussion.