2

I'm trying to load an SVG file from a CDN using this code:

<object type="image/svg+xml" data="https://cdn.mywebsite.com/path/file.svg"></object>

The SVG file is in an S3 bucket served by CloudFront CDN. It's content-type is set to "image/svg+xml". To the best of my knowledge, my S3 bucket and CDN are configured to allow CORS requests from any origin.

If I look at the browser Network tab, the HTTP GET request succeeds and it receives the SVG data in response. However, the document data is not inserted into the DOM, so it doesn't display and cannot be accessed by JavaScript.

How can I embed the SVG document into my webpage so that it becomes an accessible part of the DOM?

Matthew Bowen
  • 469
  • 1
  • 4
  • 16
  • To access the paths etc inside the svg you need to insert the svg not just the file reference like you show (the stuff you see when you open an svg file in a text editor). – Chris W. May 03 '21 at 17:07
  • @ChrisW. The HTML code works when the website and files are held locally, but it doesn't work when my site is deployed to the server and loading files from CDN. – Matthew Bowen May 03 '21 at 17:21
  • You won't be able to get at the contents via javascript unless the hosting page containing the object tag and the cdn containing the svg file are on the same domain. – Robert Longson May 03 '21 at 17:45

2 Answers2

0

As Robert Longson kindly commented, embedding directly is impossible. But I did find a way.

I used this JavaScript (uses axios library):

var parser = new DOMParser();
let response = await axios.get('https://cdn.mywebsite.com/path/file.svg');
let svgDocument = parser.parseFromString(response.data, "image/svg+xml")

If CORS is configured correctly it allows the request, then you can parse the response body into a document. From there you can process the document or embed it.

Matthew Bowen
  • 469
  • 1
  • 4
  • 16
0

Provided you are allowed to read the SVG, this native Web Component <load-svg>

  • reads the SVG as text
  • adds SVG to shadowDOM as DOM element
  • moves the style element from lightDOM to shadowDOM
    So style is only applied to current SVG

<load-svg src="//graphviz.org/Gallery/directed/fsm.svg">
  <style>
    svg  { height:180px }
    text { stroke: green }
    path { stroke: red ; stroke-width:3 }
  </style>
</load-svg>

<script>
  customElements.define('load-svg', class extends HTMLElement {
    async connectedCallback() {
      let src = this.getAttribute("src");
      let svg = await (await fetch(src)).text();
      this.attachShadow({ mode: 'open' }).innerHTML = svg;
      this.shadowRoot.append(this.querySelector("style"));
    }
 });
</script>

More complex example: How to make an svg interactive to gather comments/annotations on depicted elements

Danny '365CSI' Engelman
  • 16,526
  • 2
  • 32
  • 49