Skip to content
This repository has been archived by the owner on Jun 3, 2020. It is now read-only.

Feature suggestions, usage examples #34

Closed
atotic opened this issue Oct 27, 2016 · 19 comments
Closed

Feature suggestions, usage examples #34

atotic opened this issue Oct 27, 2016 · 19 comments
Labels

Comments

@atotic
Copy link
Collaborator

atotic commented Oct 27, 2016

Do you have any suggestions, or usage examples? Leave your comments here.

@atotic
Copy link
Collaborator Author

atotic commented Oct 27, 2016

idea watch scrollWidth, scrollHeight.

use case scroll to the bottom when content is added. To achieve same effect with existing ResizeObserver, you must enclose existing div inside an additional div.

cons unsure if we can implement this efficiently.

@atotic
Copy link
Collaborator Author

atotic commented Oct 27, 2016

FF would like to observe location: https://bugzilla.mozilla.org/show_bug.cgi?id=1109868#c2

@rviscomi
Copy link

rviscomi commented Feb 6, 2017

@atotic thanks for working on this!

Is there any way to observe multiple elements at once, or is the preferred method to forEach on the list of elements and call observe with them one by one?

My use case is to observe each th in a table. Simplified example:

const resizeObserver = new ResizeObserver(doStuff);
const thList = document.querySelectorAll('th');
Array.from(thList).forEach(th => resizeObserver.observe(th));

Would be great if observe could handle arguments of type Element or NodeList:

resizeObserver.observe(thList);

If overloading is a concern, maybe there could be an observeAll method that expects an Array-like list of elements. WDYT?

PS: FWIW the documentation at https://developers.google.com/web/updates/2016/10/resizeobserver#api makes it seem like observe does take multiple elements. /cc @surma

// Observe one or multiple elements
ro.observe(someElement);

@atotic
Copy link
Collaborator Author

atotic commented Feb 7, 2017

Making observe() accept lists would make API more pleasant to use. DOM APIs are usually minimalist. Larger API surface means more interoperability problems. This also makes them a lot less fun to use than jQuery.

We will not modify observe() to accept lists for the following reasons:

  • doing this would be inconsistent with other observer APIs
  • there is an easy way to do this in plain JS

@que-etc
Copy link

que-etc commented Feb 13, 2017

Well, I've been musing about this idea for a while.

I wish there was a way to configure what type of the box-model is observed. In most cases I've seen so far, developers are neglecting and don't leverage the content-box dimensions provided in a ResizeObserEntry for many of them need the border-box model and sometimes margin or padding boxes. Some of them even hope to receive notifications when one of the former boxes changes, not to mention that these are different events.

And unfortunately there is no reliable way to handle the last case, as it requires to either modify both styles and markup or to change the box-sizing of an element. And to tamper with a DOM in such a way is not the best option for a third-party library which aims to cover this functionality.

So it would probably be for the best if ResizeObserver accepted an optional parameter in it's constructor with one of the box types: "margin" | "border" | "padding" | "content". Like the getBoxQuads API does with it's box property.

And I'm sorry if I'm missing something here. Maybe this option has been already ruled out for some reason?

@atotic
Copy link
Collaborator Author

atotic commented Feb 13, 2017

Main reasons for only observing content box size are:

  1. efficiency: internally, all(?) browser engines store content box size as a variable. The other boxes are computed relative to it. To observe resizes efficiently, all engines have to do is trap writes to this variable. Computing other box sizes introduces many other dependencies, that are complex to compute efficiently.
  2. simplicity: narrow standards are more likely to be implemented, and be interoperable.

This can be revisited for v2, if real world usage shows demand for measurement of other sizes.

@jacobrask
Copy link

I have an observer where I only care about the element's width to do some layout calculations. Would it be reasonable to somehow also get the size of the element before the resize happened?

That way I could do if (oldWidth !== newWidth) { expensiveLayoutCalculation(); }

As an example, React has a componentDidUpdate(prevProps, prevState) component method where you can do if (prevProps.foo !== this.props.foo) { doThis(); }

@que-etc
Copy link

que-etc commented Feb 22, 2017

