Can I reduce the file size of an SVG to be closer to its JPEG equivalent?


I have an image that I’m using on a website. I would like to use an SVG so that it can be any size and still look crisp.

  • This dropbox contains the SVG file as well as the original Illustrator file.
  • This is a JPEG export:

    JPEG export

The SVG has a much larger file size than the JPG. Is it possible to optimise the SVG so that it has a similar file size? I might be able to lose some of the quality if that would help. I’ve tried this SVG optimiser, but it didn’t make much difference.

If I save the illustrator file as a JPG, trace the result and save it as an SVG, then I get a much smaller file size but some loss of quality. This makes me think that maybe the layers in the original are causing the large size? Is the image that I’m working with just too complex to be suitable for SVG?

4/8/2015 12:24:00 PM

Accepted Answer

Your SVG contains an embedded pixel graphic for the shade in the bottom right of the controller. This is responsible for about â…” of the file size. If you remove it, your SVG file is en par with your JPEG. You can probably achieve an adequately similar effect with a gradient.

Other techniques of reducing SVG file size include:

  • Remove all Metadata and similar. Inkscape has Save as plain SVG for this. I suppose that other programs have something similar.
  • Remove nodes that add little to the shapes, e.g., there are spurious nodes on your controller’s shape.

This makes me think that maybe the layers in the original are causing the large size?

Unless you are using absurdly many layers (think of one layer for each object), layers should not make a relevant contribution to the file size, and even then, it would only be a fraction.

Is the image that I’m working with just too complex to be suitable for SVG?

If you can reasonably create an image from scratch¹ it should not be too complex for the SVG format. There is no such thing as a magical complexity threshold beyond which file sizes explode (probably this holds for any vaguely reasonable format). Of course, if you only choose the resolution sufficiently coarse, you can export every SVG to a JPEG that has smaller file size. But that does not necessarily mean that you should not use SVGs.

¹ That is in particular without tracing and similar. To give an extreme example: If you want to exactly reproduce every pixel of a photograph with SVG primitives (i.e., without embedding a pixel graphics in SVG), you might indeed consider the result to be too complex for being efficiently represented in the SVG format. But that’s hopefully common sense.

4/8/2015 11:01:00 AM

As Wrzlprmft has already pointed out, over 50% of your SVG file's size is taken up by an embedded PNG bitmap image used to create a fairly subtle shading effect on the controller. Just getting rid of that image, and replacing it with a simple radial gradient, is enough to shrink the SVG down to about 10kb.

        Original         With simple radial gradient
Original image with fancy bitmap shading on left, edited version with simple radial gradient on right.

While you're at it, you should also check your paths to see if there's anything to simplify there. I didn't find much, but your controller's outline does have a few adjacent nodes (near the top and bottom middle) that can be merged without making any visible difference.

That's an easy 50% saving right there, but let's not stop yet. If you know even a little bit about the SVG format, you can do a lot better than that.

First, run "Vacuum Defs" in Inkscape to get rid of useless definitions, and then save the image as "plain SVG". Now, it's time to open it up in a text editor, and see what we can get rid of. Ideally, you should use an editor with an integrated SVG preview, so you can quickly see what effect (hopefully, none) your edits have on the appearance of the image. I use emacs for that, but there are other editors with similar features out there.

