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

Fix image sizing penalty to use CSS terms #99

Merged
merged 7 commits into from Jul 19, 2022
Merged

Fix image sizing penalty to use CSS terms #99

merged 7 commits into from Jul 19, 2022

Conversation

noamr
Copy link
Contributor

@noamr noamr commented Apr 26, 2022

This takes CSS sizing and layout for backgrounds & regular images into account.

Note that because of CSS object positioning, there still might be scenario of a big image that's not intersecting with the viewport but is counted towards LCP.

Closes #98


Preview | Diff

This takes CSS sizing and layout for backgrounds & regular images into account.

Closes #98
@noamr noamr requested review from npm1 and yoavweiss April 26, 2022 14:16
@npm1
Copy link
Collaborator

npm1 commented Apr 26, 2022

What is an implementation change resulting from this PR (which I think there are some?)? Do we have tests for such changes?

@noamr
Copy link
Contributor Author

noamr commented Apr 26, 2022

What is an implementation change resulting from this PR (which I think there are some?)? Do we have tests for such changes?

This is meant, for a start, as a discussion point for #98. If it seems like a good direction I'd be happy to cover this with some tests.

@yoavweiss
Copy link
Contributor

^^ @sefeng211 @emilio

@sefeng211
Copy link

I should say nothing in this PR and just defer to Emilio. (Sorry about push more works to your table)

index.bs Show resolved Hide resolved
@npm1
Copy link
Collaborator

npm1 commented Apr 28, 2022

"Note that because of CSS object positioning, there still might be scenario of a big image that's not intersecting with the viewport but is counted towards LCP." seems like a problem. Besides this, what are some examples where this change improves the LCP size?

@noamr
Copy link
Contributor Author

noamr commented Apr 28, 2022

"Note that because of CSS object positioning, there still might be scenario of a big image that's not intersecting with the viewport but is counted towards LCP." seems like a problem. Besides this, what are some examples where this change improves the LCP size?

It's a problem in the sense that you might not actually intersect with the image, but its not directly affecting the image upscaling penalty.it can be handled separately.

This patch would make the upscaling penalty a lot more accurate in cases where css affects the image size and not just the width/height attributes, which is almost always - background-size, object-size, css width/height attributes, flex/grid etc.

You're right in the sense that this is doesn't solve all the issues of image content size.

@noamr
Copy link
Contributor Author

noamr commented Apr 28, 2022

"Note that because of CSS object positioning, there still might be scenario of a big image that's not intersecting with the viewport but is counted towards LCP." seems like a problem. Besides this, what are some examples where this change improves the LCP size?

It's a problem in the sense that you might not actually intersect with the image, but its not directly affecting the image upscaling penalty.it can be handled separately.

This patch would make the upscaling penalty a lot more accurate in cases where css affects the image size and not just the width/height attributes, which is almost always - background-size, object-size, css width/height attributes, flex/grid etc.

You're right in the sense that this is doesn't solve all the issues of image content size.

A concrete example:

In the current spec, a 1x1 image scaled to 1000px*1000px with CSS (e.g. by having width: 100vh in its style) might be eligible for LCP because its scaling is done via CSS and not via the width/height attribute. this allows devs to "game" LCP by scaling tiny images in this way.

@yoavweiss
Copy link
Contributor

This change makes sense from my perspective. Can you accompany it with tests, to outline what implementations would need to change?

@noamr
Copy link
Contributor Author

noamr commented May 2, 2022

I've updated the patch to also account for object position and transforms. I think it's pretty rigorous now in terms of catching image edge cases. The idea is that it would always return only the intersecting visible rect of the image rather than the element, and divide that area by the image's upscaling factor.
I'll start working on WPTs.

@sefeng211
Copy link

The natural dimension can be 0 for svg images, what do we do with this case?

@noamr
Copy link
Contributor Author

noamr commented May 13, 2022

The natural dimension can be 0 for svg images, what do we do with this case?

0-size images should not contribute to LCP :) Added a line to explicitly say that and avoid the div-by-zero.

@emilio
Copy link

emilio commented May 13, 2022

@noamr this is not about 0-sized images, but about SVG images that don't have an intrinsic size (SVG images can only have an intrinsic ratio for example).

@noamr
Copy link
Contributor Author

noamr commented May 13, 2022

@noamr this is not about 0-sized images, but about SVG images that don't have an intrinsic size (SVG images can only have an intrinsic ratio for example).

What are the current dimensions used to display these if they don't have width/height attributes?

@emilio
Copy link

emilio commented May 13, 2022

Whatever CSS says. Also this is a place where browsers aren't quite interoperable. IIRC Blink falls back to the 300x150 size that iframes use, but Gecko doesn't.

@noamr
Copy link
Contributor Author

noamr commented May 13, 2022

Whatever CSS says. Also this is a place where browsers aren't quite interoperable. IIRC Blink falls back to the 300x150 size that iframes use, but Gecko doesn't.

Also Firefox falls back to 300x150 for <img src="something.svg" />

I think in the case of unspecified size SVG there shouldn't be an image penalty.
Since in SVG upscaling is not a reduction in quality, we might want to exclude this penalty for SVG altogether.

If it's about gaming the metric, I don't think this penalty helps when it comes to SVG. (see #72).

@yoavweiss @npm1 ?

@noamr
Copy link
Contributor Author

noamr commented Jul 17, 2022

Whatever CSS says. Also this is a place where browsers aren't quite interoperable. IIRC Blink falls back to the 300x150 size that iframes use, but Gecko doesn't.

Also Firefox falls back to 300x150 for <img src="something.svg" />

I think in the case of unspecified size SVG there shouldn't be an image penalty. Since in SVG upscaling is not a reduction in quality, we might want to exclude this penalty for SVG altogether.

If it's about gaming the metric, I don't think this penalty helps when it comes to SVG. (see #72).

@yoavweiss @npm1 ?

Ping @yoavweiss

Copy link
Collaborator

@npm1 npm1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had looked at this before, but never actually posted the comments

index.bs Outdated
1. Let |penaltyFactor| be <code>min(|displaySize|, |naturalSize|) / |displaySize|</code>.
1. Multiply |size| by |penaltyFactor|.
1. If |imageRequest| is not null, run the following steps to reduce the computed size of upscaled images:
1. Let (|naturalWidth|, |naturalHeight|) be |imageRequest|'s [=natural dimension=].
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be natural dimensions ie plural? Also this is clear but not technically correct as those are a triple and here you have two variables. I think you can use natural sizes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's an existing reference to CSS

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

index.bs Outdated Show resolved Hide resolved
index.bs Outdated Show resolved Hide resolved
Copy link
Contributor

@yoavweiss yoavweiss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

1. Let |concreteDimensions| be |imageRequest|'s [=concrete object size=] within |element|.
1. Let |visibleDimensions| be |concreteDimensions|, adjusted for positioning by 'object-position' or 'background-position' and |element|'s [=content box=].

Note: some of those algorithms are not rigorously defined in CSS. The expected result is to get the actual position and size of the image in |element| as a {{DOMRectReadOnly}}.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with this note, and had the same thoughts while reading through this. Maybe we can file bugs against CSS?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@noamr noamr merged commit 2da152d into main Jul 19, 2022
@noamr noamr deleted the image-sizing branch July 19, 2022 09:22
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 this pull request may close these issues.

Use naturalSize doesn't make sense for css images
5 participants