Skip to main content

Implementing cross-browser SVG as either CSS background-images or defined symbols in HTML. Production ready implementation techniques.

- (update: )

Adding SVG to CSS or HTML

I recently experienced difficulties implement SVG into CSS in a cross-browser (IE 9 - Edge) manner. Outlined here are the two working solutions intended for use in production. I hope you find the learning useful too.

Both methods allow the CSS to define width, height etc. Method one is embedding raw SVGs directly into the CSS and the second using HTML embedded definition symbols.

I'll be using the Twitter logo as an example. The cleaned and compressed SVG code looks like this:

Language HTML
<svg viewBox="0 0 32 32" id="icon-social-twitter">
   <circle cx="16" cy="16" r="16" fill="#37A7DF"/>
   <path fill="#FFF" d="M24 11.8c-0.6 0.3-1.2 0.4-1.9 0.5 0.7-0.4 1.2-1.1 1.4-1.8-0.6 0.4-1.3 0.6-2.1 0.8-0.6-0.6-1.5-1-2.4-1-1.8 0-3.3 1.5-3.3 3.3 0 0.3 0 0.5 0.1 0.7-2.7-0.1-5.2-1.4-6.8-3.4-0.3 0.5-0.4 1.1-0.4 1.7 0 1.1 0.6 2.1 1.5 2.7-0.5 0-1-0.2-1.5-0.4v0c0 1.6 1.1 2.9 2.6 3.2-0.3 0.1-0.6 0.1-0.9 0.1-0.2 0-0.4 0-0.6-0.1 0.4 1.3 1.6 2.3 3.1 2.3-1.1 0.9-2.5 1.4-4.1 1.4-0.3 0-0.5 0-0.8 0 1.5 0.9 3.2 1.5 5 1.5 6.1 0 9.4-5 9.4-9.4 0-0.1 0-0.3 0-0.4C23 13 23.6 12.5 24 11.8"/>
</svg>

I'm not delving into cleaning an compression methods but if you want to compare against the original it may be found here: uncompressed Twitter logo.

That looks like this as a CSS background-image: and this as HTML SVG: which should appear identical in all browsers.

Raw SVG used as CSS background-image

With minor modification any raw SVG may be used in an external style sheet.

Works in all modern browsers, well those which support SVG, but Internet Explorer is quite awkward and requires:

  • Replace all double quotes with single quotes: " becomes '
  • URI encode the hash tag: # becomes %23
  • URI encode less-than symbol: < becomes %3C
  • URI encode greater-than symbol: > becomes %3E
  • Precede with the image type and declare the character set: data:image/svg+xml;charset=utf8,

I've created a tool to convert raw SVGs to CSS background-images maybe give it a spin and let me know if it works for you?

Language CSS
.icon-social-twitter {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg' id='icon-social-twitter'%3E%3Ccircle cx='16' cy='16' r='16' fill='%2337A7DF'/%3E%3Cpath fill='white' d='M24 11.8c-0.6 0.3-1.2 0.4-1.9 0.5 0.7-0.4 1.2-1.1 1.4-1.8-0.6 0.4-1.3 0.6-2.1 0.8-0.6-0.6-1.5-1-2.4-1-1.8 0-3.3 1.5-3.3 3.3 0 0.3 0 0.5 0.1 0.7-2.7-0.1-5.2-1.4-6.8-3.4-0.3 0.5-0.4 1.1-0.4 1.7 0 1.1 0.6 2.1 1.5 2.7-0.5 0-1-0.2-1.5-0.4v0c0 1.6 1.1 2.9 2.6 3.2-0.3 0.1-0.6 0.1-0.9 0.1-0.2 0-0.4 0-0.6-0.1 0.4 1.3 1.6 2.3 3.1 2.3-1.1 0.9-2.5 1.4-4.1 1.4-0.3 0-0.5 0-0.8 0 1.5 0.9 3.2 1.5 5 1.5 6.1 0 9.4-5 9.4-9.4 0-0.1 0-0.3 0-0.4C23 13 23.6 12.5 24 11.8'/%3E%3C/svg%3E");
  …
}

HTML inlined SVG solution

To prevent repeating inlined SVG data use a definition symbol at the page top:

Language HTML
<svg style="display:none">
 <defs>
    <symbol viewBox='0 0 32 32' id="icon-social-twitter">
       <circle cx='16' cy='16' r='16' fill='#37A7DF'/>
       <path fill='#FFF' d='M24 11.8c-0.6 0.3-1.2 0.4-1.9 0.5 0.7-0.4 1.2-1.1 1.4-1.8-0.6 0.4-1.3 0.6-2.1 0.8-0.6-0.6-1.5-1-2.4-1-1.8 0-3.3 1.5-3.3 3.3 0 0.3 0 0.5 0.1 0.7-2.7-0.1-5.2-1.4-6.8-3.4-0.3 0.5-0.4 1.1-0.4 1.7 0 1.1 0.6 2.1 1.5 2.7-0.5 0-1-0.2-1.5-0.4v0c0 1.6 1.1 2.9 2.6 3.2-0.3 0.1-0.6 0.1-0.9 0.1-0.2 0-0.4 0-0.6-0.1 0.4 1.3 1.6 2.3 3.1 2.3-1.1 0.9-2.5 1.4-4.1 1.4-0.3 0-0.5 0-0.8 0 1.5 0.9 3.2 1.5 5 1.5 6.1 0 9.4-5 9.4-9.4 0-0.1 0-0.3 0-0.4C23 13 23.6 12.5 24 11.8'/>
    </symbol>
    …
 </defs>
</svg>

Then re-use wherever required in the HTML:

Language HTML
<svg>
  <use xlink:href="#icon-social-twitter"></use>
</svg>

Currently trying to move symbol definitions into an external file. Which may prove to have its own issues and limitations (Internet Explorer bless). Though I believe, given a few years, externalised SVG definition files will overtake the use of SVGs in CSS background-images.

The current solution is svg4everybody which injects the definitions via an AJAX call into unsupporting browsers only. Not had time to investigate as yet but will keep this article updated.

Notes

HTML embedded SVG do not require xmlns='http://www.w3.org/2000/svg' as it's predefined when using the HTML 5 doctype.

Symbol definitions need to be placed before usage in a some browsers, so always place at the top.

Embedding SVGs into the CSS is the currently preferred method because: it remains editable, has a smaller footprint, offers better gzip compression, and is cacheable.

Always compress SVGs before running in production. Remove all the nasty Illustrator code, simplify the structure and reduce the decimal places used. I use SVG Optimiser which is a little basic but it meets requirement.

Began using SVGOMG a lot for compression, still buggy, but a far nicer GUI.

Personally I've started coding all SVGs using single quotes to ease any transition between HTML and CSS.

Socialise: