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 8, 2023
1 parent 66a4dc9 commit cd89fb5
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 24 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,7 +1,9 @@
<!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>
<script src="/common/rendering-utils.js"></script>
<style>
img { height: 10px; } /* Keep all images in the viewport, so lazy images load */
#narrow-div { width: 10px; }
Expand All @@ -16,42 +18,52 @@
<script>
"use strict";

// https://github.com/web-platform-tests/rfcs/pull/75
let async_promise_test = (promise, description) => {
async_test(test => {
promise(test)
.then(() => {test.done();})
.catch(test.step_func(error => { throw error; }));
}, description);
};

function check(imgOrPicture) {
let img = imgOrPicture;
let test = async_test(imgOrPicture.outerHTML);

let source;
if (imgOrPicture.localName === 'picture') {
source = imgOrPicture.firstChild;
img = imgOrPicture.lastChild;
}

const ref = document.getElementById(img.dataset.ref);
async_promise_test(async (t) => {
let expect = ref.currentSrc;
if (expect) {
expect = expect.split('?')[0];
}
let expect = ref.currentSrc;
if (expect) {
expect = expect.split('?')[0];
}

test.step(_ => {
if (expect === '' || expect === null || expect === undefined) {
assert_unreached('ref currentSrc was ' + format_value(expect));
}
await new Promise((resolve, reject) => {
img.onload = resolve;
img.onerror = reject;
});

img.addEventListener('load', _ => {
img.offsetWidth;

// Step #5 of the "Parsing a sizes attribute" spec
// https://html.spec.whatwg.org/#parsing-a-sizes-attribute
// states that:
// "If img is null, or img's loading attribute is not in the Lazy state,
// or img is not being rendered, or img's concrete object size ignoring
// natural dimensions width is zero, then return 100vw."
// Waiting for at least one frame to allow layout to finish, ensuring an
// accurate "img's concrete object size ignoring natural dimensions",
// which is used to select the currentSrc from the srcset.
waitForAtLeastOneFrame().then(_ => {
test.step(() => {
let got = img.currentSrc;
assert_greater_than(got.indexOf('?'), -1, 'expected a "?" in currentSrc');

got = got.split('?')[0];
assert_equals(got, expect);
});

test.done();
});
t.step(() => {
let got = img.currentSrc;
assert_greater_than(got.indexOf('?'), -1, 'expected a "?" in currentSrc');
got = got.split('?')[0];
assert_equals(got, expect);
})
}, imgOrPicture.outerHTML);
});
}

const tests = [
Expand Down

0 comments on commit cd89fb5

Please sign in to comment.