Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
- This WPT test may be referenced by the following Test IDs:
- /css/css-shadow/hover-invalidates-slotted-descendant.html - WPT Dashboard Interop Dashboard
<!DOCTYPE html>
<meta charset="utf-8">
<title>:hover on a slotted ancestor invalidates a slotted descendant across the shadow scope boundary</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<style>
#host { display: block; }
/* Shadow content, not slotted. Hovered first so the common ancestor with the
slotted subtree is the host, which makes the subsequent hover chain stop
inside the shadow tree (its top is the <slot>). */
.icon { width: 100px; height: 30px; background: black; }
.option { width: 100px; height: 100px; }
.content { width: 100%; height: 100%; background-color: red; }
:is(.option):hover .content { background-color: green; }
</style>
<div id="host"><div class="option"><div class="content"></div></div></div>
<script>
const host = document.getElementById("host");
const shadow = host.attachShadow({ mode: "open" });
shadow.innerHTML = '<div class="icon"></div><slot></slot>';
promise_test(async () => {
const content = document.querySelector(".content");
const icon = shadow.querySelector(".icon");
assert_equals(getComputedStyle(content).backgroundColor, "rgb(255, 0, 0)",
"content is red before any hover");
// Hover shadow content first: now the common ancestor between the old hover
// target and the slotted content is the host, so the next hover chain stops at
// the <slot> (shadow scope) rather than walking up to <html>. The icon is not
// an .option, so this hover must not restyle the content.
await new test_driver.Actions().pointerMove(0, 0, { origin: icon }).send();
assert_equals(getComputedStyle(content).backgroundColor, "rgb(255, 0, 0)",
"content stays red while unrelated shadow content is hovered");
// Hover the slotted content; its ancestor .option gains :hover, which must
// restyle the (slotted, document-scope) .content.
await new test_driver.Actions().pointerMove(0, 0, { origin: content }).send();
assert_equals(getComputedStyle(content).backgroundColor, "rgb(0, 128, 0)",
"content turns green while its slotted ancestor is hovered");
}, "Ancestor :hover invalidates a descendant slotted into a shadow tree");
</script>