DEV Community

Cover image for 〈load-file〉Web Component, add external content to the DOM
Danny Engelman
Danny Engelman

Posted on • Edited on

〈load-file〉Web Component, add external content to the DOM

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
  • Or replaces the <load-file> element itself with the replaceWith attribute

✔️ is not a replacement for 'HTML Imports'; <script> will not execute

✔️ is done in 7 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

   <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>
Enter fullscreen mode Exit fullscreen mode
  • 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>
Enter fullscreen mode Exit fullscreen mode

It doesn't matter when the Custom Element is loaded/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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

!! Note the CAPITAL in replaceWith (creates a better GZip compressed file)

Without replaceWith the source content will be injected in shadowDOM:

<load-file src="https://load-file.github.io/heart.svg"></load-file>
Enter fullscreen mode Exit fullscreen mode

All elements with attribute shadowRoot are moved to shadowDOM:

<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>
Enter fullscreen mode Exit fullscreen mode





Top comments (3)

Collapse
 
bytrangle profile image
Trang Le

Thanks for the list. I've learned two cool new ways to add external content to the DOM. However, I'm not convinced on using the object tag for loading an svg. Rarely does one use SVG on a web page without having to adjust the styling. But you can't selectively style the svg inside the external object tag. And if you have to change the styles inside the SVG itself, that makes the SVG file less versatile.
In the end, I used CSS mask with the mask-image property pointing to the SVG.
However, for embedding content that you don't intend to change, like a pdf, or video, the object tag is a great method.

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

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.

Collapse
 
dannyengelman profile image
Danny Engelman • Edited

Tnx,

I added object and a link to vecta.io/blog/best-way-to-embed-svg which describes all in detail

Also 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