I am creating a web component using native implementation, which in it\'s html template has links to images. However, those links only work if they are absolute, or relative
Reacting on my own prev comment to MarcG answer - the need for the modules to be aware of their own path has become acknowledged and nowadays may be retrieved by the import.meta.url
mean!
So it is much easier to write now some util to fetch component's HTML/CSS.
Furthermore, if CSS is NOT fetched, but a new style sheet link dynamically added to the document - this CSS plays very well with relative paths furthermore.
Having that, today, while waiting for some standard way to specify my component's base url, my ow approach is to provide a component with 2 resources:
fetch
API, turned into template, cached and then cloned into the component each time new instance of it attached to the DOMlink
elementThis behavior seems to be specific to images.
For script and link tags, relative paths from imported document work as expected.
Also I noticed that this is not something specific to polyfills, even for native implementation(chrome) this issue(?) seems to be there.
Seems like only option here is to include a script in your imported html, which will convert these relative paths to their absolute counterparts.
To solve it elegantly you can avoid hardcoding urls in your script and generate it using url of your importing document. You can get that from document.currentScript.ownerDocument
(or document._currentScript.ownerDocument
in polyfilled scenario).
So to answer your second question, I don't see any difference in native and polyfilled implementation at least in terms of behavior of src
and href
attributes.
Quote you mentioned from http://webcomponents.org/polyfills/html-imports/ seems to be specific to href/src of script and link tags and they work as written.
Hope it helps.
The webcomponent specification defines that URLs are always relative to the main document. This, of course, breaks web component encapsulation, as you rightly concluded. In other words, the specification is buggy, and lots of people are complaining about it. That's why the polyfill doesn't follow the specification: it's fixing the problem.
The specification will change. However, since this is not trivial to fix, it could still take some time. Please see these links:
• https://lists.w3.org/Archives/Public/public-webapps/2014OctDec/0013.html
• https://www.w3.org/Bugs/Public/show_bug.cgi?id=20976#c8
For the moment, the solution is for your component to change the URL of its template images, from relative to absolute. You can get the templateBaseUrl
as follows:
(function (window, document)
{
var proto = Object.create(HTMLElement.prototype);
var template = document.currentScript.ownerDocument.querySelector("template");
var templateBaseUrl = template.baseURI;
proto.createdCallback = function ()
{
// Now find all images inside the template and change their src attribute,
// using templateBaseUrl. Also you must change CSS background-image: url(...);
...
};
document.registerElement('test-element', {prototype: proto});
})(window, document);
Another way of fixing this, in case of small images like icons, is to embed the image data directly into the document, with data URIs. This also saves HTTP Requests (until we have Http/2). For example:
<img src="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7" />