Files
sousa-gecko/testing/web-platform/tests/css/css-conditional/match-container.tentative.html
T
Seokho Song 06c4f0ceda Bug 2036834 [wpt PR 59633] - Implement Element.matchContainer, a=testonly
Automatic update from web-platform-tests
Implement Element.matchContainer

Introduces the Element.matchContainer() method, providing a JavaScript
API to evaluate CSS container queries against a specific element and
observe state changes. This functions similarly to window.matchMedia()
but targets container queries.

* Add "ElementMatchContainer" feature flag.

* Exposes the "matchContainer" method on the "Element" interface.

* Introduces the "ContainerQueryList" interfaces to represent the query state. "ContainerQueryListEvent" will be implemented on the later CL.
These are similar with MediaQueryList and MediaQueryListEvent.

Spec PR: https://github.com/w3c/csswg-drafts/pull/13551
Intent to Prototype: https://groups.google.com/a/chromium.org/g/blink-dev/c/70qTl8BnzR4/m/n480dIuEAgAJ
Feature Entry: https://chromestatus.com/feature/5150754462629888

Bug: 40887402
Change-Id: I8f74b8650f10cc49b82f617b9b9b88281b2d6b63
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7656126
Reviewed-by: Anders Hartvoll Ruud <andruud@chromium.org>
Commit-Queue: Seokho Song <seokho@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1624615}

--

wpt-commits: 2021583074d4d318e975dce580f7868250a0446b
wpt-pr: 59633
2026-05-08 08:40:25 +00:00

142 lines
5.6 KiB
HTML

<!DOCTYPE html>
<title>Element.matchContainer</title>
<link rel="help" href="https://github.com/w3c/csswg-drafts/pull/13551">
<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.");
</script>