Skip to content

Commit

Permalink
Implement auto sizes for lazy-loaded img
Browse files Browse the repository at this point in the history
Auto Sizes allows developers to omit the sizes attribute (or set it to
sizes=auto) for lazy loaded image elements with srcset. For this use
case the image's width should be provided. The browser will use the
layout width of the image in order to select the source url from the
srcset.

Spec PR:
whatwg/html#8008

WPT tests PR:
#34427

Chrome Platform Status link:
https://chromestatus.com/feature/5191555708616704

Intent to Prototype link:
https://groups.google.com/a/chromium.org/g/blink-dev/c/AYoqvNluyeA

R=pdr

Bug: 1359051
Low-Coverage-Reason: For html_srcset_parser.cc, it should be
                     covered by `image-srcset-cache.html`
                     but there seems to be cov reporing problem.
Change-Id: I8e9bc836e9582a9209db53d55e0edc96f90499f2
  • Loading branch information
tcaptan-cr authored and chromium-wpt-export-bot committed Jun 15, 2023
1 parent 293bb6c commit b5d1d68
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!doctype html>
<title>Auto sizes rendering</title>
<link rel="help" href="https://html.spec.whatwg.org/multipage/images.html#sizes-attributes">
<meta name="assert" content="auto sizes rendering">
<img
src="/images/green.png"
width="100px"
>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!doctype html>
<html class="reftest-wait">
<title>Auto sizes rendering</title>
<link rel="help" href="https://html.spec.whatwg.org/multipage/images.html#sizes-attributes">
<link rel="match" href="reference/sizes-auto-rendering-ref.html">
<script src="/common/rendering-utils.js"></script>
<script src="/common/reftest-wait.js"></script>
<meta name="assert" content="auto sizes rendering">
<img
id="testImg"
loading="lazy"
srcset="
/images/red.png 50w,
/images/green.png 100w
"
sizes="auto"
width="100px"
>
<script>
function imageLoaded() {
waitForAtLeastOneFrame().then(takeScreenshot);
}

testImg.addEventListener('load', imageLoaded);
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!doctype html>
<html class="reftest-wait">
<title>Auto sizes rendering</title>
<link rel="help" href="https://html.spec.whatwg.org/multipage/images.html#sizes-attributes">
<link rel="match" href="reference/sizes-auto-rendering-ref.html">
<script src="/common/rendering-utils.js"></script>
<script src="/common/reftest-wait.js"></script>
<meta name="assert" content="auto sizes rendering">
<img
id="testImg"
loading="lazy"
srcset="
/images/green.png 100w,
/images/red.png 200w
"
sizes="auto"
width="100px"
>
<script>
function imageLoaded() {
waitForAtLeastOneFrame().then(takeScreenshot);
}

testImg.addEventListener('load', imageLoaded);
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!doctype html>
<html class="reftest-wait">
<title>Auto sizes dynamic rendering</title>
<link rel="help" href="https://html.spec.whatwg.org/multipage/images.html#sizes-attributes">
<link rel="match" href="reference/sizes-auto-rendering-ref.html">
<script src="/common/rendering-utils.js"></script>
<script src="/common/reftest-wait.js"></script>
<meta name="assert" content="auto sizes dynamic rendering">
<img
id="testImg"
loading="lazy"
srcset="
/images/fail.gif 200w,
/images/green.png 100w,
/images/red.png 50w
"
sizes="auto"
width="50px"
>
<script>
function secondImageLoaded() {
waitForAtLeastOneFrame().then(takeScreenshot);
}

function firstImageLoaded() {
testImg.addEventListener('load', secondImageLoaded);
testImg.style.width = '100px';
}

testImg.addEventListener('load', firstImageLoaded, {once: true});
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!doctype html>
<html class="reftest-wait">
<title>Auto sizes rendering</title>
<link rel="help" href="https://html.spec.whatwg.org/multipage/images.html#sizes-attributes">
<link rel="match" href="reference/sizes-auto-rendering-ref.html">
<script src="/common/rendering-utils.js"></script>
<script src="/common/reftest-wait.js"></script>
<meta name="assert" content="auto sizes rendering">
<img
id="testImg"
loading="lazy"
srcset="
/images/fail.gif 50w,
/images/green.png 100w,
/images/red.png 200w
"
sizes="auto"
width="100px"
>
<script>
function imageLoaded() {
waitForAtLeastOneFrame().then(takeScreenshot);
}

testImg.addEventListener('load', imageLoaded);
</script>
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
<!doctype html>
<title>img parse a sizes attribute: sizes=auto</title>
<link rel="help" href="https://html.spec.whatwg.org/multipage/images.html#parse-a-sizes-attribute">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
img { height: 10px; } /* Keep all images in the viewport, so lazy images load */
#narrow-div { width: 10px; }
#wide-div { width: 500px; }
img { height: 8px; } /* Keep all images in the viewport, so lazy images load */
#narrow-div { width: 8px; }
#wide-div { width: 100px; }
</style>
<div id=log></div>
<script src="support/parse-a-sizes-attribute.js"></script>
<img srcset='/images/green-1x1.png?ref1 50w, /images/green-16x16.png?ref1 51w' sizes='1px' id=ref1>
<img srcset='/images/green-1x1.png?ref2 50w, /images/green-16x16.png?ref2 51w' sizes='100vw' id=ref2>
<img srcset='/images/green-8x8.png?ref1 8w, /images/green-16x16.png?ref1 16w' sizes='1px' id=ref1>
<img srcset='/images/green-8x8.png?ref2 8w, /images/green-16x16.png?ref2 16w' sizes='100vw' id=ref2>
<div id='narrow-div'></div>
<div id='wide-div'></div>
<script>
Expand Down Expand Up @@ -58,38 +59,39 @@
// Smoke tests
{sizes: '1px', 'data-ref': 'ref1'},
{sizes: '', 'data-ref': 'ref2'},

