Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test has a WPT meta file that expects 36 subtest issues.
- This WPT test may be referenced by the following Test IDs:
- /html/semantics/embedded-content/the-img-element/sizes/sizes-auto.html - WPT Dashboard Interop Dashboard
<!doctype html>
<title>img parse a sizes attribute: sizes=auto</title>
<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; }
</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>
<div id='narrow-div'></div>
<div id='wide-div'></div>
<script>
"use strict";
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 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];
}
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;
});
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 = [
// 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': 'ref2'}, // no `sizes: 'auto'` -> 100vw
{loading: 'lazy', style: 'width: 10px', 'data-ref': 'ref2'}, // no `sizes: 'auto'` -> 100vw
{loading: 'lazy', style: 'max-width: 10px', 'data-ref': 'ref2'}, // no `sizes: 'auto'` -> 100vw
{loading: 'lazy', style: 'width: 100%; max-width: 10px', 'data-ref': 'ref2'}, // no `sizes: 'auto'` -> 100vw
{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: '0', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', style: 'width: 0px', 'data-ref': 'ref1'},
{loading: 'lazy', sizes: 'auto', 'data-ref': 'ref2'}, // no width -> UA default of 300px
{loading: 'lazy', sizes: 'auto, 100vw', width: '10', '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: 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: 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': 'ref2'}, // no width -> UA default of 300px
{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': 'ref2'}, // no width -> UA default of 300px
{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: '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
];
function test_img(obj, i) {
const img = document.createElement('img');
let parent = document.body;
for (const attr in obj) {
if (attr === 'parent') {
parent = document.getElementById(obj.parent);
} else {
img.setAttribute(attr, obj[attr]);
}
}
img.srcset = `/images/green-1x1.png?img${i} 50w, /images/green-16x16.png?img${i} 51w`
parent.appendChild(img);
check(img);
}
function test_picture(obj, i) {
const picture = document.createElement('picture');
const source = document.createElement('source');
const img = document.createElement('img');
let parent = document.body;
for (const attr in obj) {
switch (attr) {
case 'parent':
parent = document.getElementById(obj.parent);
break;
case 'sizes':
// Authors have to specify sizes="auto" on the img to use auto-sizes.
if(obj[attr].toLowerCase().startsWith("auto")) {
img.setAttribute(attr, obj[attr]);
break;
}
case 'type':
case 'media':
source.setAttribute(attr, obj[attr]);
break;
default:
img.setAttribute(attr, obj[attr]);
break;
}
}
source.srcset = `/images/green-1x1.png?picture${i} 50w, /images/green-16x16.png?picture${i} 51w`;
picture.appendChild(source);
picture.appendChild(img);
parent.appendChild(picture);
check(picture);
}
onload = () => {
let i = 0;
for (const obj of tests) {
i++;
test_img(obj, i);
test_picture(obj, i);
}
done();
}
</script>