Whilst we are waiting for HTML Modules to arrive in all Browsers (Chrome Platform Status)
The〈load-file〉Web Component
✔️ Fetches any external text file: ie. .txt
, .svg
, .html
✔️ Injects the content into the DOM
-
in shadowDOM
- respects lightDOM content for shadowDOM
<slot>
elements - with optional scoped CSS styling! ✨✨✨
- can move lightDOM content to shadowDOM
- respects lightDOM content for shadowDOM
Or replaces the
<load-file>
element itself with thereplaceWith
attribute
✔️ is not a replacement for 'HTML Imports'; <script>
will not execute
✔️ is done in 8 lines of code:
There are multiple ways to put an external SVG file on the page
source: https://vecta.io/blog/best-way-to-embed-svg
-
👉 as src :
<img src="file.svg">
- SVG content can not be styled with CSS
-
👉 as Object :
<object type = "image/svg+xml" data="file.svg"></object>
-
👉 as CSS background-image
background-image: url(file.svg)
-
👉 🎉 use the
<load-file>
Web Component 🎉- it provides scoped CSS styling
- Load the SVG
<load-file replaceWith src="//load-file.github.io/heart.svg"></load-file>
<load-file src="//load-file.github.io/heart.svg">
<style shadowRoot>
path:nth-child(2n+2) {
fill: GREEN; /* shadowDOM style does NOT style global DOM */
}
</style>
</load-file>
- display as bare SVG, by using the
replaceWith
attribute- (global) CSS styles all SVGs (see red heart puzzle pieces)
- OR, display contained in shadowDOM
- now (local) CSS styles one SVG (see green heart puzzle pieces)
Loading the <load-file> Web Component
Load the element from the Repo
<script src="https://load-file.github.io/element.js"></script>
It doesn't matter when the Custom Element is defined.
Any existing <load-file>
elements in the document will automagically upgrade when the Custom Element is defined later.
or define the entire element in the <head> of your HTML document with a <script> tag:
<script>
customElements.define("load-file",class extends HTMLElement{async connectedCallback(){
this.shadowRoot||this.attachShadow({mode:"open"});this.shadowRoot.innerHTML=await(
await fetch(this.getAttribute("src"))).text();this.shadowRoot.append(...this.children);
this.hasAttribute("replaceWith")&&this.replaceWith(...this.shadowRoot.children)}})
</script>
Using the <load-file> Web Component
Specify the full path in the src
attribute
add the replaceWith
attribute so the src content replaces the <load-file>
Element itself in the document
<load-file replaceWith src="https://load-file.github.io/heart.svg"></load-file>
!! Note the CAPITAL in replaceWith
`(creates a better GZip compressed file)
Without replaceWith
the source content will be injected in shadowDOM:
js
<load-file src="https://load-file.github.io/heart.svg"></load-file>
All elements with attribute shadowRoot
are moved to shadowDOM:
js
<load-file src="https://load-file.github.io/heart.svg">
<style shadowRoot>
path:nth-child(2n+2) {
fill: GREEN; /* shadowDOM style will NOT style global DOM */
}
</style>
</load-file>
Top comments (2)
Pretty cool, I like it :D
However, you forgot to mention SVG can be loaded with
<object>
, which allows some more of the CSS inside the SVG to do its magic, outside style rules still don't apply, but if I remember correctly, outside custom properties are available inside the SVG.Tnx,
I added
object
and a link to vecta.io/blog/best-way-to-embed-svg which describes all in detailAlso changed functionality slightly. Only the first
<style>
element will now be moved to shadowDOM. That way any<slot>
element in a loaded .html file will slot content from lightDOM correctly