Skip to content

Commit 06c4f0c

Browse files
DevSDKmoz-wptsync-bot
authored andcommitted
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: w3c/csswg-drafts#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
1 parent f61c247 commit 06c4f0c

1 file changed

Lines changed: 141 additions & 0 deletions

File tree

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
2+
<!DOCTYPE html>
3+
<title>Element.matchContainer</title>
4+
<link rel="help" href="https://github.com/w3c/csswg-drafts/pull/13551">
5+
<script src="/resources/testharness.js"></script>
6+
<script src="/resources/testharnessreport.js"></script>
7+
<style>
8+
.size-container {
9+
container-type: inline-size;
10+
}
11+
.style-container {
12+
container-name: style-container;
13+
}
14+
</style>
15+
<div id="root"></div>
16+
<script>
17+
function createTestElement(html) {
18+
document.getElementById("root").innerHTML = html;
19+
return document.getElementById("root").firstElementChild;
20+
}
21+
test(() => {
22+
let container = createTestElement(`
23+
<div class="size-container" style="width: 200px">
24+
<div id="target"></div>
25+
</div>
26+
`);
27+
let target = container.querySelector("#target");
28+
let qMatches = target.matchContainer("(width: 200px)");
29+
assert_true(qMatches.matches, "Exact width should match.");
30+
let qLess = target.matchContainer("(width < 100px)");
31+
assert_false(qLess.matches, "Target width is 200px, so < 100px should not match.");
32+
let qGreater = target.matchContainer("(width > 100px)");
33+
assert_true(qGreater.matches, "Target width is 200px, so > 100px should match.");
34+
}, "Element.matchContainer correctly matches the size of its container query.");
35+
36+
test(() => {
37+
let container = createTestElement(`
38+
<div class="size-container" style="width: 200px">
39+
<div id="target"></div>
40+
</div>
41+
`);
42+
let target = container.querySelector("#target");
43+
let invalidContainerQuery = target.matchContainer("(invalid-feature)");
44+
assert_false(invalidContainerQuery.matches,
45+
"matchContainer with invalid query should not match.");
46+
}, "Element.matchContainer handles an invalid query.");
47+
test(() => {
48+
let container = createTestElement(`
49+
<div class="size-container" style="width: 200px">
50+
<div id="target"></div>
51+
</div>
52+
`);
53+
let target = container.querySelector("#target");
54+
let syntaxError = target.matchContainer("???");
55+
assert_false(syntaxError.matches,
56+
"matchContainer with syntax error should not match.");
57+
let emptyQuery = target.matchContainer("");
58+
assert_false(emptyQuery.matches,
59+
"matchContainer with empty string should not match.");
60+
}, "Element.matchContainer handles syntax errors and empty queries.");
61+
62+
test(() => {
63+
let container = createTestElement(`
64+
<div class="size-container" style="width: 200px">
65+
<div id="target"></div>
66+
</div>
67+
`);
68+
let target = container.querySelector("#target");
69+
let q = target.matchContainer("(width > 100px)");
70+
assert_true(q.matches, "Initially matches at 200px.");
71+
container.style.width = "50px";
72+
assert_false(q.matches, "Should flip to false after shrinking below 100px.");
73+
container.style.width = "300px";
74+
assert_true(q.matches, "Should flip back to true after growing above 100px.");
75+
}, "Element.matchContainer .matches reflects container size changes dynamically.");
76+
77+
test(() => {
78+
let container = createTestElement(`
79+
<div class="size-container" id="displaycase" style="width: 200px">
80+
<div id="target"></div>
81+
</div>
82+
`);
83+
let target = container.querySelector("#target");
84+
let q = target.matchContainer("(width > 100px)");
85+
assert_true(q.matches, "Initially matches.");
86+
target.style.display = "none";
87+
assert_true(q.matches,
88+
"display:none target still resolves to its container; matches the " +
89+
"container's preserved width. (Mirrors @container rule semantics, " +
90+
"which evaluate for display:none descendants — required for the " +
91+
"@container { display: none } toggle pattern to work.)");
92+
target.style.display = "block";
93+
assert_true(q.matches, "Still matches after re-display.");
94+
}, "Element.matchContainer .matches still evaluates when target is display:none.");
95+
96+
test(() => {
97+
let container = createTestElement(`
98+
<div class="size-container" style="width: 200px">
99+
<div id="target"></div>
100+
</div>
101+
`);
102+
let target = container.querySelector("#target");
103+
let q = target.matchContainer("(width > 100px)");
104+
assert_true(q.matches, "Initially matches while in tree.");
105+
target.remove();
106+
assert_false(q.matches,
107+
"Removed target has no container; should not match.");
108+
container.appendChild(target);
109+
assert_true(q.matches, "Re-inserted target should match again.");
110+
}, "Element.matchContainer .matches updates when the target is removed from and re-inserted into the dom tree.");
111+
112+
test(() => {
113+
let container = createTestElement(`
114+
<div class="style-container" style="--my-prop: foo">
115+
<div id="target"></div>
116+
</div>
117+
`);
118+
let target = container.querySelector("#target");
119+
assert_true(target.matchContainer("style(--my-prop: foo)").matches,
120+
"Style query for matching custom property should match.");
121+
assert_false(target.matchContainer("style(--my-prop: bar)").matches,
122+
"Style query for non-matching custom property should not match.");
123+
assert_false(target.matchContainer("style(--missing: foo)").matches,
124+
"Style query for unset custom property should not match.");
125+
}, "Element.matchContainer matches style queries on a style container.");
126+
127+
test(() => {
128+
let container = createTestElement(`
129+
<div class="style-container" style="--my-prop: foo">
130+
<div id="target"></div>
131+
</div>
132+
`);
133+
let target = container.querySelector("#target");
134+
let q = target.matchContainer("style(--my-prop: foo)");
135+
assert_true(q.matches, "Initially matches.");
136+
container.style.setProperty("--my-prop", "bar");
137+
assert_false(q.matches, "Should flip to false after style change.");
138+
container.style.setProperty("--my-prop", "foo");
139+
assert_true(q.matches, "Should flip back to true after restoring value.");
140+
}, "Element.matchContainer .matches reflects custom property changes on the style container dynamically.");
141+
</script>

0 commit comments

Comments
 (0)