Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

  • This WPT test may be referenced by the following Test IDs:
<!doctype html>
<title>Image width and height attributes are used to infer aspect-ratio</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
img:not([nowidth]) {
width: 100%;
max-width: 100px;
height: auto;
}
</style>
<picture>
<source srcset="/images/green-100x50.png"></source>
<img>
</picture>
<picture>
<source srcset="/images/green-100x50.png" width="100" height="100"></source>
<img>
</picture>
<picture>
<source srcset="/images/green-100x50.png" width="100" height="100"></source>
<img width="50" height="100">
</picture>
<picture>
<source srcset="/images/green-100x50.png" width="100" height="100" id="twosource-s1"></source>
<source srcset="/images/green-100x50.png" width="300" height="150"></source>
<img id="twosource-img">
</picture>
<div style="width: 100px;">
<picture>
<source srcset="/images/green-100x50.png" width="100%" height="50%" id="percent-src"></source>
<img style="contain:size;" id="percent-img" nowidth="true">
</picture>
</div>
<picture>
<source srcset="/images/green-100x50.png" width="100abc" height="50abc" id="trailing-src"></source>
<img style="contain:size;" id="trailing-img" nowidth="true">
</picture>
<script>
let guard = async_test("source width and height attributes are used to infer aspect-ratio in <picture>");
function assert_ratio(img, expected, description) {
let epsilon = 0.001;
assert_approx_equals(parseFloat(getComputedStyle(img).width, 10) / parseFloat(getComputedStyle(img).height, 10),
expected, epsilon, description);
}
function createPicture(width, height) {
var picture = document.createElement("picture");
var source = document.createElement("source");
if (width !== undefined)
source.setAttribute("width", width);
if (height !== undefined)
source.setAttribute("height", height);
source.setAttribute("srcset", "/images/green.png");
picture.appendChild(source);
var img = document.createElement("img");
picture.appendChild(img);
document.body.appendChild(picture);
return img;
}
function assert_cs(img, val) {
assert_equals(getComputedStyle(img).aspectRatio, val);
}
// Create and append a new image and immediately check the ratio.
// This is not racy because the spec requires the user agent to queue a task:
test(function() {
var img = createPicture(100, 100);
assert_ratio(img, 1.0);
assert_cs(img, "auto 100 / 100");
img.style.display = "none";
img.setAttribute("nowidth", "true");
assert_equals(getComputedStyle(img).width, "100px");
assert_equals(getComputedStyle(img).height, "100px");
var source = img.previousSibling;
assert_equals(getComputedStyle(source).width, "auto");
assert_equals(getComputedStyle(source).height, "auto");
}, "Computed style for width/height/aspect-ratio");
test(function() {
img = createPicture(200, 100);
img.setAttribute("width", 250);
img.setAttribute("height", 50);
assert_ratio(img, 2.0);
assert_cs(img, "auto 200 / 100");
img.style.display = "none";
img.setAttribute("nowidth", "true");
assert_equals(getComputedStyle(img).width, "200px");
assert_equals(getComputedStyle(img).height, "100px");
source = img.previousSibling;
assert_equals(getComputedStyle(source).width, "auto");
assert_equals(getComputedStyle(source).height, "auto");
}, "Source width/height should take precedence over img attributes.");
test(function() {
img.parentNode.removeChild(img.previousSibling);
assert_cs(img, "auto 250 / 50");
img.src = "/images/green.png";
assert_ratio(img, 5.0);
img.style.display = "none";
img.setAttribute("nowidth", "true");
assert_equals(getComputedStyle(img).width, "250px");
assert_equals(getComputedStyle(img).height, "50px");
}, "Make sure style gets invalidated correctly when the source gets removed.");
test(function() {
img = createPicture(100, undefined);
img.setAttribute("width", 200);
img.setAttribute("height", 100);
assert_cs(img, "auto");
img.style.display = "none";
img.setAttribute("nowidth", "true");
assert_equals(getComputedStyle(img).width, "100px");
assert_equals(getComputedStyle(img).height, "auto");
}, "If the <source> has only one of width/height, we don't get an aspect ratio, even if the <img> has both.");
test(function() {
img = createPicture(undefined, undefined);
img.setAttribute("width", 200);
img.setAttribute("height", 100);
assert_cs(img, "auto 200 / 100");
}, "If we don't have width/height on the source, we fall back to width/height on the <img>.");
test(function() {
img = createPicture(100, undefined);
img.parentNode.style.display = "none";
img.setAttribute("width", "200");
img.setAttribute("height", "300");
img.setAttribute("nowidth", "true");
assert_cs(img, "auto");
assert_equals(getComputedStyle(img).width, "100px");
assert_equals(getComputedStyle(img).height, "auto");
}, "If we only have one width attribute, we should get width mapped but no aspect ratio, even if <img> has attributes.");
test(function() {
img = createPicture(undefined, 100);
img.parentNode.style.display = "none";
img.setAttribute("width", "200");
img.setAttribute("height", "300");
img.setAttribute("nowidth", "true");
assert_cs(img, "auto");
assert_equals(getComputedStyle(img).width, "auto");
assert_equals(getComputedStyle(img).height, "100px");
}, "If we only have height attribute, we should get height mapped but no aspect ratio, even if <img> has attributes.");
test(function() {
img = createPicture(100, 100);
assert_cs(img, "auto 100 / 100");
img.previousSibling.setAttribute("height", "300");
assert_cs(img, "auto 100 / 300");
img.previousSibling.setAttribute("width", "10");
assert_cs(img, "auto 10 / 300");
img.style.display = "none";
img.setAttribute("nowidth", "true");
assert_equals(getComputedStyle(img).width, "10px");
assert_equals(getComputedStyle(img).height, "300px");
}, "Dynamically changing width/height should change computed style");
test(function() {
img = document.getElementById("twosource-img");
assert_cs(img, "auto 100 / 100");
source = document.getElementById("twosource-s1");
source.setAttribute("type", "x-foo/x-bar");
// We should now match the second source
assert_cs(img, "auto 300 / 150");
img.style.display = "none";
img.setAttribute("nowidth", "true");
assert_equals(getComputedStyle(img).width, "300px");
assert_equals(getComputedStyle(img).height, "150px");
}, "Changing which <source> matches should change computed style");
test(function() {
img = document.getElementById("percent-img");
assert_equals(img.offsetWidth, 100);
assert_equals(img.offsetHeight, 0);
assert_cs(img, "auto");
source = document.getElementById("percent-src");
assert_equals(source.width, 100);
assert_equals(source.height, 50);
img.style.display = "none";
img.setAttribute("nowidth", "true");
assert_equals(getComputedStyle(img).width, "100%");
assert_equals(getComputedStyle(img).height, "50%");
}, "Percentages on source should be ignored for aspect-ratio but used for width/height.");
test(function() {
img = document.getElementById("trailing-img");
assert_equals(img.offsetWidth, 100);
assert_equals(img.offsetHeight, 50);
assert_cs(img, "auto 100 / 50");
source = document.getElementById("trailing-src");
assert_equals(source.width, 100);
assert_equals(source.height, 50);
img.style.display = "none";
img.setAttribute("nowidth", "true");
assert_equals(getComputedStyle(img).width, "100px");
assert_equals(getComputedStyle(img).height, "50px");
}, "Trailing garbage should be ignored but not make the attribute invalid");
onload = function() {
let images = document.querySelectorAll("img");
test(function() {
var img = images[0];
assert_ratio(img, 2.0, "2.0 is the original aspect ratio of green-100x50.png");
assert_cs(img, "auto");
img.style.display = "none";
img.setAttribute("nowidth", "true");
assert_equals(getComputedStyle(img).width, "auto");
assert_equals(getComputedStyle(img).height, "auto");
}, "Loaded picture test: Both <source> and <img> are without width and height attributes");
test(function () {
img = images[1];
assert_ratio(img, 2.0, "Loaded image's aspect ratio, at least by default, overrides width / height ratio.");
assert_cs(img, "auto 100 / 100");
img.style.display = "none";
img.setAttribute("nowidth", "true");
assert_equals(getComputedStyle(img).width, "100px");
assert_equals(getComputedStyle(img).height, "100px");
}, "Loaded picture test: <source> with width and height attributes, <img> without width and height attributes");
test(function () {
img = images[2];
assert_ratio(img, 2.0, "Loaded image's aspect ratio, at least by default, overrides width / height ratio (2).");
assert_cs(img, "auto 100 / 100");
img.style.display = "none";
img.setAttribute("nowidth", "true");
assert_equals(getComputedStyle(img).width, "100px");
assert_equals(getComputedStyle(img).height, "100px");
}, "Loaded picture test: Both <source> and <img> are with width and height attributes");
guard.done();
};
</script>