Customizable built-in elements on Safari – polyfill via script tag vs ES6 import
Asked Answered
T

1

6

I'm building a website with using only native, vanilla JS features (ES6, web components, import modules).

I'd like to include a polyfill to get Safari to support extending HTML elements (class MyLink extends HTMLAnchorElement). Ideally, I'd like to include it via an import in my main.js file, and not as a <script> tag in my index.html.

I first tried the official Custom Elements V1 polyfill, including it both via a script tag (<script src="https://unpkg.com/@webcomponents/custom-elements"></script>) as well as via import (import "https://cdn.skypack.dev/@webcomponents/custom-elements";). There are no errors either way, but I'm not seeing support for extending built-in elements on Safari.

I tried a different polyfill that explicitly mentions customizable built-in elements, and in this case, adding it via a script tag does make it work on Safari:

<script src="//unpkg.com/@ungap/custom-elements"></script>

But it still doesn't work if I import in in my js:

import ungapCustomElements from "https://cdn.skypack.dev/@ungap/custom-elements";

Am I using the wrong CDN? The wrong polyfill? What's the difference? Why does it work via a script tag but not as an ES6 import?

In case it's relevant, here's my declaration for the custom element I'm trying to get working:

class ButtonLink extends HTMLAnchorElement {
  connectedCallback() {
    console.log("This is not called on Safari");
  }
}

customElements.define("button-link", ButtonLink, { extends: "a" });
Talkie answered 10/5, 2021 at 7:44 Comment(5)
Even if you do get it to work, you are heading down a dead end. Apple has stated they will never implement Customized Built-In Elements. So you are stuck to a Polyfill... which (in years) to come.. won't get updated. There is no signal from Chromium/Mozilla it will delete Customized Built-In Elements; but don't expect much enhancements in the future.Quern
And "Customized Built-In" is a very lonely dead end street. All BaseClasses like Google-Lit, Stencil, SalesForce-LWC, extend from HTMLElement (Autonomous Elements)Quern
@Danny'365CSI'Engelman thanks for the heads up. That's such a shame and a huge loss for accessibility.Talkie
These comments made me laugh ... not only the fact the polyfill can be imported only in Safari means no other browser will be affected, but the standard is there to stay and the polyfill battle tested, so you better hope it won't ever change in the future, if it works. Regardless, somebody raised the same concern (direct script VS import) so I'll direct you there because there are other questions to answer first: github.com/ungap/custom-elements/issues/… ... for all others: just use custom elements built-in happily ever after and forget about ugly workaroundsArrant
Thanks for this @AndreaGiammarchi – in my case it turned out to be an import ordering issue as well (I was calling customElements.define() before importing the polyfill). I'll be sure to open an issue directly in the polyfill repository if I run into problems in the future!Talkie
T
4

This turned out to be an import ordering issue (thank you @AndreaGiammarchi for linking to the GitHub issue).

With the polyfill included via a script tag, my scripts and imports were ordered as follows:

<script src="//unpkg.com/@ungap/custom-elements/es.js"></script>
<script type="module" src="/components/ButtonLink.js"></script> <!-- <-- The component was defined here, along with the call to customElements.define() -->
<script type="module" src="/main.js"></script>

With the polyfill included via import, I was trying to get it to work with the import statement added to the top of main.js (which was loaded after ButtonLink.js and didn't have any effect).

Importing the polyfill at the top of my custom element script file fixed it.

Talkie answered 20/2, 2022 at 12:33 Comment(1)
if all your files are included as type=module you can use deferred in the polyfill script to avoid blocking the page and make lighthouse happier than ever 👍Arrant

© 2022 - 2024 — McMap. All rights reserved.