Inline SVG vs SVG File Performance
Asked Answered
A

6

92

I'm currently building a website aimed at modern browsers and mobile devices. In terms of performance, is it better to inline SVG's directly inside the HTML using <svg> or is it better to use <img> and/or background-image instead. I run gzip on the server to further compress my content and prefer not to rely on Javascript.

Abohm answered 22/4, 2014 at 3:59 Comment(0)
R
68

Pros for inline:

  • Fewer http requests;
  • You can use css fill property and change the color;
  • Svg is part of the content, so it is clickable and you can insert text;

Pros for separate file:

  • Svg files can be cached;
  • You don't see multiple lines of irelevant code in your files;
  • If you need to change it later then you just change one file;
Ruben answered 5/8, 2016 at 9:59 Comment(14)
So if I only have to change the height of svg, I could just go with <img> sourced to svg file and just change height of the img, or am I doing it wrong?Birchard
Svg files can be cached; >> HTML can also be cached. You don't see multiple lines of irelevant code in your files; >> You could make a file seprate file give it a name like you would for the svg and use include for php to import it on the place you want it. If you need to change it later then you just change one file; >> See above.Choppy
@RoyvanWensen html changes more often than images so it is better to cache images separately. Also you have the same svg icons used in different html pages so you only need to cache it once.Ruben
Also, if you inline your SVG, it needs to be downloaded before the browser gets to subsequent content. Whereas if it's an external resource, the browser can download it in parallel and control priorities. This distinction doesn't matter as much with tiny SVGs.Musky
@Musky - Do you mean that similar to CSS or JS, inline SVG is a blocking resource?Combustible
@Combustible all inline content blocks the thing that comes after it, as the inlined thing needs to be downloaded in order to get to the content afterwardsMusky
@Musky - Sorry, I'm confused. My understanding is that any inline content is downloaded and interpreted as part of the browser reading and executing the DOM. If yes, why would an inline SVG be a blocking resource if it is base64 encoded?Combustible
@Combustible if I have a 30 byte reference to an external image, followed by 30 bytes of text, the browser has to download 60 bytes to display that text. If I have a 100k inlined image, followed by 30 bytes of text, the browser has to download over 100k to display that text. The inlined image is effectively blocking.Musky
@Musky - Righto. I am assuming that although an image may be larger in size if inline, the browser processes it faster versus establishing another connection, download the resource and parsing it.Combustible
@Combustible an external asset shouldn't need another connection if you're using HTTP/2 and the same host. But yes, with inline, you don't have the request/response overhead, but you do get the blocking behaviour.Musky
@Musky - Thanks. I imagine that even if it's the same host that there would be the overhead of a DNS request/response.Combustible
@Combustible you wouldn't need to go via DNS if it's same origin. The existing HTTP/2 connection would be used.Musky
@Musky - Thanks Jake. Can a connection to a server be primed so that when you make a request, it's in memory?Combustible
@Combustible yep, you're looking for <link rel="preload">Musky
T
56

There is no universal approach. It really depends on many things, but here some basic strategies which can be used separately or combined.

If we have:

  • Small number of SVG(s) with < 5k file size each–inline them in HTML. Compressed gzip/brotli each will be around 1k. Any small number multiplied by 1k is better than same number of additional requests, no matter cached or not.

  • Huge number of small SVG(s) < 5k - Make SVG sprite

  • Any number of big SVG(s) > 5k and let's say we do not need to access SVG properties via CSS or JS. Then <img src="name.svg">

  • Any number of SVG(s), but we do need to use CSS to change a SVG property or lets say animate some SVG property. The only viable option is inline svg.

  • If we need SVG(s) for backgrounds but they are < than 5k each:

    .bg { background: url('data:image/svg+xml;utf8,<svg ...> ... </svg>'); }

  • If we need SVG(s) for backgrounds but they are > than 5k each:

    .bg { background: url('images/file.svg'); }

  • I have never had a chance to try SVG sprite as background, but it is an option too

Trihedral answered 26/8, 2019 at 21:35 Comment(3)
About SVG in a .css file, i.e. ... background: url('data:image/svg ... — is the reason you recommended against this for > 5k SVGs, that then, if the CSS changes, all that > 5k SVG will get downloaded again together with the modified CSS? Or did you have in mind other reasons too? — Thanks for this detailed answer :- )Gastropod
Does 15 is a small number? Also "Any small number multiplied by 1k is better than same number of additional requests, no matter cached or not." does that mean 15 * 1k is better than one request with 15k? Thank you very much.Brimful
Unless you're in a almost-0 latency lab network, even one 100K request is much better than 10 10K requests. There are modules that exist for Apache Http proxy, and others, that essentially "inline" significant number of href'd resources on the origin server and then transmit the combined response to the user-agent. Unless you can rely upon such a network device, the strategy recommended above is a good one. Cheers!Selfimportant
C
27

Inline SVGs would reduce the number of HTTP requests, so it should make the page load faster the first time someone's visiting. But the drawback is that your SVGs won't be cached in the browser and therefore it will have to be loaded every time. I'd say if you're only using a few SVGs (like 10 or so), inline them; but if you have many, go with img+background-image.

You may also want to consider using SVG definitions and using the SVG use tag to reference SVG definitions. This method is pretty good; especially if you need to repeat an SVG multiple times in your page. More info on this technique: http://css-tricks.com/svg-sprites-use-better-icon-fonts/

My web app can also help you easily make these SVG definition & use pairs.

Corpse answered 27/12, 2014 at 11:56 Comment(0)
S
6

Claudiu Creanga, you are correct on most, but not on the last one :)

Concerning file SRC: "If you need to change it later then you just change one file;"

The file can be a separate SVG as Inline also. Just include the XML/text source via PHP for instance:

<?php include_once($_SERVER['DOCUMENT_ROOT'] . '/img/icon-home.svg'); ?>

I'm using this tactic since I do CSS3 animations on my icons. This way you have the original reference file for modifying in a vector program and simple upload will fix all inline code. Object and path ID's inside the SVG won't change if you just rearrange or manipulated them.

Sunrise answered 16/10, 2016 at 19:1 Comment(0)
P
0

Being able to cache SVGs is a big reason to include them as images. What I love doing is including them using CSS masks - this is for me the perfect cross between a true image and the ability to change the color of the icon like I would if it was inline SVG. This results in icons that are easily controlled through CSS classes, can be customized, and don't bloat the code at all.

Reference for this method: https://equinusocio.dev/blog/accessible-icon-buttons-with-masks-and-svg/

Pierides answered 15/5, 2021 at 19:54 Comment(0)
S
0

Concerning inline SVGs, most answers here are only concerned about the loading aspect of performance -- but that's easy to solve. Just write a little script that fetches the SVGs after DOMContentLoaded from URL references in <img> and inserts the SVG markup into your HTML:

const imgs = document.getElementsByClassName('svg-replace');
const parser = new DOMParser();
for (const img of imgs) {
    fetch(img.getAttribute('src'))
    .then(res => res.text())
    .then(str => {
        const svg = parser.parseFromString(str, 'image/svg+xml');
        img.replaceWith(svg.firstChild);
    })
}

This way, you even have a nice no-JS fallback. A more advanced technique for repeated use of inlined SVGs is creating a sprite sheet with <symbol>s that you include with <use> like in SVG Chameleon.

The more interesting question is how well this performs in the browser. You need less icon variations because you can easily change colors etc., but your DOM grows. This issue has been discussed in https://cloudfour.com/thinks/svg-icon-stress-test/.

Subvert answered 11/9, 2023 at 14:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.