Intent to Ship: ResizeObserver
Contact emails
Explainer
https://github.com/WICG/ResizeObserver/blob/master/explainer.md
Spec
Spec: https://wicg.github.io/ResizeObserver/
Tag review: https://github.com/w3ctag/design-reviews/issues/187
Notable final comments on Tag review were:
Is this going to be launched as an Origin Trial? If so, this seems to be in good shape.
Summary
ResizeObserver is a new DOM observer API. It is intended to be used for observing size of DOM elements like this:
let ro = new ResizeObserver(entries => {
for (entry of entries) {
console.log(entry.target);
console.log(entry.contentRect);
}
ro.observe(document.element);
Link to “Intent to Implement” blink-dev discussion
Intent To Implement: ResizeObserver
Link to Origin Trial feedback summary
There was no Origin Trial for ResizeObserver.
The reason why I believe shipping is preferable to Origin Trial is that ResizeObserver has already received a lot of feedback.
After the spec was finalized, Internet produced a polyfill that is widely used:
>>>>> by Philip Walton
The ResizeObserver polyfill has 182,689 monthly downloads on npm (for comparison, the IntersectionObserver polyfill only has 57,453)
According to HTTP Archive, the `ResizeObserver` constructor is used on 667 of the top alexa sites including dropbox.com and uber.com (presumably with the polyfill, so they're slower than they need to be).
<<<<<
We've also gotten feedback from:
- the polyfill implementors, especially que-etc. His conclusion is that people often want to track other box dimensions too.
- bmauer from Facebook hacked on it. Wanted to use it for chat window, wanted to track scroll dimensions, wanted to use it to obtain precise timing information for layout.
- blois@google has used it to propagate iframe sizes to parent.
- Firefox had an intern work on it in summer of 2016. They used our tests to test interoperability, but never shipped.
Feedback can be summarized as:
1) want to observe more sizes, not just content size. (border box size, scroll size)
2) want previous size reported together with current size.
Implementing 1) performantly would be challenging in current Layout code.
Implementing 2) is easy, but I have not seen any real world examples where it would be useful.
Both of these would be nice extensions for v2, and can be (mostly) implemented on top of v1.
Is this feature supported on all six Blink platforms (Windows, Mac, Linux, Chrome OS, Android, and Android WebView)?
Yes.
Demo link
To run demos in today's Chrome, launch it with --enable-blink-features=ResizeObserver
Demo on rawgit.
Debuggability
ResizeObserver implements standard observer pattern also used by MutationObserver, and IntersectionObserver. When notification delivery is delayed because of depth restrictions, a window error event is generated, and devtools prints it to console.
Risks
Interoperability and Compatibility
ResizeObserver was discussed at 2016 TPAC.
Edge: Under consideration, priority low, status here. Greg seemed supportive in person at TPAC.
Firefox: In development, an intern worked on it is 2016. Their implementation passed most of the w-p-t test, and dholbert commented upon the spec #17 #21
Safari: No public signals, status here. Did not protest at TPAC.
Web developers: Positive: polyfill in wide use, see Origin Trial feedback above.
web-platform-tests submitted here. Firefox already used them to check compatibility.
Ergonomics
ResizeObserver can be used in tandem with scroll event to implement "chat window" scrolling to bottom.
Could the default usage of this API make it hard for Chrome to maintain good performance?
No. ResizeObserver can be implemented efficiently, and only runs if observed element's size has changed. If the Element's size has changed, cost of layout dwarfs cost of broadcasting resize observations.
Activation
Will it be challenging for developers to take advantage of this feature immediately, as-is?
No, the polyfill has already been widely used.
Is this feature fully tested by web-platform-tests?
ResizeObserver is fully tested by test suite, and the suite has been submitted to w-p-t repository.
Entry on the feature dashboard
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAMdyzDuGco-6Nyx%3DQ2cXe%3DzDzaxWPwFJa6XnO9V6ON%2BuCynqhQ%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAOtFfx586uV7dm-c9TR0m%3D%3DeA__MB%3Dvr8ZOUKeny9osNtXTEBw%40mail.gmail.com.
1) In practice, how often do authors trigger the layout loop in <https://wicg.github.io/ResizeObserver/#html-event-loop>? What impact does that have on performance?2) Because the layout loop is designed to terminate, there can be active notifications that are not delivered before the browser paints. In practice, how often do authors have pending notifications that are not delivered before the browser paints? What impact does that have on the quality of the user experience (i.e., flashes of bad layout that are corrected in the next frame when the pending notifications are delivered)?I asked these questions in the intent-to-implement thread, but it was probably too early for empirical evidence to be available. Now that the polyfill has significant usage, we might be able to study a representative sample of these usage and get quantitative data about how authors use ResizeObserver in practice.
abarth asked:
> 1) In practice, how often do authors trigger the layout loop? What impact does that have on performance?
> 2) Because the layout loop is designed to terminate, there can be active notifications that are not delivered before the browser paints. In practice, how often do authors have pending notifications that are not delivered before the browser paints? What impact does that have on the quality of the user experience (i.e., flashes of bad layout that are corrected in the next frame when the pending notifications are delivered)?
Getting practice data for an unreleased API is not always possible. Luckily, ResizeObserver has a widely used polyfill. @philipwalton has provided a spreadsheet that lists most popular sites using the polyfill.
I've investigated RO usage on these sites using an instrumented binary, and tracing tools. On 9 sites, live usage of RO was detected. Many sites did not trigger RO in my test setup (loading, or window resize).
Result summary
- 8 sites observed between 1 and 4 elements. A single outlier observed 28.
- RO was always used as an element query: children would be rearranged, images loaded depending on size.
- RO was triggered on load, and during window resizing.
- Notifications were handled quickly (<2ms) on 6 sites. On 3 sites, occasionally a notification would trigger a long operation (12, 40, and 90ms). This happened when site did lots of DOM manipulation inside RO callback.
- No undelivered notifications were observed while tracing. I did see undelivered notifications twice while running in gdb, but this was not consistently reproducible.
- Many of the sites were using React. A popular React component uses the polyfill.
Interpretation
ResizeObserver is being used as intended, to implement responsive components. Main problem with API as used today is too much work being done inside a callback.
Undelivered notifications have not been observed as a problem. This does not mean that they never will be. RO might be widely adopted, and 1000 components start responding to notifications in a single page, webdevs like to push platform to its limits.
The most common performance problem was doing too much DOM manipulation inside a callback. Other event loop callbacks have the same problem. What to do if response to an event involves changing the DOM?
"What is the well-lit path for ResizeObserver if webdevs want to perform DOM manipulation in response to resize?" is an interesting question.
If they perfom DOM manipulation in a RO callback, it might be too slow.
If they post an idle task to perform DOM manipulation, the element's contents will be out of sync with size for 1 frame (bad layout).
There is no 1 size fits all. I think the answer is:
- if your component is changing in response to window resize, post an idle task, DOM is pretty messy during window resizes, no one will notice.
- if you are animating the component, be careful with component design. Either design it so its response to resize is fast enough and skip idle task, or post an idle task but draw your component so that bad layout will not be jarring to the user. (
- the two-years from now answer is use CustomPaint instead :-)
Many sites were written in React. We should survey libraries using ResizeObserver, to make sure they use it appropriately.
Most sites created a new ResizeObserver for every observed element, even the one with 28 observers.
Result details:
ResizeObserver was instrumented to record RO.observe(), RO. deliverNotifications(), and skipped notifications. Page load, and window resize were traced.
Load: 4 observe(), 4 notify() (0.18ms max)
Resize: 4 observer(), 4 notify() (0.18ms max)
Uber got the polyfill by using react-measure-it component. Observes 4 divs. Looks like it is used for layout of the topmost menus.
https://www.visitstockholm.com/
Load: 28 observe, 28 notify (0.2ms max)
Resize: 140 notify (40ms max, rest < 1ms. React.batchedUpdates got triggered inside max)
My favorite. Full custom grid-like layout with ResizeObserver's help. 28 observed elements, feels performant.
Load: 2 observe, 2 notify (14ms max)
Resize: 3 notify (.5ms max)
React site, might be using the same component as uber.
The 14ms callback was important code that loaded/resized images dynamically, looping through all, checking if they were visible, etc.
Load: 2 observe, 2 notify (59ms max, something z.moatads.com related happens inside callback)
Resize: 3 notify, 90ms max.
2 Elements observed. Managed to trigger "undelivered notifications" once on load. Observed div wraps ads.
Load: 5 observe, 2 notify (.01ms max)
Resize: 8 notify (0.01ms max)
Observing single div, with no notifications.
Load: 7 observe, 6 notify (.4ms max)
Resize: 2 notify, (.16ms max)
Max simultaneous notifications: 2
Observing 7 divs. I did manage to trigger "undelivered notifications" error once after multiple resizes.
Load: 2 observe, 2 notify (1.5ms max, .5ms inside compiler)
Resize: 5 notify, (1.5ms max, React.setState...)
Max simultaneous notifications: 3
React. Good looking site. Observing menus to change contents in response to resize.
Load: 5 observe, 3 notify (.25ms max)
Resize: 2 notify (12ms max, 2 recalc styles)
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAMdyzDupLu2jdCZ-cnw7P_g7FVQum5wBKVXSVFZ7%2B3uHuMoLWw%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAP%3D28cfk9yY1zELRPgyvk348bj7BBYyEQLCAJSBB253w-KRuXA%40mail.gmail.com.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAARdPYd16kcs5h45wWeGD_gMadNXi8uw6inKLZWfgXZZqTC1hA%40mail.gmail.com.
Feedback can be summarized as:
2) want previous size reported together with current size.
Implementing 2) is easy, but I have not seen any real world examples where it would be useful.