Skip to content

Conversation

@break-stuff
Copy link
Contributor

@break-stuff break-stuff commented Jan 23, 2026

Using this in our component library, we ran into 2 issues:

  • This crashes in SSR environments (the popover polyfill works fine)
  • When loading this async or in a component instead of globally, nodes are not always properly hydrated, which results in crashes that affect component rendering.

This PR adds a few defensive checks to ensure that when CSS nodes aren't fully initialized during async imports or in unusual SSR scenarios, the polyfill won't crash but will gracefully handle undefined values.

Related Issue(s)

Reminder to add related issue(s), if available.

Steps to test/reproduce

We have the polyfill loaded as part of a usePopover hook that is used in a tooltip component. We are loading the polyfill using the following approach to keep it SSR-safe:

if (typeof window !== "undefined") { 
  import("@oddbird/popover-polyfill"); 
  import("@oddbird/css-anchor-positioning"); 
}

This results in console errors because node children cannot be found immediately due to the async nature of the import function and the load timing of the component.

Show me

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'map')
    at Cn (css-anchor-positioning.umd.cjs:7:1)
    at Object.<anonymous> (css-anchor-positioning.umd.cjs:17:1)
    at h (css-anchor-positioning.umd.cjs:1:1)
    at Object.Rule (css-anchor-positioning.umd.cjs:1:1)
    at h (css-anchor-positioning.umd.cjs:1:1)
    at K.m (css-anchor-positioning.umd.cjs:1:1)
    at K.reduce (css-anchor-positioning.umd.cjs:1:1)
    at Object.StyleSheet (css-anchor-positioning.umd.cjs:1:1)
    at h (css-anchor-positioning.umd.cjs:1:1)
    at u (css-anchor-positioning.umd.cjs:1:1)

@netlify
Copy link

netlify bot commented Jan 23, 2026

Deploy Preview for anchor-polyfill ready!

Name Link
🔨 Latest commit 4fc79bc
🔍 Latest deploy log https://app.netlify.com/projects/anchor-polyfill/deploys/69737ee06029820008121c7d
😎 Deploy Preview https://deploy-preview-374--anchor-polyfill.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link

netlify bot commented Jan 23, 2026

Deploy Preview for anchor-position-wpt canceled.

Name Link
🔨 Latest commit 4fc79bc
🔍 Latest deploy log https://app.netlify.com/projects/anchor-position-wpt/deploys/69737ee06029820008121c7f

@break-stuff break-stuff changed the title Update-for-ssr-environments Update for SSR environments and Async imports Jan 23, 2026
@jgerigmeyer jgerigmeyer requested a review from jamesnw January 23, 2026 17:16
Copy link
Contributor

@jamesnw jamesnw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for opening this PR! I'd like to figure out how to get this working in your setup.

As I look through this, I'm wondering if you've tried manually applying the polyfill? Something like this (note the import ends in /fn)-

import polyfill from '@oddbird/css-anchor-positioning/fn';

if (
  !("anchorName" in document.documentElement.style) &&
  typeof window !== 'undefined'
) {
  polyfill()
}

This gives you the control to add whatever logic you need to verify that your styles and DOM elements are ready to go before calling polyfill().

On the optional chaining, I'm wondering if you have a minimal reproduction of how to trigger errors in these places. This would be while walking the ASTs for CSS that is present when the polyfill is run, so these changes are suggesting that the AST is somehow malformed? If possible, it would be nice to catch those cases early and exit the polyfill immediately, rather than run the polyfill on empty or invalid ASTs.

Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is only used for running the Web Platform Tests, in which case we can be sure that window is available. I don't think we need to make any changes to this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added it for continuity so the tests and public API are consistent. I can remove it.

@break-stuff
Copy link
Contributor Author

It looks like that worked.

@jamesnw
Copy link
Contributor

jamesnw commented Jan 27, 2026

Glad to hear that! I'll close this PR, but if you have any tips or patterns that others would find useful, feel free to document them here! Thanks for looking into this!

@jamesnw jamesnw closed this Jan 27, 2026
@break-stuff
Copy link
Contributor Author

@jamesnw I think we still need to add the check at the very least. The popover polyfill also has it.

@jamesnw
Copy link
Contributor

jamesnw commented Feb 3, 2026

@jamesnw I think we still need to add the check at the very least. The popover polyfill also has it.

I think it makes sense to add an early return for this. I'm on the fence if it should be in index.ts (so that users of index-fn.ts have full control and responsibility over when the polyfill runs), or in polyfill.ts (to avoid running the polyfill when it is unlikely to succeed).

Either way, I'm curious to see if it will impact the tests.

Do you want to open a new PR with just that change, or reduce the scope of this PR? Either way is fine with me!

Thanks!

@break-stuff
Copy link
Contributor Author

I'll start with a small one just for that change. Really, if that works, then I don't really need to worry about the async part of it in my use cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants