GithubHelp home page GithubHelp logo

The "move distance" metric imposes a strange penalty on extremely-offscreen content (depending on how far offscreen it was) about layout-instability HOT 22 OPEN

wicg avatar wicg commented on July 30, 2024
The "move distance" metric imposes a strange penalty on extremely-offscreen content (depending on how far offscreen it was)

from layout-instability.

Comments (22)

npm1 avatar npm1 commented on July 30, 2024 2

Yea that sounds like a bug to me. I think we should ignore content that was moved from being completely offscreen to partially or fully onscreen. Similarly, we should ignore content that was onscreen and moved to being completely offscreen. For content that was partially onscreen and moved to still be (at least partially) onscreen, does the current algorithm correctly capture the move distance or do you think we need to make some modifications in cases where the content is not fully onscreen?

from layout-instability.

dholbert avatar dholbert commented on July 30, 2024

CC @npm1 @mattwoodrow

from layout-instability.

dholbert avatar dholbert commented on July 30, 2024

For partially-onscreen stuff, I suspect the current algorithm is fine, yeah.

(Thoughts on that, for the Move Distance metric: if an element moves by 100px, then the user still sees something moving by 100px, regardless of whether the element is fully vs. partially onscreen. So it makes sense for us not to care whether the element is fully vs. partially onscreen for this calculation.

And the offscreen portion will still be "discounted" via the reduction in Impact Area for the moved thing, since the Impact Area excludes offscreen stuff, via the definition of Visual Representation.)

from layout-instability.

skobes-chromium avatar skobes-chromium commented on July 30, 2024

I don't think we should ignore any content that was moved to/from partially/fully offscreen positions. That would give a free pass to pages that shift everything by more than the viewport height.

But I agree with setting an upper bound on the move distance. In the example described it is true that it's "not any better or worse for its prior posiiton to be at -1000px vs. -50px, as long as it was entirely clipped at that point".

For an element with height e_h moving from y0 to y1 in viewport coordinates, and viewport height v_h, it should be ok to use
move_distance = min(y1, v_h) –⁠ max(y0, –⁠e_h)
instead of
move_distance = y1 –⁠ y0.

from layout-instability.

npm1 avatar npm1 commented on July 30, 2024

Ah yes we need to penalize full viewport moves, though from a user perspective I still think that content that was entirely offscreen and now appearing onscreen is the same as 'new content', so could we only penalize the content that leaves the screen in those cases? Also, looks like your suggested change for move distance can still result in a value larger than v_h, so would it make sense to trim it to be at most v_h or are there cases where having larger values makes sense?

from layout-instability.

skobes-chromium avatar skobes-chromium commented on July 30, 2024

The idea that makes sense to me is to ignore the "fully offscreen" movement, but count the "partially onscreen" movement. In theory an element could shift by up to (v_h + e_h), minus some small delta, and be partially visible both before and after.

from layout-instability.

npm1 avatar npm1 commented on July 30, 2024

Yea I think we agree on counting partially onscreen movement. What I previously suggested was ignoring fully offscreen movement (with that being the starting or ending state), but you pointed out that a full viewport move might trigger no layout shift. Hence my updated suggestion was to just ignore starting fully offscreen moves, but still count moves when the element ends up fully offscreen. Does that make sense?

from layout-instability.

skobes-chromium avatar skobes-chromium commented on July 30, 2024

Sorry I was responding to your second question (why do we want values larger than v_h).

I am not sure why we would want to treat fully-offscreen to onscreen differently from onscreen to fully-offscreen. It seems to me we can keep the symmetry of counting both cases, while addressing the primary concern of this issue which is setting an upper bound on the movement distance.

from layout-instability.

npm1 avatar npm1 commented on July 30, 2024

Ok, that makes sense to me. I thought about it and excluding some offscreen cases has some problems in terms of the 'smoothness' of the layout shift function, so probably not desirable.

from layout-instability.

skobes-chromium avatar skobes-chromium commented on July 30, 2024

Filed crbug.com/1127567 to update Chromium implementation.

from layout-instability.

skobes-chromium avatar skobes-chromium commented on July 30, 2024

I now notice, after all of this, that we already limit the distance fraction to be <= 1.0.

https://wicg.github.io/layout-instability/#distance-fraction

Was there any need to limit the move vector, when the distance fraction has its own limit?

from layout-instability.

dholbert avatar dholbert commented on July 30, 2024

Hmm, fair point; that means #73 (limiting the move vector to 2x the viewport) is probably redundant & doesn't make a meaningful difference; and it sets a modest upper-limit on how much an arbitrarily-far-away offscreen element can hurt your score.

The original scenario that I had in mind here was content appearing from "just-offscreen" vs. "somewhat further offscreen", and it just feels odd (from a user-impact perspective) that we penalize these differently depending on how far offscreen (in terms of fraction-of-viewport-size) the content was. I think I was originally envisioning that maybe we'd clamp the move vector to only incorporate the on-screen portion of movement, or something. Having said that, maybe it's simpler to not bother with this.

from layout-instability.

dholbert avatar dholbert commented on July 30, 2024

Basically: for sites that hide content by positioning it offscreen (e.g. so they can measure it and reason about its layout before displaying it), I'm concerned that this piece of the spec is incentivizing them to position their offscreen content as close to the viewport as possible, i.e. directly adjacent to the viewport. (e.g. at left:-100px for a 100px-wide div). I can absolutely see this being part of a "Top 10 easy ways to do SEO by improving your CLS score" clickbaity webdev blog post.

