Web Vibration API: Haptik auf Android und iPhone

Ein Tap soll unter dem Daumen ticken wie in einer nativen App, also greifst du zur Web Vibration API. Auf einem Android-Smartphone klappt navigator.vibrate(10) beim ersten Versuch. Auf dem iPhone passiert nichts, auf dem Laptop gibt der Aufruf true zurück und es passiert ebenfalls nichts, und der iPhone-Workaround, den du auf GitHub gefunden hast, funktioniert seit iOS 26.5 nicht mehr. Dieses Tutorial zeigt, was eine Seite im Oktober 2026 wirklich auslösen kann, baut einen Helper, der überall still bleibt, wo er nichts abspielen kann, und baut Haptik in React in einen Switch, einen Button und einen Wheel Picker ein.
Was kann die Web Vibration API 2026?
Sie schaltet den Vibrationsmotor für die Millisekunden an und aus, die du angibst, und zwar in Chromium-Browsern auf Android, sobald jemand die Seite angetippt hat. Das ist die ganze API: eine Methode, navigator.vibrate, die eine Zahl oder ein Array aus abwechselnden Vibrations- und Pausenzeiten nimmt. Es gibt keine Intensität, keine Wellenform und keinen Weg, zu fragen, ob das Gerät überhaupt einen Motor hat. Software Mansions Überblick über Web-Haptik vom August 2026 (opens in a new tab) fasst den Stand in einem Satz zusammen: Praktisch beschränkt sich die Vibration API auf Browser, die auf Chromium basieren.
Hier siehst du, wo ein Tick wirklich beim Finger ankommt, Stand Oktober 2026 (caniuse (opens in a new tab) für den Support, unser eigener Test in Chromium auf dem Desktop für die letzte Zeile):
Die letzte Zeile ist die Falle. Feature Detection mit "vibrate" in navigator sagt in Chrome auf dem Desktop ja, verrät also nichts über die Hardware. Der Boolean, den navigator.vibrate() zurückgibt, sagt nur, dass der Browser das Muster angenommen hat. Ob es jemand gespürt hat, sagt er nicht.
Wie verhält sich navigator.vibrate auf Android?
Es spielt das übergebene Muster ab und ersetzt jedes Muster, das gerade läuft. Die Grenzen dafür kannst du im Vibration Controller (opens in a new tab) von Chromium nachlesen:
- Erst muss ein Tap kommen. MDN (opens in a new tab) nennt Sticky User Activation als Voraussetzung. Bis die Seite einen Tap, einen Klick oder einen Tastendruck gesehen hat, gibt Chrome
falsezurück und loggtBlocked call to navigator.vibrate because user hasn't tapped on the frame or any embedded frame yet. Ist die Aktivierung einmal da, hält sie, bis die Seite navigiert. Ein Tick aus einem Scroll-Handler oder nach einemawaitfunktioniert danach also. - Im Hintergrund bleibt es still. Der Aufruf gibt
falsezurück, solange die Seite verborgen ist. - Lange Muster werden gekürzt. Chromium begrenzt jeden Eintrag auf 10.000ms, behält die ersten 99 Einträge und verwirft eine abschließende Pause.
- Das Smartphone kann dich überstimmen. MDN weist darauf hin, dass manche Geräte im Lautlos- oder Nicht-stören-Modus nicht vibrieren.
Halt die Pulse kurz; der Helper unten nutzt 4 bis 22ms pro Puls. Das Brummen von 200ms, das viele Beispiele nutzen (auch das erste bei MDN), fühlt sich wie eine Benachrichtigung an. Für einen Toggle ist das die falsche Botschaft.
Funktioniert die Web Vibration API auf iOS?
Nein. Safari hat navigator.vibrate nie implementiert, und caniuse führt bis 27.2 keine Safari-Version auf iOS damit. Wer nach Vibration API iPhone Support sucht, landet bei genau einem Workaround: Safari 17.4 hat ein natives Switch-Control eingeführt, <input type="checkbox" switch> (Ankündigung von WebKit (opens in a new tab)), und das Umschalten spielt den haptischen System-Tick ab.
Bis iOS 26.5 haben Bibliotheken wie ios-haptics diesen Tick auf Abruf ausgelöst, indem sie .click() auf einem versteckten Label aufriefen, das mit dem Switch verbunden war. Das funktioniert nicht mehr. Laut der README von ios-haptics vom April 2026 (opens in a new tab) klappt der Trick nur noch auf iOS 17.4 bis 26.4, weil Apple ihn in iOS 26.5 gepatcht hat. Der WebKit-Fix (opens in a new tab), am 21. Mai 2026 in den Main-Branch gemergt, schließt diese Lücke: WebKit verlangte für die Haptik schon User Activation und verlangt jetzt zusätzlich ein Trusted Event. Ein Klick, den label.click() weiterreicht, ist das nicht mehr.
Was weiter funktioniert, ist ein echter Tap, der auf einem Label für den Switch landet. Der Tap erzeugt einen Trusted Click, das Label reicht ihn an den Switch weiter, und weil der ursprüngliche Klick trusted war, lässt die Änderung in WebKit den Switch trotzdem ticken. Der Quellcode von ios-haptics (opens in a new tab) ist am 22. September 2026 genau darauf umgestiegen: Er legt ein transparentes Label über dein Element. Hier dieselbe Idee als Komponente für React 19:
Setz es in Buttons ein, nicht in Links: In unserem Test in Chromium hat ein Label in einem <a> zwar das onClick des Links ausgeführt, aber die Standardaktion übernommen, und der Link hat nie navigiert. Gib dem Input keinen name, damit er nie in einem Formular-Submit landet. Außerhalb von iOS schaltet ein Tap darauf nur eine versteckte Checkbox um, die niemand sieht. Es kann also auf jeder Plattform rendern und verursacht nie einen Hydration Mismatch.
Auf dem iPhone bekommst du einen festen Tick pro Tap, ausgelöst vom Tap selbst: keine Muster, nichts nach einem await, nichts während eines Drags und nichts für ein Rad, das an Zeilen vorbeidreht, weil ein Scroll nie einen Klick erzeugt.
Wie rufst du navigator.vibrate sicher auf, wenn es nicht unterstützt wird?
Prüf die Methode selbst, prüf die Aktivierung, fang alles ab und gib einen Boolean zurück. Hier der ganze Helper ohne Abhängigkeiten:
Die Prüfung für Node ist wichtig. Node 21 und neuer definieren ein globales navigator ohne vibrate. Ein Helper, der nur typeof navigator prüft, kommt auf dem Server also an seinem Guard vorbei und ruft eine Methode auf, die es nicht gibt.
Der Haptics-Helper von Wingo UI ist dieselbe Idee plus ein Fallback fürs iPhone und eine Option force, die einen Tick auch dann abspielt, wenn Haptik aus ist. haptic(kind) gibt zurück, ob eine Haptik gesendet wurde, configureHaptics({ enabled, iosFallback }) setzt die Optionen für die ganze App, und supportsHaptics() sagt dir, ob der Browser überhaupt einen Weg für Haptik anbietet (ruf es in einem Effect auf: Auf dem Server ist es false, und in Chrome auf dem Desktop aus dem oben genannten Grund true).
$ npx wingo-ui@latest add hapticsEin Vorbehalt zu unserem eigenen Code: Die Option iosFallback des Helpers, standardmäßig an, klickt weiterhin per Skript auf ein verstecktes Label. Das tickt auf iPhones bis iOS 26.4, wird ab 26.5 ignoriert, und der Aufruf gibt dort trotzdem true zurück, weil WebKit nichts zurückmeldet. Wenn du das Tap-Overlay von oben einbaust, ruf einmal configureHaptics({ iosFallback: false }) auf, damit iPhones mit älteren Versionen nicht doppelt ticken.
Die Snippets unten importieren den Helper von Wingo UI. Mit der abhängigkeitsfreien Datei von oben importierst du stattdessen vibrate aus @/lib/vibrate und nutzt setHapticsEnabled statt configureHaptics; eine Option force hat sie nicht.
Welche Haptik passt zu welcher Interaktion?
Ein Tick pro Ereignis, abgestimmt auf dessen Gewicht. Diese Muster sendet der Helper auf Android:
Drei Regeln verhindern, dass daraus Rauschen wird. Ruf es aus dem Handler einer echten Geste auf, nie aus einem Effect oder beim Rendern. Tick nie pro Animationsframe; tick, wenn sich ein Zustand ändert, etwa wenn eine Zeile die Mitte erreicht. Und leg Information nie nur in den Tick: Leute am Desktop, Leute mit iPhone an einem Rad und alle mit lautlos gestelltem Smartphone spüren ihn nicht, also muss der Bildschirm dasselbe zeigen.
Wie baust du React Haptic Feedback in einen Switch, einen Button und ein Rad ein?
Ruf haptic() in dem Handler auf, in dem sich der Zustand ändert, einmal pro Änderung.
Ein Switch
Der kostenlose Switch ruft onCheckedChange bei jedem Klick, jeder Taste und jedem Drag auf, und gibst du ein Promise zurück, zeigt er einen Spinner und springt bei einem fehlgeschlagenen Speichern mit errorText zurück. Tick bei der Änderung und noch einmal bei einem Fehler:
Ab iOS 26.5 bleibt dieser Switch still: Er ist ein Radix-Button mit role="switch", nicht der native Input, also kommt mit dem Tap kein System-Tick, und haptic() erreicht den Switch-Tick aus dem Skript nicht. Ist dir ein iPhone-Tick an einem Einstellungs-Toggle wichtiger als das eigene Design, tickt ein schlichtes <input type="checkbox" switch> von selbst und rendert in Browsern, die das Attribut nicht kennen, als Checkbox.
Ein Button
Der Haptic Button spielt die in hapticKind gesetzte Art (Standard light) nur bei Touch- und Stift-Eingaben ab, ein Mausklick fordert also nie eine Vibration an. Mit mode="hold" spielt er light, wenn das Halten beginnt, success, sobald onConfirm fertig ist, warning bei einem zu kurzen Tap und error, wenn onConfirm mit einem Fehler endet; mit gesetztem onLongPress spielt ein Long Press medium.
$ npx wingo-ui@latest add haptic-buttonFür einen normalen Button, der auf beiden Plattformen ticken soll, kombinierst du den Aufruf und das Overlay. Der Button ist schon position: relative, das Overlay deckt ihn also ab:
Ein Rad
Das Picker Wheel spielt jedes Mal einen selection-Tick, wenn eine neue Zeile die Mitte erreicht, solange ein Finger, ein Maus-Drag oder ein Scrollrad es bewegt, und nie bei Tasten, Klicks oder Wertänderungen von außen. haptics={false} schaltet das ab.
$ npx wingo-ui@latest add picker-wheelHier zeigt sich die Lücke zwischen den Plattformen am deutlichsten. Auf Android tickt jede Zeile, die die Mitte passiert. Auf dem iPhone bleibt das Rad ab iOS 26.5 still, weil das Drehen ein Scrollen ist und nie den Trusted Click erzeugt, den der Switch braucht. Dort übernehmen das Band, die Neigung und das Einrasten das Feedback.
Wie lässt du Nutzer die Haptik abschalten?
Gib ihnen eine Einstellung und reich sie einmal an den Helper weiter. Haptisches Feedback braucht in jeder Web-App so einen Schalter: Manche Leute finden Vibration störend, und der Browser gibt einer Seite keinen Weg, die Haptik-Einstellung des Smartphones zu lesen.
Speicher den Wert zusammen mit den übrigen Einstellungen des Nutzers. Jede Komponente, die über den Helper tickt, folgt ihm ohne Prop: der Haptic Button, das Picker Wheel und das Pull To Refresh aus unserem Guide zu Pull to Refresh, um nur einige zu nennen.
Was kommt nach navigator.vibrate?
Eine semantische API mit benannten Effekten, falls die Browser den Entwurf übernehmen, der gerade entsteht. Die Web Haptics API (opens in a new tab) begann im März 2026 als Vorschlag an die CSS Working Group (opens in a new tab) und ist seit April bei der WICG in Arbeit. Ihr Entwurf hat einen Aufruf navigator.playHaptics(effect, intensity) und eine verschachtelte CSS-Regel @haptic, mit sechs benannten Effekten (hint, edge, tick, align, success, error) und einer Intensität von 0 bis 1, die der Browser auf die Haptik der Plattform abbildet. Der Aufruf gibt undefined zurück, eine Seite erfährt also nichts über das Gerät. Stand Oktober 2026 führt Chrome Platform Status (opens in a new tab) Web haptics als Proposed, und kein stabiler Browser liefert es aus.
Die Form kennst du schon: benannte Arten statt Mustern in Millisekunden. Wenn deine App schon jeden Tick durch einen einzigen Aufruf haptic(kind) schickt, änderst du beim Umstieg auf eine neue API später genau eine Datei.
Wo fängst du an?
Bau zuerst einen Helper ein und lass dann die drei Stellen ticken, die Leute am häufigsten berühren: Toggles, den Haupt-Button und jedes Rad oder jeden Slider. Die Datei lib/vibrate.ts ohne Abhängigkeiten von oben deckt Android ab. npx wingo-ui@latest add haptics kopiert stattdessen lib/haptics.ts von Wingo UI; der Helper gehört zu Wingo UI Pro, wie der Haptic Button und das Picker Wheel, der Switch ist kostenlos. Für den Rest der Smartphone-Checkliste (Bottom Sheets, Touch Targets von 44px, Safe Area Insets) lies Mobile-first React-Komponenten oder stöbere in der Kategorie Mobile UI in React.
Häufige Fragen
Funktioniert navigator.vibrate auf dem iPhone?
Nein. Safari hat die Vibration API nie implementiert, und caniuse führt Stand Oktober 2026 keine Safari-Version auf iOS mit Unterstützung. Die einzige Haptik, die eine Webseite auf dem iPhone erzeugen kann, ist der System-Tick eines nativen Switch-Inputs, und seit iOS 26.5 spielt ihn nur ein echter Tap des Nutzers ab.
Warum gibt navigator.vibrate auf meinem Laptop true zurück?
Weil true nur heißt, dass der Browser das Muster angenommen hat. Chrome auf dem Desktop bietet navigator.vibrate an und gibt, sobald die Seite einen Klick gesehen hat, für ein gültiges Muster true zurück, obwohl kein Motor da ist. Nutz den Rückgabewert, um Ablehnungen zu erkennen, aber nie als Hinweis auf Hardware.
Warum tut navigator.vibrate auf meinem Android-Smartphone nichts?
Die üblichen Gründe sind eine Seite, die noch nicht angetippt wurde (Chrome blockiert den Aufruf und loggt eine Warnung, bis die Seite Sticky User Activation hat), ein Tab im Hintergrund, Lautlos- oder Nicht-stören-Modus oder Firefox, das die API in Version 129 entfernt hat.
Kann eine Webseite die Stärke der Vibration steuern?
Nicht mit der Vibration API, die den Motor nur für die angegebenen Dauern an- und ausschaltet. Der Vorschlag für eine Web Haptics API, seit April 2026 in der WICG inkubiert, bringt benannte Effekte mit einer Intensität von 0 bis 1, aber Stand Oktober 2026 liefert ihn kein stabiler Browser aus.
Ist der Haptics-Helper von Wingo UI kostenlos?
Nein. Der Haptics-Helper, der Haptic Button und das Picker Wheel gehören zu Pro; der Switch ist kostenlos. Mit einem Pro-Account, angemeldet über npx wingo-ui@latest login, kopiert npx wingo-ui@latest add haptics die Datei lib/haptics.ts in dein Projekt.
- Mobile UI
- Haptik
- Vibration API
- iOS
- React