Anyway, with the SVG file opened in your text editor, let's start simplifying it!

  • Right at the top, there's a big useless <!-- comment -->. Just delete it.

  • If you're editing an SVG straight from Illustrator, there's also a useless <!DOCTYPE ... > line. Delete it too.

  • Inkscape insists on sticking a useless RDF metadata block into your image. Just locate the <metadata ...> tag and delete it, along with everything up to and including the closing </metadata>.

  • Also, even if you save the file as "plain SVG", Inkscape still litters it with a bunch of custom attributes. Find every attribute that begins with inkscape: or sodipodi: and delete them.

  • With the metadata and the Inkscape-specific attributes gone, you can remove all the unused XML namespace attributes from the <svg> tag. It should be safe to remove at least xmlns:rdf, xmlns:dc, xmlns:cc, xmlns:inkscape and xmlns:sodipodi. If there's a redundant xmlns:svg attribute, remove it, too. The only namespace attributes you should have left at this point are:

  • The <svg> tag also has a bunch of other useless attributes you can safely remove, such as enable-background and xml:space="preserve". (Those are inserted by the Illustrator SVG exporter, and Inkscape isn't smart enough to realize they're useless.) The viewBox attribute can also be safely removed from this image, since it just repeats the values of the x, y, width and height attributes.

  • You can also safely remove the encoding and standalone attributes from the <?xml ... ?> tag.

  • Now let's get to the guts of the image data. For some reason, Inkscape insists on assigning id attributes to every element, even if they're never referenced. Any id attribute whose value is never repeated elsewhere in the file (search for it!) is safe to remove. Basically, the only IDs you need to keep are those for the gradients, and possibly for any other objects (e.g. paths) found inside <defs> sections.

  • Also, Inkscape likes to generate long IDs like linearGradient4277. Consider abbreviating any IDs that you can't just delete into something short like lg1 instead.

  • There are also multiple <defs> sections right after one another. Merging them saves a few bytes (and simplifies the document structure in general).

  • There are also several empty groups (<g> elements) at the end of the file. Just get rid of them. There may also be multiple consecutive groups with the exact same transform attribute (or none at all); it's also safe to merge those.

  • For some weird reason, Inkscape saves a redundant Bezier path (d attribute) for <circle> elements. That takes up space for absolutely no reason, so just delete those. (Leave the d attributes on <path> elements be; those are actually used for something.)

  • Inkscape also likes to use CSS in style attributes where more specific attributes would be shorter, e.g. rewriting fill="#4888fa" to the more verbose style="fill:#4888fa". You can save a few bytes by breaking up those styles into individual attributes (and removing the ones that just uselessly repeat the default setting), but that take a bit more familiarity with the SVG format than most of the changes above.

  • Also, if there are any <use ... > elements, you may be able to save a few bytes by replacing them with the actual element they're linking to. (Of course, this only saves space if the linked elements are only used once.) It also seems that Inkscape likes to define circular gradients indirectly, first defining the stops in a <linearGradient>, and then referencing them in a <radialGradient>; you can simplify that by moving the stops directly inside the radial gradient, and getting rid of the now unused linear gradient. As a bonus, if, by doing this, you managed to get rid of all xlink:href attributes, you can delete the xmlns:xlink attribute from the <svg> tag.

  • If you really want to squeeze out every last extra byte, look for numerical values with way too many decimals, and round them to something more sensible. This is where the live preview really helps, since it lets you see how much you can round the value before it starts to be visible. Even if you don't want to carefully test every number to see how much it can be rounded, though, you can at least pick low-hanging fruit like, say, rounding a value of 1.0000859 pixels to just 1.

  • Finally, clean up the indentation and whitespace in the file. To absolutely minimize the byte count, you'd need to put everything on one line (or at least, only put line breaks in front of attributes, where whitespace is required anyway), but that's really hard to read. Still, it's possible to strike a decent balance between readability and compactness with some simple, conservative indentation.

Anyway, here's what I managed to hand-edit your SVG image into:

<?xml version="1.0"?>
  x="0" y="0" width="124" height="52">