// Actual tests
{loading: 'lazy', sizes: 'auto', width: '10', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'AUTO', width: '10', 'data-ref': 'ref1'},
{loading: 'lazy', width: '10', 'data-ref': 'ref1'},
{loading: 'lazy', style: 'width: 10px', 'data-ref': 'ref1'},
{loading: 'lazy', style: 'max-width: 10px', 'data-ref': 'ref2'}, // no specified width -> 0 -> 100vw
{loading: 'lazy', style: 'width: 100%; max-width: 10px', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', width: '8', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'AUTO', width: '8', 'data-ref': 'ref1'},
{loading: 'lazy', width: '8', 'data-ref': 'ref1'},
{loading: 'lazy', style: 'width: 8px', 'data-ref': 'ref1'},
{loading: 'lazy', style: 'height: 10px; max-width: 10px', 'data-ref': 'ref2'}, // no specified width -> 0 -> 100vw
{loading: 'lazy', style: 'width: 100%; max-width: 8px', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', width: '500', 'data-ref': 'ref2'},
{loading: 'lazy', sizes: 'auto', width: '10', style: 'visibility: hidden', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', width: '10', style: 'display: inline', hidden: '', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', width: '8', style: 'visibility: hidden', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', width: '8', style: 'display: inline', hidden: '', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', width: '0', 'data-ref': 'ref2'}, // 0 -> 100vw
{loading: 'lazy', sizes: 'auto', style: 'width: 0px', 'data-ref': 'ref2'}, // 0 -> 100vw
{loading: 'lazy', sizes: 'auto', 'data-ref': 'ref2'}, // no specified width -> 0 -> 100vw
{loading: 'lazy', sizes: 'auto, 100vw', width: '10', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto, 100vw', width: '8', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: '100vw, auto', width: '10', 'data-ref': 'ref2'},
{loading: 'eager', sizes: 'auto', width: '10', 'data-ref': 'ref2'},
{loading: 'lazy', sizes: 'auto', width: '100%', parent: 'narrow-div', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', width: '100%', parent: 'wide-div', 'data-ref': 'ref2'},
{loading: 'lazy', sizes: 'auto', style: 'height: 10px; aspect-ratio: 10 / 10', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'height: 8px; aspect-ratio: 10 / 10', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'height: 10px; aspect-ratio: 500 / 10', 'data-ref': 'ref2'},
{loading: 'lazy', sizes: 'auto', style: 'min-height: 10px; aspect-ratio: 10 / 10', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'min-height: 8px; aspect-ratio: 10 / 10', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'min-height: 10px; aspect-ratio: 500 / 10', 'data-ref': 'ref2'},
{loading: 'lazy', sizes: 'auto', style: 'inline-size: 10px', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'min-inline-size: 10px', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'block-size: 10px; aspect-ratio: 10 / 10', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'min-block-size: 10px; aspect-ratio: 10 / 10', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'block-size: 10px; writing-mode: vertical-rl', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'min-block-size: 10px; writing-mode: vertical-rl', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'inline-size: 10px; aspect-ratio: 10/10; writing-mode: vertical-rl', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'min-inline-size: 10px; aspect-ratio: 10/10; writing-mode: vertical-rl', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: '--my-width: 10px; width: var(--my-width)', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'width: calc(5px + 5px)', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'inline-size: 8px', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'min-inline-size: 8px', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'block-size: 8px; aspect-ratio: 10 / 10', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'min-block-size: 8px; aspect-ratio: 10 / 10', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'block-size: 8px; writing-mode: vertical-rl', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'min-block-size: 8px; writing-mode: vertical-rl', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'inline-size: 8px; aspect-ratio: 10/10; writing-mode: vertical-rl', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'min-inline-size: 8px; aspect-ratio: 10/10; writing-mode: vertical-rl', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: '--my-width: 8px; width: var(--my-width)', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'width: calc(4px + 4px)', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'position: absolute; left: 50%; right: 49%', 'data-ref': 'ref2'}, // replaced elements don't get the width resolved from 'left'/'right' per https://drafts.csswg.org/css2/#abs-replaced-width
];

Expand All @@ -103,7 +105,7 @@
img.setAttribute(attr, obj[attr]);
}
}
img.srcset = `/images/green-1x1.png?img${i} 50w, /images/green-16x16.png?img${i} 51w`
img.srcset = `/images/green-8x8.png?img${i} 8w, /images/green-16x16.png?img${i} 16w`
parent.appendChild(img);
check(img);
}
Expand All @@ -128,7 +130,7 @@
break;
}
}
source.srcset = `/images/green-1x1.png?picture${i} 50w, /images/green-16x16.png?picture${i} 51w`;
source.srcset = `/images/green-8x8.png?picture${i} 8w, /images/green-16x16.png?picture${i} 16w`;
picture.appendChild(source);
picture.appendChild(img);
parent.appendChild(picture);
Expand Down
Binary file added images/green-8x8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b5d1d68

Please sign in to comment.