Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spec should clarify whether or not this is intended to serve as a "layout-changed observer" (I think it's not?) #81

Closed
dholbert opened this issue Oct 6, 2020 · 3 comments · Fixed by #112

Comments

@dholbert
Copy link
Contributor

dholbert commented Oct 6, 2020

It may be tempting for web developers to use the Layout Instability API as a way of tracking when elements move (for any reason), as a way to receive callbacks when they need to recompute the positions of other related elements (e.g. overlays, focus rings).

There's a blog post here that recommends doing exactly that -- it describes a number of other things too, so you can do find-in-page for "layout shift" to jump to the relevant details:
https://www.notion.so/Focus-Rings-4459faa9d1f643728ca8dde145a89900

(see also: a tweet about this in https://twitter.com/aweary/status/1313266406641864706?s=20 )

So this blog post is describing a way to use the Layout Shift API as a callback that fires when layout changes (specifically when it changes in a way that moves elements around); and it uses this as a hook for the web-developer's JS to run and make some resulting positioning adjustments to overlays and such.

Is this an intended-to-be-useful use case for this API? The problem that comes to mind first is the magic "3px" threshold that's currently hardcoded in spec (which means: an element that slowly moves < 3px per animation frame won't trigger a layout shift report, even if it continues moving a long distance at that rate; see first example in #53 (comment) . So this blog post's approach wouldn't ever receive a callback if they happened to only have slowly/subtly moving content.)

If in fact this "layout observer" sort of thing is not a use-case that this API intends to robustly support, then it might make sense to make that clear in the spec...

@npm1
Copy link
Collaborator

npm1 commented Oct 6, 2020

I wonder why they are not using IntersectionObserver instead? It is not an intended use-case. Another problem I see from using this API for that is that the PerformanceObserver delivery of entries could be delayed, and this use-case would require quick delivery of the entries.

@faultyserver
Copy link

Hi! I'm the author of that long post, so I can give some additional background. As a quick note, I've updated it to no longer "recommend" using LayoutShift, and rather to point out that it may seem like a relevant choice, but that this discussion is also open about the intended use.

IntersectionObserver is an interesting thought! At first my mind assumed that it wouldn't be useful, because we aren't looking to track when an element enters or leaves the viewport, but rather just when it changes positions within the viewport, where it most likely won't be intersecting anything or changing its intersection value at any point. We already have a more convenient solution to address scrolling and occlusion issues as described in that post by scoping where the ring gets rendered.

But, now that I think about it more, I think you are recommending that we could do something where the ring itself uses an IntersectionObserver between its own current bounding box and the target element to see if the element has moved at all? That, I must admit, is not a possibility I had considered, but I'm very interested in trying this approach now.

Coming back to LayoutShift, this use case would indeed require timely delivery of entries (ideally within the same frame window with additional time to be able to update before the frame renders), and would ideally be able to track shifts at any granularity, even down to 1px or lower. As I mention at the end of that post, what this ring system really wants is a "subscribe to animation frame" API, rather than requesting one. LayoutShift (from initially skimming the spec), seemed like a potential match to provide that kind of subscription, but with this new information it is clearly not a great fit. I think clarifying the intended limitations would be useful to prevent that kind of misunderstanding as this API becomes more widely available.

@dholbert
Copy link
Contributor Author

dholbert commented Oct 9, 2020

One more reason to explicitly recommend against (and perhaps design against) the "layout changed, let's run some JS to update all our CSS and reposition these elements" use-case: we don't want to end up in a future where some fraction of websites depend on browsers supporting this feature in order to render properly.

Layout-shift is meant as a developer-facing feature for monitoring performance/user-experience; so I think we should make it clear that it's only meant to be used in a way where its implementation status is effectively undetectable to users. (This will ensure that we can safely deprecate & drop support for this API in the future, without breaking sites, once we've got a hypothetical better metric available and/or when this metric hypothetically becomes impractical for next-gen web engines to implement.)

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

Successfully merging a pull request may close this issue.

3 participants