December 7, 2017 10:34 am

Building a great touchpad experience for the web with Pointer Events

By / Program Manager, Microsoft Edge

Most web pages don’t fit on one screen, so good scrolling behavior is an integral part of a good web browser. It’s so crucial to the user experience that we have spent a lot of time optimizing page scrolling, with great results.

Since launching Microsoft Edge, we’ve optimized most scrolling experiences — scrolling via touchscreens, page and content scrollbars. One particular focus in previous releases has been improving touchpads, specifically precision touchpads (PTPs), to provide a smooth, fluid, intuitive experience by default.

In this post, we’re introducing a new optimization coming in EdgeHTML 17 to allow developers to customize scrolling behaviors and gestures with Precision Touch Pads, without impacting scrolling performance: PTP Pointer Events.

Background

Precision touchpads are high-end touchpads that ship in Surface devices (Surface Pro 2 and later) and modern Windows 10 devices from our OEM partners. Windows 10 takes advantage of this hardware to enable system-wide gestures and better, more responsive scrolling than what was possible with older technology.

Microsoft Edge also utilizes PTPs to enable back/forward swipe and to enhance users’ scrolling experience via off-thread (aka independent) scrolling. Since PTP input is processed differently by the input stack in Windows 10, we wanted to ensure that we took advantage of this and that we gave users a scrolling experience that felt as natural as their experience with touchscreens everywhere on the web.

However, the web has traditionally had a bit of a design flaw when it comes to scrolling, in the form of scroll jank — that ‘glitchy’ feeling that the page is stuck, and not keeping up with your finger while you’re scrolling.

Often, scroll jank is caused by mousewheel or Touch Event listeners on the page (these are often used for tracking user interactions or for implementing custom scrolling experiences):

// Examples of event listeners that can negatively affect scrolling performance
document.addEventListener("wheel", handler);
document.addEventListener("touchstart", handler);

If one of these listeners is going to modify the default scrolling behavior of the browser, the browser has to cancel its optimized default scroll altogether (accomplished by web developers calling preventDefault() within handlers). Since browsers don’t always know if the listener is going to cancel the scroll, however, they always wait until the listener code executes before proceeding with the scroll, a delay which manifests itself as scroll jank:

Animation showing an example of scroll jank due to a mousewheel handler with a 200ms duration

An example page showing scroll jank due to a mousewheel handler with a 200ms duration.

Browsers identified this issue and shipped passive event listeners as a mitigation (available in Chrome 51+ and EdgeHTML 16+) to help reduce its scope:

Animation showing an example page scrolling smoothly touch/wheel handlers attempting to block scrolling.

The same example with smooth scrolling thanks to passive event listeners

Intersection Observers also help get around this issue by providing web developers with a mechanism to track user interactions with the page (to trigger lazy loading of infinite scrollers, for example) without affecting scrolling performance. These two approaches, however, still do not solve the cases where active event listeners are necessary, and require developers to be aware of the issues explained above and to change their sites in order for users to see improvements.

Given that we wanted to enable the best scrolling experience with PTP on as many sites as possible while minimizing developer work, we made the decision to not fire mousewheel events in response to PTP gestures (such as two finger pans). While this greatly reduced scroll jank and gave users a scrolling experience akin to the one they get on touchscreens, the lack of mousewheel events being fired unfortunately also meant that users were unable to zoom on sites such as Bing Maps and pan on sites that use custom scrolling controls (both of which expect mousewheel events coming from touchpads in order to operate).

Developers on our public issue tracker have made it clear that this has been a top pain point, however, the Microsoft Edge team wanted to ensure that the solution built to address these broken experiences not only fixed them, but also preserved the functional and performance benefits accrued by not firing mousewheel events.

PTP Pointer Events

As of EdgeHTML 17, Microsoft Edge will fire Pointer Events with a pointerType of “touch” in response to PTP gestures. While this is a departure from the mousewheel events of the past, we believe that the advantages to this approach more than justify the departure:

No additional overhead for modern websites

If your website already supports Pointer Events and touch, there is no additional work you need to do to take advantage of PTPs in Microsoft Edge; your site will just work!

