fix: element removed from the DOM when directly under the shadow root#422
Conversation
✅ Deploy Preview for anchor-polyfill ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for anchor-position-wpt canceled.
|
jamesnw
left a comment
There was a problem hiding this comment.
This looks good! Thanks! Can you fix the tests?
I would like to, but |
There's a specific Node version (v24.11) that works for the pinned version of Playwright that supports polyfillabel browsers. I added a note to CONTRIBUTING.md about running |
Thanks, i fixed the test. And another bug related to shadow-root + position-area. |
jamesnw
left a comment
There was a problem hiding this comment.
LGTM- one idea you can take or leave. Good catch on the document.createElement bug- I'm wondering if you have looked at the other places that's used? That could be handled in a separate PR, though.
Co-authored-by: James Stuckey Weber <james@oddbird.net>
I haven't; i noticed this one because position-area inside the shadow root was broken. Let's look at it in a separate PR. |
Problem
When a
position-areatarget element sits directly inside a shadow root,wrapperForPositionedElementfailed to wrap it and instead removed it from the DOM entirely.The wrapping logic was:
A
ShadowRootis aNode, not anElement, sotargetEl.parentElementisnullwhen the target is a direct child of the shadow root. The optional chaining short-circuited theinsertBefore, but the followingwrapperEl.appendChild(targetEl)still ran — moving the target into a wrapper that was never inserted into the tree. The result: the target disappeared from the rendered DOM.Fix
Insert the wrapper relative to the target itself rather than going through its parent:
insertAdjacentElement('beforebegin', …)places the wrapper just before the target without referencing the parent node, so it works whether the parent is a regular element or a shadow root.Second fix:
position-areamapping styles not reaching shadow rootsEven once wrapped, the target wasn't positioned: the generated
position-areamapping stylesheet (which defines the--pa-value-*custom properties on the wrapper) was always appended todocument.head, and a<style>there doesn't apply inside a shadow root. So--pa-value-*stayed empty and the wrapper collapsed to its static position.transformCSSnow inserts these polyfill-created styles into each polyfilled root via a newgetRootStyleContainerhelper (shadow root → that shadow root; document →document.head). The wrapper now resolves its insets and alignment correctly inside a shadow root.Test page
Updated
shadow-dom.htmlto reproduce the scenario: the target/anchor now live directly under the shadow root (no intermediateposition: relativewrapper) and useposition-areasyntax, which exercises the wrapping code path. The adopted-stylesheets e2e test now asserts against the<polyfill-position-area>wrapper (right edges aligned, target top at anchor bottom).