How to Implement 3D Touch Interactions in Safari 10 with JavaScript

This guide explains the evolution of Apple’s Force Touch to 3D Touch, lists supported iPhone models, describes Quick Actions and Peek‑and‑Pop interactions, and provides step‑by‑step code for detecting touch pressure in Safari 10 using Touch.force and the touchforcechange event.

Aotu Lab
Aotu Lab
Aotu Lab
How to Implement 3D Touch Interactions in Safari 10 with JavaScript

Force Touch and 3D Touch

Force Touch was introduced by Apple in September 2014 as a pressure‑sensitive screen technology. It first appeared on Apple Watch and was refined on the iPhone 6s in September 2015 as 3D Touch, adding higher sensitivity, stronger haptic feedback, and three pressure levels: light tap, press, and deep press.

Hardware Requirements

Supported devices are iPhone 6s, iPhone 6s Plus, iPhone 7 and iPhone 7 Plus.

Typical 3D Touch Interactions

Two common gestures are Quick Actions (pressing an app icon to reveal a shortcut menu) and Peek and Pop (press‑and‑hold to preview content, then press deeper to open it). The following images illustrate these interactions in the Mail app.

Quick Actions illustration
Quick Actions illustration
Peek and Pop illustration
Peek and Pop illustration

3D Touch on the Web

Safari provides two features for 3D Touch in web pages: Touch.force – a read‑only property on the Touch object ranging from 0 (no pressure) to 1 (maximum detectable pressure). touchforcechange – an event fired when the pressure value changes. On macOS Safari a similar webkitmouseforcechanged event exists for Force‑Touch trackpads, but the focus here is on iOS devices.

Implementation Scenarios

iOS 10+ devices with 3D Touch : listen for touchforcechange and use the reported force value directly to update the UI.

Devices with 3D Touch but iOS < 10 : the touchforcechange event is unavailable, but the force property still updates. Implement a timer (e.g., 60 fps, ~16 ms interval) that polls Touch.force and updates the UI.

Devices without 3D Touch : Touch.force always returns 0. Gracefully degrade by falling back to a long‑press gesture or by disabling the effect.

Working Example

The demo page shows a blue button; pressing it with varying force changes the frame of a sloth animation. Implementation steps:

Bind touchstart to start a polling timer that reads Touch.force at ~16 ms intervals.

When touchforcechange fires, read the current force value and cancel the polling timer (the event provides the value directly).

On touchend or touchcancel, reset the force to 0 and clear any timer.

The animation uses a sprite sheet; the CSS background‑position is adjusted according to the current force value.

Sprite sheet example
Sprite sheet example

The source code is available on GitHub; the core file ThreeDTouch.js defines a ThreeDTouch class that accepts a DOM element and a callback receiving the live force value.

/**
 * 3D Touch event handler. Pass a DOM element and receive force updates via callback.
 *
 * @param {HTMLElement} el - Element to monitor.
 * @param {Function} callback - Function receiving the current force value.
 */
function ThreeDTouch(el, callback) {
    this.el = el;
    this.callback = callback;
    this._bindEvents();
}

ThreeDTouch.prototype = {
    // Bind relevant touch events
    _bindEvents: function () {
        var events = ['touchforcechange', 'touchstart', 'touchend', 'touchcancel'];
        events.forEach(function (event) {
            this.el.addEventListener(event, this, false);
        }.bind(this));
    },
    // Dispatch touch events
    handleEvent: function (ev) {
        switch (ev.type) {
            case 'touchforcechange':
                this._touchForceDidChange(ev);
                break;
            case 'touchstart':
                this._touchDidStart(ev);
                break;
            case 'touchend':
            case 'touchcancel':
                this._touchDidEnd(ev);
        }
    },
    // Force value changed
    _touchForceDidChange: function (ev) {
        var force = ev.touches[0].force;
        this.callback(force);
        clearTimeout(this.timeoutId); // Stop polling if event is supported
    },
    _touchDidStart: function (ev) {
        var touch = ev.touches[0];
        this._checkForce(touch);
    },
    _touchDidEnd: function (ev) {
        this.callback(0);
        clearTimeout(this.timeoutId);
    },
    // Poll force value at ~60 fps
    _checkForce: function (touch) {
        this.callback(touch.force);
        this.timeoutId = setTimeout(this._checkForce.bind(this, touch), 16);
    }
};

References

https://developer.apple.com/.../WhatsNewInSafari/Articles/Safari_10_0.html

https://developer.mozilla.org/en-US/docs/Web/API/Force_Touch_events

https://github.com/stuyam/pressure

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

frontendJavaScriptSafariTouch Events3D Touch
Aotu Lab
Written by

Aotu Lab

Aotu Lab, founded in October 2015, is a front-end engineering team serving multi-platform products. The articles in this public account are intended to share and discuss technology, reflecting only the personal views of Aotu Lab members and not the official stance of JD.com Technology.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.