Above code will only work when the Web Component is defined after DOM has parsed; using "defer" or "import" makes your JS file execute after DOM is parsed, you "fixed" the problem without understanding what happened.
I blogged about this long time ago: https://dev.to/dannyengelman/web-component-developers-do-not...
► execute <script> at bottom of file
► execute <script defer>
Both do the same; they execute script after DOM was parsed. When your JS creates GUI you now have to battle FOUCs.
► "import" loads your script async
so it _could_ load before _all_ DOM has parsed... but 9999 out of 10000 scenarios it won't
Simply render your <element> (server-side is fine) and whenever the JavaScript downloads and executes your custom elements will mount and do their thing.
I'm really just pushing back on the idea of using them for CSS formatting purposes of general text and layout instead of classes.
Custom elements solve exactly this problem. You can now do:
And then set up the listener: And the browser will ensure that it always sets up the listeners for all of the expanders, no matter whether they are loaded on the page initially or dynamically injected later. Without this you would have had to jump through a bunch of hoops to ensure it. This solves the problem elegantly.