Intent to Implement: ResizeObserver

336 views
Skip to first unread message

Aleks Totic

unread,
May 18, 2016, 6:39:13 PM5/18/16
to blink-dev

Contact emails

ato...@chromium.org  


Spec

Draft spec: https://wicg.github.io/ResizeObserver/


Summary

An observer-style API to get notifications when Element's size changes


Motivation

Web Components want to be responsive: a map that tiles its content area; a menu that hides its title when space is too narrow.


There is currently no API for an Component to detect when its size has changed. Web Applications can monitor viewport changes with window.resize event, or @media queries.


ResizeObserver provides an API that gives Elements a way to observe, and respond to changes in their size. 

The API is a classic observer: observe/unobserve/disconnect.


Sample code for a map that tiles its content area at https://jsbin.com/woqusem/edit?html,output


Interoperability and Compatibility Risk

Feature has a draft spec. We've had a CSSWG meeting with Mozilla/Safari/Microsoft, and the response was that they do not mind the idea.. As a result of the meeting, we now have some tracking bugs:

Mozilla: https://bugzilla.mozilla.org/show_bug.cgi?id=1272409 Webkit: https://bugs.webkit.org/show_bug.cgi?id=157743 Microsoft: https://developer.microsoft.com/en-us/microsoft-edge/platform/status/resizeobserver/


Ongoing technical constraints

None.


Will this feature be supported on all six Blink platforms (Windows, Mac, Linux, Chrome OS, Android, and Android WebView)?

Yes.


OWP launch tracking bug

https://bugs.chromium.org/p/chromium/issues/detail?id=612954


Link to entry on the feature dashboard

https://www.chromestatus.com/feature/5670617353289728


Requesting approval to ship?

No.

Adam Barth

unread,
May 18, 2016, 7:15:25 PM5/18/16
to Aleks Totic, blink-dev
On Wed, May 18, 2016 at 3:39 PM 'Aleks Totic' via blink-dev <blin...@chromium.org> wrote:

Contact emails

ato...@chromium.org  


Spec

Draft spec: https://wicg.github.io/ResizeObserver/


Summary

An observer-style API to get notifications when Element's size changes


Motivation

Web Components want to be responsive: a map that tiles its content area; a menu that hides its title when space is too narrow.


There is currently no API for an Component to detect when its size has changed. Web Applications can monitor viewport changes with window.resize event, or @media queries.


ResizeObserver provides an API that gives Elements a way to observe, and respond to changes in their size. 

The API is a classic observer: observe/unobserve/disconnect.


Sample code for a map that tiles its content area at https://jsbin.com/woqusem/edit?html,output


Interoperability and Compatibility Risk

Feature has a draft spec. We've had a CSSWG meeting with Mozilla/Safari/Microsoft, and the response was that they do not mind the idea.. As a result of the meeting, we now have some tracking bugs:

Mozilla: https://bugzilla.mozilla.org/show_bug.cgi?id=1272409 Webkit: https://bugs.webkit.org/show_bug.cgi?id=157743 Microsoft: https://developer.microsoft.com/en-us/microsoft-edge/platform/status/resizeobserver/


Ongoing technical constraints

None.


We had a similar API in Flutter for a while (SizeObserver), but we ended up removing it because it was often misused by developers and lead to a poor quality user experience.

It's very common for developers to use these notifications about size changes to resize other elements.  As specified, ResizeObserver spins a loop until the system either reaches a fixed point or some threshold is exceeded.

In general, reaching a fixed point can take a long time because there's no organization to the data flow in the overlay layout computation.  For example, it's very easy to create n^2 algorithms (or worse) using this mechanism.

To avoid these problems, it's tempting to set a low loop threshold.  In Flutter, we essentially had a loop threshold of one.  However, when you hit the threshold and bail out of the loop, you put up a frame with an incomplete layout.  The loop will keep spinning on the next frame and you'll proceed to put up a sequence of different bad frames until the layout computation reaches a fixed point.  These bad frames end up looking like UI flickers, where some elements have the wrong size for one or two frames.

Based on our experience with a similar API in Flutter, I would urge you to reconsider whether you want to implement ResizeObserver.

Adam

ben.m...@gmail.com

unread,
May 18, 2016, 7:47:17 PM5/18/16
to blink-dev
For interest from web developers, this is something that Facebook would be interested in.

One general comment here is that a common developer abstraction is to have a function like queryThenMutateDOM(query, mutate) which runs all queries then all mutations in a loop until one iteration of the loop does not call queryThenMutateDOM. It'd be great to have support for this abstraction and it easily implemented on top of ResizeObserver lifecycle. One specific use case for this generalization that we're currently running into -- right now it's impossible to measure the time spent in stylesheet recalc and layout. We're considering doing something fairly terrible where we use rAF to force a layout from JS on every frame so that we can measure layout time. 

