|
| 1 | +project_path: /web/_project.yaml |
| 2 | +book_path: /web/updates/_book.yaml |
| 3 | +description: Scrolling responsiveness is critical to the user's engagement with a website on mobile, yet wheel event listeners often cause serious scrolling performance problems. Learn how we are helping users and developers to be fast by default. |
| 4 | + |
| 5 | +{# wf_updated_on: 2019-02-01 #} |
| 6 | +{# wf_published_on: 2019-02-07 #} |
| 7 | +{# wf_tags: interventions,chrome73 #} |
| 8 | +{# wf_featured_image: /web/updates/images/generic/warning.png #} |
| 9 | +{# wf_featured_snippet: Scrolling responsiveness is critical to the user's engagement with a website on mobile, yet <code>wheel</code> event listeners often cause serious scrolling performance problems. Learn how we are helping users and developers to be fast by default. #} |
| 10 | +{# wf_blink_components: N/A #} |
| 11 | + |
| 12 | +# Making wheel scrolling fast by default {: .page-title } |
| 13 | + |
| 14 | +{% include "web/_shared/contributors/sahel.html" %} |
| 15 | + |
| 16 | +To improve `wheel` scrolling/zooming performance developers are encouraged to |
| 17 | +register `wheel` and `mousewheel` [event listeners as |
| 18 | +passive](/web/updates/2016/06/passive-event-listeners) |
| 19 | +by passing the `{passive: true}` option to `addEventListener()`. Registering |
| 20 | +the event listeners as passive tells the browser that the wheel listeners will |
| 21 | +not call `preventDefault()` and the browser can safely perform scrolling and |
| 22 | +zooming without blocking on the listeners. |
| 23 | + |
| 24 | +The problem is that most often the wheel event listeners are conceptually |
| 25 | +passive (do not call `preventDefault()`) but are not explicitly specified as |
| 26 | +such requiring the browser to wait for the JS event handling to finish before |
| 27 | +it starts scrolling/zooming even though waiting is not necessary. In Chrome 56 |
| 28 | +[we fixed this issue for touchStart and touchMove](/web/updates/2017/01/scrolling-intervention) |
| 29 | +, and that change was later adopted by both Safari and Firefox. As you can see |
| 30 | +from the demonstration video we made at that time, leaving the behavior as it |
| 31 | +was produced a noticeable delay in scroll response. Now in Chrome 73, we've |
| 32 | +applied the same intervention to `wheel` and `mousewheel` events. |
| 33 | + |
| 34 | +<div class="video-wrapper"> |
| 35 | + <iframe class="devsite-embedded-youtube-video" data-video-id="65VMej8n23A" |
| 36 | + data-autohide="1" data-showinfo="0" frameborder="0" allowfullscreen> |
| 37 | + </iframe> |
| 38 | +</div> |
| 39 | + |
| 40 | +## The Intervention |
| 41 | + |
| 42 | +Our goal with this change is to reduce the time it takes to update the display |
| 43 | +after the user starts scrolling by wheel or touchpad without developers needing |
| 44 | +to change code. Our metrics show that 75% of the `wheel` and `mousewheel` event |
| 45 | +listeners that are registered on root targets (window, document, or body) do |
| 46 | +not specify any values for the passive option and more than 98% of such |
| 47 | +listeners do not call preventDefault(). In Chrome 73 we are changing the |
| 48 | +`wheel` and `mousewheel` listeners registered on root targets (window, |
| 49 | +document, or body) to be passive by default. It means that an event listener |
| 50 | +like: |
| 51 | + |
| 52 | +```js |
| 53 | +window.addEventListener("wheel", func); |
| 54 | +``` |
| 55 | + |
| 56 | +becomes equivalent to: |
| 57 | + |
| 58 | +```js |
| 59 | +window.addEventListener("wheel", func, {passive: true} ); |
| 60 | +``` |
| 61 | + |
| 62 | +And calling `preventDefault()` inside the listener will be ignored with the |
| 63 | +following DevTools warning: |
| 64 | + |
| 65 | + [Intervention] Unable to preventDefault inside passive event listener due |
| 66 | + to target being treated as passive.See https://www.chromestatus.com/features/6662647093133312 |
| 67 | + |
| 68 | +## Breakage and Guidance |
| 69 | + |
| 70 | +In the vast majority of cases, no breakage will be observed. Only in rare cases |
| 71 | +(less than 0.3% of pages according to our metrics) unintended scrolling/zooming |
| 72 | +might happen due to `preventDefault()` call getting ignored inside the |
| 73 | +listeners that are treated as passive by default. Your application can |
| 74 | +determine whether it may be hitting this in the wild by checking if calling |
| 75 | +`preventDefault()` had any effect via the defaultPrevented property. The fix |
| 76 | +for the affected cases is relatively easy: pass `{passive: false}` to |
| 77 | +`addEventListener()` to override the default behavior and preserve the event |
| 78 | +listener as blocking. |
| 79 | + |
| 80 | +## Feedback {: .hide-from-toc } |
| 81 | + |
| 82 | +{% include "web/_shared/helpful.html" %} |
| 83 | + |
| 84 | +<div class="clearfix"></div> |
| 85 | + |
| 86 | +{% include "web/_shared/rss-widget-updates.html" %} |
0 commit comments