Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test has a WPT meta file that expects 27 subtest issues.
- This WPT test may be referenced by the following Test IDs:
- /css/css-conditional/match-container.tentative.html - WPT Dashboard Interop Dashboard
<!DOCTYPE html>
<title>Element.matchContainer</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
.size-container {
container-type: inline-size;
}
.style-container {
container-name: style-container;
}
</style>
<div id="root"></div>
<script>
function createTestElement(html) {
document.getElementById("root").innerHTML = html;
return document.getElementById("root").firstElementChild;
}
test(() => {
let container = createTestElement(`
<div class="size-container" style="width: 200px">
<div id="target"></div>
</div>
`);
let target = container.querySelector("#target");
let qMatches = target.matchContainer("(width: 200px)");
assert_true(qMatches.matches, "Exact width should match.");
let qLess = target.matchContainer("(width < 100px)");
assert_false(qLess.matches, "Target width is 200px, so < 100px should not match.");
let qGreater = target.matchContainer("(width > 100px)");
assert_true(qGreater.matches, "Target width is 200px, so > 100px should match.");
}, "Element.matchContainer correctly matches the size of its container query.");
test(() => {
let container = createTestElement(`
<div class="size-container" style="width: 200px">
<div id="target"></div>
</div>
`);
let target = container.querySelector("#target");
let invalidContainerQuery = target.matchContainer("(invalid-feature)");
assert_false(invalidContainerQuery.matches,
"matchContainer with invalid query should not match.");
}, "Element.matchContainer handles an invalid query.");
test(() => {
let container = createTestElement(`
<div class="size-container" style="width: 200px">
<div id="target"></div>
</div>
`);
let target = container.querySelector("#target");
let syntaxError = target.matchContainer("???");
assert_false(syntaxError.matches,
"matchContainer with syntax error should not match.");
let emptyQuery = target.matchContainer("");
assert_false(emptyQuery.matches,
"matchContainer with empty string should not match.");
}, "Element.matchContainer handles syntax errors and empty queries.");
test(() => {
let container = createTestElement(`
<div class="size-container" style="width: 200px">
<div id="target"></div>
</div>
`);
let target = container.querySelector("#target");
let q = target.matchContainer("(width > 100px)");
assert_true(q.matches, "Initially matches at 200px.");
container.style.width = "50px";
assert_false(q.matches, "Should flip to false after shrinking below 100px.");
container.style.width = "300px";
assert_true(q.matches, "Should flip back to true after growing above 100px.");
}, "Element.matchContainer .matches reflects container size changes dynamically.");
test(() => {
let container = createTestElement(`
<div class="size-container" id="displaycase" style="width: 200px">
<div id="target"></div>
</div>
`);
let target = container.querySelector("#target");
let q = target.matchContainer("(width > 100px)");
assert_true(q.matches, "Initially matches.");
target.style.display = "none";
assert_true(q.matches,
"display:none target still resolves to its container; matches the " +
"container's preserved width. (Mirrors @container rule semantics, " +
"which evaluate for display:none descendants — required for the " +
"@container { display: none } toggle pattern to work.)");
target.style.display = "block";
assert_true(q.matches, "Still matches after re-display.");
}, "Element.matchContainer .matches still evaluates when target is display:none.");
test(() => {
let container = createTestElement(`
<div class="size-container" style="width: 200px">
<div id="target"></div>
</div>
`);
let target = container.querySelector("#target");
let q = target.matchContainer("(width > 100px)");
assert_true(q.matches, "Initially matches while in tree.");
target.remove();
assert_false(q.matches,
"Removed target has no container; should not match.");
container.appendChild(target);
assert_true(q.matches, "Re-inserted target should match again.");
}, "Element.matchContainer .matches updates when the target is removed from and re-inserted into the dom tree.");
test(() => {
let container = createTestElement(`
<div class="style-container" style="--my-prop: foo">
<div id="target"></div>
</div>
`);
let target = container.querySelector("#target");
assert_true(target.matchContainer("style(--my-prop: foo)").matches,
"Style query for matching custom property should match.");
assert_false(target.matchContainer("style(--my-prop: bar)").matches,
"Style query for non-matching custom property should not match.");
assert_false(target.matchContainer("style(--missing: foo)").matches,
"Style query for unset custom property should not match.");
}, "Element.matchContainer matches style queries on a style container.");
test(() => {
let container = createTestElement(`
<div class="style-container" style="--my-prop: foo">
<div id="target"></div>
</div>
`);
let target = container.querySelector("#target");
let q = target.matchContainer("style(--my-prop: foo)");
assert_true(q.matches, "Initially matches.");
container.style.setProperty("--my-prop", "bar");
assert_false(q.matches, "Should flip to false after style change.");
container.style.setProperty("--my-prop", "foo");
assert_true(q.matches, "Should flip back to true after restoring value.");
}, "Element.matchContainer .matches reflects custom property changes on the style container dynamically.");
test(() => {
let container = createTestElement(`
<div class="size-container" style="width: 200px">
<div id="target"></div>
</div>
`);
let target = container.querySelector("#target");
assert_true(target.matchContainer("(width > 100px), (width < 50px)").matches,
"Matches when the first query in the list matches.");
assert_true(target.matchContainer("(width < 50px), (width > 100px)").matches,
"Matches when the second query in the list matches.");
assert_true(target.matchContainer("(width > 100px), (width: 200px)").matches,
"Matches when both queries in the list match.");
assert_false(target.matchContainer("(width < 50px), (width < 60px)").matches,
"Does not match when no query in the list matches.");
}, "Element.matchContainer matches a comma-separated list if any query matches.");
const serializationCases = [
["(width > 100px)", "(width > 100px)"],
["(width < 300px)", "(width < 300px)"],
["(min-width: 300px)", "(min-width: 300px)"],
["(not (max-width: 500px))", "(not (max-width: 500px))"],
["((max-width: 500px) and (max-height: 500px))",
"((max-width: 500px) and (max-height: 500px))"],
["((max-width: 500px) or (max-height: 500px))",
"((max-width: 500px) or (max-height: 500px))"],
["(width) and (height)", "(width) and (height)"],
["(width) or (height)", "(width) or (height)"],
["somename not (width)", "somename not (width)"],
["test_name (width) or (height)", "test_name (width) or (height)"],
["style(--my-prop: foo)", "style(--my-prop: foo)"],
["(min-width:300px)", "(min-width: 300px)"],
["(min-width: 300px)", "(min-width: 300px)"],
["(MIN-WIDTH: 300px)", "(min-width: 300px)"],
["(width<300px)", "(width < 300px)"],
["(width > 100px), (width < 50px)", "(width > 100px), (width < 50px)"],
["(width < 300px),(min-width: 300px)", "(width < 300px), (min-width: 300px)"],
];
for (const [input, expected] of serializationCases) {
test(() => {
let container = createTestElement(`
<div class="size-container" style="width: 200px">
<div id="target"></div>
</div>
`);
let target = container.querySelector("#target");
assert_equals(target.matchContainer(input).query, expected);
}, `Element.matchContainer .query serializes ${JSON.stringify(input)}`);
}
test(() => {
let container = createTestElement(`
<div class="size-container" style="width: 200px">
<div id="target"></div>
</div>
`);
let target = container.querySelector("#target");
assert_equals(target.matchContainer("???").query, "",
"query is empty for a syntax error.");
assert_equals(target.matchContainer("").query, "",
"query is empty for an empty query.");
assert_equals(target.matchContainer("(width > 100px),").query, "",
"query is empty for a trailing comma in the list.");
assert_equals(target.matchContainer(",(width > 100px)").query, "",
"query is empty for a leading comma in the list.");
}, "Element.matchContainer .query is empty for invalid queries.");
</script>