If you have not yet implemented Pointer Event support, we strongly recommend you check out the MDN documentation for Pointer Events to prepare your site for the modern web. Pointer Events are available on Internet Explorer 11, Microsoft Edge, and Google Chrome and are in development in Firefox.

Enhanced scrolling performance

Scrolling with PTPs in Microsoft Edge will never cause scroll jank since Pointer Event handlers (unlike mousewheel and Touch Event handlers) are designed so that they cannot block scrolling.

With these new changes in Microsoft Edge, you can be certain that you are getting the best possible scrolling experience on PTP-enabled devices thanks to Pointer Events.

Improved Gesture Recognition/Site Functionality

Since PTP Pointer Events emulate touch Pointer Events, PTP gestures such as pinch to zoom and two finger panning will light up on sites that already support touch Pointer Events. This will allow developers to build near-native gesture experiences on the web, complete with the smooth animation and inertia curves that users have come to expect from interacting with pages via touch.

Using PTP Pointer Events

Using PTP Pointer Events on your site is as simple as registering for Pointer Events and using the touch-action CSS property to control how touches are handled by the browser:

In HTML, add the touch-action CSS property to your target element to prevent the browser from executing its default touch behavior in response to gestures (in Microsoft Edge, for example, this will prevent two finger swipes from triggering back/forward swipe behavior):

<canvas height=400 width=400 id="canvas" style="touch-action: none;"></canvas>

In JavaScript, attach a Pointer Event listener to your target element. You can determine the type of pointer that caused the handler to be invoked using the pointerType property of the event object passed into the event listener callback:

document.getElementById('canvas').addEventListener('pointermove', function(event) {
    console.log('pointermove!');
});

More detailed information on Pointer Events can be found on MDN here.

Once you have added Pointer Event support to your site, the only step that remains is understanding how Microsoft Edge exposes PTP gestures to sites as Pointer Events. Note that for both of the gestures below, the Pointer Events generated in EdgeHTML will be sent to the element that is directly under the cursor when the PTP gesture begins.

Two Finger Panning

The two finger PTP panning gesture is converted within EdgeHTML to a single contact gesture (identical to a single-fingered touch pan gesture) and is exposed to sites as such. The gesture originates at the cursor location and any movement of the fingers on the touchpad is translated to a scaled delta which results in a pan action. The CSS touch-action property can be used to control the way that a specific region can be manipulated by the user.
Animation showing two-finger touchpad input being mapped to a one-finger Pointer Event pan (pointerType of "touch") by EdgeHTML

Zooming

The pinch to zoom PTP gesture is converted within EdgeHTML to a gesture that originates at the cursor location. Two contacts are placed at a scaled distance away from the cursor location and any movement of the fingers on the touchpad is translated into scaled deltas which results in a zoom action.

Animation showing a two-finger Touchpad gesture (pinch-to-zoom) mapped by EdgeHTML two a two-finger "touch" Pointer Event (pointerType of "touch")

Rotation

PTP Pointer Events in Microsoft Edge introduce support for two-finger Rotation gestures for the first time, due to the fact that raw pointer data is exposed directly from the touchpad in all cases other than panning (where the two contacts on the touchpad are combined into one). Existing sites with Pointer Event handlers for touch that support rotation will light up with Precision Touchpads in Microsoft Edge as well.

What’s next

You can try out PTP Pointer Events in Microsoft Edge starting with our next Windows Insider release on any site that currently supports Pointer Events for touch gestures, including Bing Maps or Google Maps, on any device with a Precision Touchpad. The broader Windows 10 community will see PTP Pointer Events when EdgeHTML 17 ships with the next major release of Windows 10.

We are excited to enable jank-free and near-native touchpad experiences across the web using Pointer Events, and look forward to feedback on this feature from developers and end users alike! You can share any bugs you encounter in testing via Microsoft Edge Platform Issues or the Feedback Hub app on Windows 10, or give your feedback directly @MSEdgeDev on Twitter or in the comments below.

Try it out and let us know what you think!

Scott Low, Program Manager, Microsoft Edge

Updated December 8, 2017 3:31 pm

Join the conversation