<g transform="translate(1,-27.5)">
  <linearGradient id="lg1"
    x1="70.1063" y1="13.4122"
    x2="66.1994" y2="-26.4368"
    <stop offset="0" stop-color="#154BBF" />
    <stop offset="1" stop-color="#6E8BFF" />
  <path d="M 119.198,75.836 C 115.115,80.541 7.902,78.843 3.585,74.366 -0.734,69.888 -1.322,46.938 2.76,42.233 6.842,37.53 113.821,30.047 118.137,34.524 c 4.319,4.477 5.143,36.609 1.061,41.312 z" id="path3298" fill="url(#lg1)" />
  <linearGradient id="lg2"
    x1="70.4391" y1="13.5887"
    x2="70.4391" y2="-25.3265"
    <stop offset="0" stop-color="#4166FA" />
    <stop offset="1" stop-color="#87A4FF" />
  <path d="M 119.2,71.843 C 115.247,76.118 11.615,74.749 7.447,70.692 3.281,66.635 2.747,45.804 6.7,41.528 c 3.953,-4.277 107.372,-11.239 111.539,-7.183 4.167,4.057 4.915,33.222 0.961,37.498 z" id="path3305" fill="url(#lg2)" />
  <path stroke="#fff" stroke-width="5" d="m 103.734,64.225 0,0 c -0.921,-0.271 -1.661,-0.724 -2.2,-1.342 -0.917,-1.051 -0.957,-2.455 -0.88,-3.576 -1.831,-0.373 -3.866,-0.886 -7.099,-1.84 -3.233,-0.954 -5.221,-1.627 -6.961,-2.308 -0.544,0.983 -1.34,2.14 -2.679,2.525 -0.789,0.227 -1.656,0.204 -2.577,-0.068 -1.415,-0.417 -2.876,-1.431 -3.723,-2.583 -1.731,-2.354 -1.283,-6.55 -0.601,-9.655 0.964,-4.399 3.692,-11.662 7.252,-13.641 3.374,-1.877 12.426,0.468 16.37,1.6315 3.944,1.1635 12.873,4.1185 14.692,7.5355 1.914,3.596 0.262,11.176 -1.317,15.393 -1.113,2.978 -3.016,6.746 -5.746,7.782 -1.338,0.505 -3.117,0.564 -4.531,0.146 z" />
  <path fill="#4888fa" d="m 103.734,64.225 0,0 c -0.921,-0.271 -1.661,-0.724 -2.2,-1.342 -0.917,-1.051 -0.957,-2.455 -0.88,-3.576 -1.831,-0.373 -3.866,-0.886 -7.099,-1.84 -3.233,-0.954 -5.221,-1.627 -6.961,-2.308 -0.544,0.983 -1.34,2.14 -2.679,2.525 -0.789,0.227 -1.656,0.204 -2.577,-0.068 -1.415,-0.417 -2.876,-1.431 -3.723,-2.583 -1.731,-2.354 -1.283,-6.55 -0.601,-9.655 0.964,-4.399 3.692,-11.662 7.252,-13.641 3.374,-1.877 12.426,0.468 16.37,1.6315 3.944,1.1635 12.873,4.1185 14.692,7.5355 1.914,3.596 0.262,11.176 -1.317,15.393 -1.113,2.978 -3.016,6.746 -5.746,7.782 -1.338,0.505 -3.117,0.564 -4.531,0.146 z" />
  <path fill="#87b5ff" d="m 114.774,40.292 c -1.17,-2.151 -7.571,-4.939 -14.293,-6.921 V 33.37 c -0.023,-0.007 -0.047,-0.014 -0.07,-0.021 -0.023,-0.007 -0.047,-0.015 -0.071,-0.02 l 0,0 c -6.723,-1.985 -13.612,-3.12 -15.761,-1.949 -4.296,2.337 -9.198,17.315 -6.265,21.228 0.907,1.209 3.014,2.449 4.466,2.043 1.452,-0.404 2.121,-3.4 2.652,-3.174 2.518,1.077 5.601,2.117 8.744,3 3.119,0.966 6.272,1.765 8.972,2.229 0.569,0.097 -0.498,2.975 0.502,4.104 1.001,1.128 3.443,1.232 4.861,0.709 4.586,-1.693 8.602,-16.933 6.263,-21.227 z" />
  <path fill="#2f67c9" d="m 90.818,42.604 c -0.097,-0.194 -0.901,-0.575 -1.999,-1.006 0.317,-1.135 0.497,-2.007 0.401,-2.2 -0.319,-0.641 -3.681,-1.766 -4.323,-1.447 -0.192,0.096 -0.574,0.9 -1.004,1.998 -1.135,-0.315 -2.006,-0.497 -2.201,-0.401 -0.64,0.319 -1.766,3.681 -1.446,4.322 0.096,0.193 0.901,0.575 1.997,1.006 -0.316,1.134 -0.496,2.007 -0.4,2.199 0.32,0.64 3.682,1.767 4.323,1.447 0.193,-0.095 0.575,-0.901 1.005,-1.997 1.135,0.314 2.008,0.496 2.199,0.401 0.642,-0.32 1.767,-3.682 1.448,-4.322 z" />
  <path fill="#4888fa" d="m 100.282,33.311 c -0.024,-0.007 -0.046,-0.013 -0.069,-0.02 -0.023,-0.006 -0.046,-0.013 -0.07,-0.02 l 0,0 c -2.455,-0.725 -4.932,-1.334 -7.181,-1.755 -0.765,2.073 -1.164,4.497 -0.789,5.91 0.627,2.363 9.764,5.059 11.574,3.414 1.096,-0.996 2.091,-3.297 2.566,-5.483 -1.876,-0.731 -3.937,-1.428 -6.031,-2.046 l 0,0 z" />
  <circle fill="#639bff" r="3.427" cy="46.947" cx="101.382" />
  <circle fill="#4888fa" r="2.868" cy="45.940" cx="109.28" />
  <circle fill="#2f67c9" r="2.868" cy="52.538" cx="106.287" />
  <radialGradient id="rg3"
    cx="90.874" cy="39.29"
    fx="90.874" fy="39.29"
    <stop stop-color="#1166a8" stop-opacity="0" offset="0" />
    <stop stop-color="#1166a8" stop-opacity="0.02" offset="0.45" />
    <stop stop-color="#1166a8" stop-opacity="0.63" offset="1" />
  <path d="m 103.734,64.225 0,0 c -0.921,-0.271 -1.661,-0.724 -2.2,-1.342 -0.917,-1.051 -0.957,-2.455 -0.88,-3.576 -1.831,-0.373 -3.866,-0.886 -5.973,-1.508 -0.375,-0.11 -0.75,-0.223 -1.124,-0.338 -0.378,-0.107 -0.753,-0.216 -1.128,-0.326 -2.107,-0.622 -4.095,-1.295 -5.835,-1.976 -0.544,0.983 -1.34,2.14 -2.679,2.525 -0.789,0.227 -1.656,0.204 -2.577,-0.068 -1.415,-0.417 -2.876,-1.431 -3.723,-2.583 -1.731,-2.354 -1.283,-6.55 -0.601,-9.655 0.964,-4.399 3.692,-11.662 7.252,-13.641 3.374,-1.877 12.426,0.468 16.245,1.591 l 0.274,0.081 c 3.795,1.123 12.724,4.078 14.543,7.495 1.914,3.596 0.262,11.176 -1.317,15.393 -1.113,2.978 -3.016,6.746 -5.746,7.782 -1.338,0.505 -3.117,0.564 -4.531,0.146 z" fill="url(#rg3)" />

This SVG image looks all but indistinguishable from the second example image above, and only takes up 5189 bytes, considerably less than your JPEG image. I'm sure it could be optimized further yet, but this is really just an example of what you can do in a few minutes with practice. (It took me much longer to type up this answer than to actually edit the SVG code.)

Finally, compressing this SVG code with gzip shrinks it down to just 1846 bytes(!), just barely over a quarter of the size of your JPEG version.