Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cross domain svg sprite

I'm aware that there are plenty of methods to use SVG sprites in HTML. My preference to this date has been to use something like

<div class="container">
   <svg class="icon">
     <title>Icon Title</title>
     <use xlink:href="/svg/sprite.svg#icon"/>
   </svg>
</div>

However, now I wanted to load the sprite from a subdomain, like this:

<div class="container">
   <svg class="icon">
     <title>Icon Title</title>
     <use xlink:href="https://sub.domain.com/svg/sprite-home.svg#icon"/>
   </svg>
</div>

Unfortunately, this doesn't work as the file is not fetched. I've tried with <object> as well, but that doesn't seem to work either.

So far, I'm only able to use

<?php include_once("https://sub.domain.com/svg/sprite.svg"); ?>

It's ok as a quick fix, as this doesn't involve much refactoring. However, this also means the HTML gets bloated.

With the <use> method the sprite gets cached. But with the include method the sprite isn't cached, only gets embedded, and so it is far from ideal.

Does anybody use any alternative to the php include method that is compatible with cross domain requests and browser caching?

like image 887
cortopy Avatar asked Sep 29 '15 17:09

cortopy


1 Answers

Thanks to this post at css-tricks I've been able to work out how to do this. The idea is to AJAX to bring the SVG sprite with jQuery like this (see post for vanilla version):

$j.get("https://sub.domain.com/svg/sprite-home.svg", function(data) {
  var div = document.createElement("div");
  div.className = 'no-display';
  div.innerHTML = new XMLSerializer().serializeToString(data.documentElement);
  document.body.insertBefore(div, document.body.childNodes[0]);
});

What this does is insert the SVG at the beginning of the document. Unlike the original post, I've added a class to make it hidden, as otherwise you get a blank big space at the top in Chrome. The result is great (it works with local files too) and now you can reference icons by just their id.

<div class="container">
   <svg class="icon">
     <title>Icon Title</title>
     <use xlink:href="#icon"/>
   </svg>
</div>

There are many advantages to this technique:

  • SVG sprite is cached
  • Really simple to use as you only reference the icon
  • You can request several SVG sprites and they all work the same

The only thing to bear in mind is that, this requires CORS AJAX to be set up. For those using nginx, it would be simple enough:

location ~* \.svg$ {
  ...
  add_header 'Access-Control-Allow-Methods' 'GET';
  add_header 'Access-Control-Allow-Origin' 'https://your.domain.com';
}
like image 103
cortopy Avatar answered Sep 22 '22 15:09

cortopy