@jacobrask But you can use content rectangle from the previous observation.

// Replace with an empty rectangle if the "doSomethingHeavy" function
// needs to be invoked on the first observation.
let prevRect = null;

const observer = new ResizeObserver(entries => {
    // Simplified case with only one element being observed.
    const {contentRect} = entries[0];

    if (!prevRect) {
        prevRect = contentRect;  
    }

    if (prevRect.width !== contentRect.width) {
        doSomethingHeavy();
    }

    prevRect = contentRect;
});

observer.observe(document.documentElement);

@jacobrask
Copy link

Thanks for your answer. This is also what I currently do. It makes it a bit more difficult to factor out the observer function though, since I'll then need to make a "factory" function to be able to access the memoized prevRect.

function createObserver() {
  let prevRect;
  return entries => {
    // Simplified case with only one element being observed.
    const {contentRect} = entries[0];

    if (!prevRect) {
        prevRect = contentRect;  
    }

    if (prevRect.width !== contentRect.width) {
        doSomethingHeavy();
    }

    prevRect = contentRect;
  };
}

const observer = new ResizeObserver(createObserver());
observer.observe(document.documentElement);

I completely understand that this use case might not be worth making the API more complicated for, but it might still be good to know a potential use case/pattern.

@eeeps
Copy link

eeeps commented May 26, 2017

I'm fiddling with using ResizeObserver for element/container queries.

I’m trying to concoct an example that shows whether/how ResizeObserver is more performant than window.onresize.

Based on these two pages, it seems like, if every element’s size is changing on every window resize, it isn’t, really? I turned Chrome CPU throttling up to 10x on my MBP and resized -- both pages stutter about the same amount.

Is that true, or am I doing something wrong?

@atotic
Copy link
Collaborator Author

atotic commented May 27, 2017

You are not doing anything wrong. If all your divs are changing size, performance is dominated by layout, not by resize observation. ResizeObserver is not about raw performance, (although it can help by eliminating polling), it is about giving developer ability to respond to size changes inside components.

For example
https://jsbin.com/satucev/2/edit?html,output
you can detect hover size change, and change content dynamically.

Without ResizeObserver, you'd have to poll, or use mouseover, etc.

@eeeps
Copy link

eeeps commented May 27, 2017

Thanks! That's really helpful.

Tangentially-related: for the element/container query use case, would there be any performance or usability benefit to setting IntersectionObserver-style thresholds on the ResizeObserver, so that events only fire at pre-set breakpoints? (Rather than on every resize, requiring the callback to check against breakpoints with an if).

@atotic
Copy link
Collaborator Author

atotic commented May 27, 2017

Performance benefit would be marginal. Layout and Paint that happen together with ResizeObserver and most often much more expensive.

@eeeps
Copy link

eeeps commented Jun 21, 2017

Re: #34 (comment) and margin/border/padding/content rects...

More than three-quarters of Chrome-Platform-Status-observed pageloads use some form of box-sizing. Which leads me to believe that there will be more demand for getting the dimensions of other sorts of boxes, as adoption ramps up.

@atotic
Copy link
Collaborator Author

atotic commented Sep 27, 2017

@jacobrask I am curious about why exactly did you need to know previous reported size? Can you elaborate?

@jacobrask
Copy link

jacobrask commented Oct 3, 2017

@atotic To be very specific, I have a grid layout component which distributes items into columns. Whenever the grid component's width updates it should redistribute the items. This is obviously expensive, so I only want to do it when the width changes and not the height, which is why I want to compare it with the previous width.

@atotic
Copy link
Collaborator Author

atotic commented Oct 3, 2017

@jacobrask Thanks for being specific, this is the first real-world example of needing to know previous size.

btw, is your site https://www.visitstockholm.com/?

@jacobrask
Copy link

No, I work on the Prenly news reader. Adaptable page layout is important for a our application so ResizeObserver is being introduced at several places.

@atotic
Copy link
Collaborator Author

atotic commented Oct 4, 2017

@jacobrask Neat. Are there any publicly available pages that currently use ResizeObserver polyfill. I am profiling today for "Intent to Ship".

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

6 participants