And despite "optimizing" the CLS score, this choice (placing your offscreen stuff just barely offscreen) has no upside, and has definite downsides. If the offscreen div happens to have content that overflows a little bit in a particular configuration (e.g. due to a box-shadow, or due to the user having an unexpected set of fonts, or an a11y-related minimum font size, or a particular piece of unexpectedly-wide content), then that overflowing content will leak out of the offscreen element & onto the viewport, where otherwise it would not have been visible if the web developer had kept it at left: 10000px or whatever.

from layout-instability.

dholbert avatar dholbert commented on July 30, 2024

@npm: I see this is now closed - I'd still be interested in your / @skobes 's thoughts/feedback on the issue that I brought up in my most recent comment here.

from layout-instability.

skobes-chromium avatar skobes-chromium commented on July 30, 2024

It seems to me that with the distance fraction limited to 1.0, there is not a significant incentive to position offscreen content as close to the viewport as possible. The score is the same for left: -100vw as it is for left: -10000px. There may be a small difference for negative offsets of less than the viewport width. Is that what you're concerned about, or something else?

from layout-instability.

npm1 avatar npm1 commented on July 30, 2024

If I understand the concern correctly, here is the problem. Suppose I have a div with width and height 100 and it's offscreen and moving it onscreen to the top left corner. Suppose viewport size is square 500. Assume it's the only thing that moves in that animation frame.

  • If the div was initially on left: -100 top: -100 then the move distance is computed as 200. The distance fraction will be 200/500 = 0.4.
  • If the div was on left:-1000 top: -1000 then the move distance is large and the distance fraction will be 1.0.

Both cases are the same for user experience but receive quite different CLS scores. Is this example what you had in mind @dholbert?

from layout-instability.

dholbert avatar dholbert commented on July 30, 2024

@skobes: right, there's no difference between -100vw and larger values. My concern here is about the fact that we're giving better scores to stuff positioned adjacent to the viewport as opposed to separated a healthy distance from the viewport.

@npm1: Yes, your example is the scenario I'm talking about. (though let's disregard top since it's unnecessary; left on its own is sufficient to get us offscreen. The same concerns apply regardless of whether you use top or left or both of them, though.) Moreover, you said "both cases are the same for user experience" - in fact I think the case that we're incentivizing is the one that is at risk of giving a worse user experience, per below:

My concern is:
(1) We're incentivizing the web developer to use left:-100 in your example there (rather than a larger offset) since it gives the minimum CLS penalty.
(2) That is precisely the wrong thing that we want to incentivize, because if the web developer has any sort of mistake that creates a small amount of overflow (e.g. unexpectedly wide image or word, unexpected font on user's system, unaccounted-for box-shadow), then that overflow will end up leaking onscreen and breaking the user experience.

So it would be better for us not create this incentive to nudge authors towards something that's demonstrably worse/more-fragile.

from layout-instability.

dholbert avatar dholbert commented on July 30, 2024

One option for solving this: we could disregard movement that's outside of a scroll frame's scrollable overflow area.

Per https://drafts.csswg.org/css-overflow-3/#scrolling-direction : "UAs must clip the scrollable overflow area of scroll containers on the block-start and inline-start sides of the box (thereby behaving as if they had no scrollable overflow on that side)." If we could arrange to exclude layout shifts that occur in that region (i.e. ignoring the portion of the movement vector that is outside of the scrollable overflow area, or something to that effect), then that would address my concerns here, I think.

from layout-instability.

npm1 avatar npm1 commented on July 30, 2024

I would be fine excluding those, personally. Note sure how @skobes feels about this though

from layout-instability.

skobes-chromium avatar skobes-chromium commented on July 30, 2024

Sounds good to me.

from layout-instability.

mmocny avatar mmocny commented on July 30, 2024

I like the suggestion of disregard movement that's outside of a scroll frame's scrollable overflow area.

However, should we completely disregard all movement when the movement started outside of that area, or just the portion that was outside?

Here's what concerns be about discarding just the portion:

  • left: -1000 to left:0 -> move distance of 100
  • left: -100 to left:0 -> move distance of 100
  • left: -100 to left: 400 -> move distance of 500

It is good that extremely-offscreen content scores the same as nearly-offscreen content now, but, why should content that is moved further away from viewport boundary appear to score worse? This wasn't actually a "move" after all...

For the user, it appears out of nowhere in both cases, as if it were just added to DOM, and occupies the same overall size.


Earlier, Steve argued that it "would give a free pass to pages that shift everything by more than the viewport height.", but I think that only applies when doing viewport clipping and not scrollable overflow area clipping, right?

from layout-instability.

dholbert avatar dholbert commented on July 30, 2024

This wasn't actually a "move" after all...
For the user, it appears out of nowhere in both cases, as if it were just added to DOM, and occupies the same overall size.

I had the same thought, and I think this is a good point. Strawman proposal: maybe we should just give a free pass to elements whose current or previous-frame "Visual Representation" is empty? (Note that the "Visual Representation" is defined such that it excludes points outside of the viewport.) That seems like it would match the "user-perceives-it-as-being-just-added-to-the-DOM" (or removed from the DOM) scenario pretty closely.

(The dependence on "viewport" in Visual Representation might be problematic for our purposes here, though -- it might not handle elements that are out-of-a-scrollable-div's-scrollable-region, e.g. the abspos "Hi" text in this example which is partially out-of-view (just so you can tell where it is). If you adjust the left and/or top for the "Hi" text such that it's entirely out of it's scrollframe's scrollable area, then it's clearly not visible so it feels like its Visual Representation should be empty; but it's still inside the geometry of the document's viewport, sort of, so I'm not sure what that means for its Visual Representation.)

from layout-instability.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.