These two things would make ResizeObserver far more compelling from a developer standpoint. queryThenMutateDOM allows developers to port existing code quickly to this abstraction and the ability to measure stylesheet/layout time would be huge.

-b

Aleks Totic

unread,
May 18, 2016, 8:03:21 PM5/18/16
to blink-dev, ato...@google.com
Careless use of the  API can certainly cause bad user experience. Proper use will enable better user experiences.

Without the API, there is no good way to provide good user experiences upon resize.

That's why I believe that API is needed.

What did you replace SizeObserver with in Flutter?

Aleks

Rick Byers

unread,
May 18, 2016, 8:17:05 PM5/18/16
to Aleks Totic, blink-dev, ikilp...@chromium.org
On Wed, May 18, 2016 at 8:03 PM, 'Aleks Totic' via blink-dev <blin...@chromium.org> wrote:
Careless use of the  API can certainly cause bad user experience. Proper use will enable better user experiences.

Without the API, there is no good way to provide good user experiences upon resize.

To what extent are these use cases potentially addressed by Houdini custom layout?

Adam Barth

unread,
May 18, 2016, 8:32:57 PM5/18/16
to Aleks Totic, blink-dev
On Wed, May 18, 2016 at 5:03 PM 'Aleks Totic' via blink-dev <blin...@chromium.org> wrote:
Careless use of the  API can certainly cause bad user experience. Proper use will enable better user experiences.

Without the API, there is no good way to provide good user experiences upon resize.

That's why I believe that API is needed.

What did you replace SizeObserver with in Flutter?

We replaced it with a variety of different mechanisms depending on the use case:

1) We addressed some use cases simply by being lazy and reading the layout information when it was actually needed (e.g., during user interaction) rather than reading it eagerly via observation.

2) We addressed some other use cases by letting developers manipulate painting information based on layout information.  For example, imagine that a developer is allowed to supply a transformation matrix for an element or issue canvas2d drawing commands after reading layout information.  This approach doesn't introduce the same pipeline inversion as ResizeObserver because these manipulations cannot dirty layout state and trigger a layout loop.

3) Finally, we addressed the remaining use cases with custom layout.  In Flutter, we have a spectrum of custom layout mechanisms, some of which are simple but not very power and others which are very powerful but are not simple.  When we replaced SizeObserver with custom layout, we tended to use some of the simpler custom layout mechanisms.

Adam

Elliott Sprehn

unread,
May 18, 2016, 8:40:30 PM5/18/16
to Rick Byers, Aleks Totic, blink-dev, Ian Kilpatrick
On Wed, May 18, 2016 at 5:16 PM, Rick Byers <rby...@chromium.org> wrote:
On Wed, May 18, 2016 at 8:03 PM, 'Aleks Totic' via blink-dev <blin...@chromium.org> wrote:
Careless use of the  API can certainly cause bad user experience. Proper use will enable better user experiences.

Without the API, there is no good way to provide good user experiences upon resize.

To what extent are these use cases potentially addressed by Houdini custom layout?


These are solving different use cases. ResizeObserver is async and can mutate the DOM. Houdini layout runs inside a Worklet inside the actual layout pass of the browser. Inside a Houdini layout you cannot mutate the DOM.

With that difference in mind ResizeObserver is primarily intended for doing UI selection. For example you might choose to move buttons into an overflow menu as the toolbar shrinks in size, or you might turn sidebars into menus. Block, Flexbox, Grid and Houdini Layout should be used for box placement.  :)

- E

Jon Rimmer

unread,
May 23, 2016, 7:08:50 AM5/23/16
to blink-dev
We are building visualisation components using SVG and D3, and ResizeObserver would be very useful for making these responsive.

It is not just a case of simple scaling — different parts of the chart need to adjust independently, e.g. axes might remain the same size while the central area scales, or elements might appear or collapse as the element gets bigger or larger. As SVG's built-in support for this kind of responsive layout is non-existent, we have to do it in code. And we cannot rely on window.resize events, as the components may be included in, for example, a flexbox alongside other data-bound components whose size may change.

Our approach is to require the component element be positioned either relatively or absolutely, then use absolute positioning on its child so that it fills its parent. In this way, we avoid ever allowing the child to invalidate its parent's size. It is up to the component consumer to specify or control its size, and the component will render to SVG as appropriate. We have experimented with various resize listener hacks to detect changes to size of the component. Our current approach is to use requestAnimationFrame to check the offsetHeight and offsetWidth of the component element each frame and, if they have changed, queue a re-render — with appropriate debouncing, as rebuilding the SVG DOM is quite expensive.

I can see how a combination of CSS containment, element queries, custom layout and custom painting might eventually allow us to create these components in a more performant and declarative manner, if they were all implemented cross-browser and worked well with SVG content. However, I don't have much confidence that will happen before I retire. Meanwhile, ResizeObserver would allow us to remove the manual size checking without changing the rest of the component logic.

Jon
Reply all
Reply to author
Forward
0 new messages