37

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?

  • 16
    Not related to your question, but you shouldn't use JPG for images like this one. Instead, use PNG: the size is likely going to be similar and you won't get any loss of quality. – svick Apr 8 '15 at 17:59
  • Do realize that the comparison will depend on the physical size of the image. Scaling a JPEG increases the size a lot. Scaling a SVG has no effect. It's conceivable that a very small icon would be smaller as a JPEG, though I wouldn't call your graphic very small. – Paul Draper Apr 12 '15 at 23:06
  • If you're not an Inkscape user, and you don't feel confident about golfing an SVG by hand, you might like like the online tool I've linked to in my answer. – Dom Apr 13 '15 at 12:24
  • 1
    Just to add to svick's comment: images "like this one" where PNG is better is anything with transparent edges or anything with sharp solid areas of colour or white. If it's a 'graphic' (e.g. a logo, icon, etc) not a 'photo', PNG is usually better. JPG is better for photographs (or photo-realistic images). – user568458 Apr 13 '15 at 13:09
40

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.

81

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:

    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    
  • 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"?>
<svg
  xmlns="http://www.w3.org/2000/svg"
  version="1.1"
  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"
    gradientUnits="userSpaceOnUse"
    gradientTransform="matrix(0.9997,-0.0263,0.0263,0.9997,-7.4,61.3)">
    <stop offset="0" stop-color="#154BBF" />
    <stop offset="1" stop-color="#6E8BFF" />
  </linearGradient>
  <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"
    gradientUnits="userSpaceOnUse"
    gradientTransform="matrix(0.9997,-0.0263,0.0263,0.9997,-7.4,61.3)">
    <stop offset="0" stop-color="#4166FA" />
    <stop offset="1" stop-color="#87A4FF" />
  </linearGradient>
  <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"
    r="19.89"
    gradientUnits="userSpaceOnUse"
    gradientTransform="matrix(1.7028,-0.3387,0.276,1.3872,-70.22,16.58)">
    <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" />
  </radialGradient>
  <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)" />
</g></svg>

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.

  • 4
    Nicely golfed. – Wrzlprmft Apr 8 '15 at 16:36
  • 7
    get rid of line breaks and you'd save 50 more bytes :) – Yorik Apr 8 '15 at 18:05
  • 15
    I had to join this site just to upvote this awesome answer! Well done! – Karl-Johan Sjögren Apr 8 '15 at 20:57
  • Hey Ilmari, I wonder if you could check out the web app I've linked in an answer and confirm whether it does everything you'd do by hand? I ran it on a large SVG with amazing reductions, but when I also ran that SVG through another service beforehand, I was able to save an additional 2kb. When I inspect the SVG code, I still see some metadata with links to Adobe, and I have no idea if it's necessary. Your SVG wisdom is greatly appreciated. – Dom Apr 13 '15 at 12:34
30

I am a little surprised no-one has mentioned the "Scour" extension. It's bundled with Inkscape (as of v0.47), and does many of the optimisations mentioned by Ilmari Karonen.

  • 14
    +1 That's awesome! Honestly, I wasn't even aware that this tool existed. With the right options, the command-line version even beats my hand-optimized code by almost 200 bytes, and running it on the hand-optimized code gets it down to just 4571 bytes(!). – Ilmari Karonen Apr 9 '15 at 1:36
5

You can convert it to a compressed SVG (SVGZ) and put the image.svgz on your web page:

gzip image.svg
mv image.svg.gz image.svgz

Or, in Adobe Illustrator, simply save as "SVG compressed", which will write an image.svgz file.

For your test image it's still larger than the JPG, though:

image.jpg:   7268 bytes
image.svg:  22385 bytes
image.svgz: 14614 bytes
  • 6
    Compressed SVGs don't work in most, if not all, recent IE's sadly. The idea is helpful, but IE renders it much less viable. +1 anyway because it's not your fault IE $ucks. :) – Dom Apr 8 '15 at 12:21
  • 5
    @Dom, experience with IE and PNG suggests 3-5 decades not years. – Glenn Randers-Pehrson Apr 8 '15 at 14:32
  • 3
    Bashing IE never ceases to amuse me! :) It's pretty cool that we can attract someone of your level of experience to GDSE, I hope you like it here and if no-one has said it yet, welcome! – Dom Apr 8 '15 at 14:43
  • 2
    To test in IE, you can use the VMs from modern.ie/en-us – Scott Carlson Apr 8 '15 at 15:33
  • 4
    If you're serving it on a website, this will offer negligible benefit to clients requesting HTTP compression (which typically uses gzip anyway). – Bob Apr 8 '15 at 16:23
3

I've recently found a tool at https://petercollingridge.appspot.com/svg-editor (source code) that helps optimize SVG files. It has good results in this case, bringing the file size down to 3.7kB, which is just over half the size of the JPG, with a little manual adjustment:

Using this tool to optimize SVG files requires significantly less time than golfing the file manually.

  • Welcome to Graphic Design SE. Note that the asker mentioned this very tool in the question. Not that this invalidates this answer, but you can put it into perspective. Also, what do you mean by manual adjustment? – Wrzlprmft Apr 12 '15 at 16:57
  • This is not quite the same tool as mentioned in the question, but it is made by the same author and is located on the same domain. The author's link does have a link to this tool, but I didn't notice it until I posted my answer; I didn't delete it since it is still useful. By manual adjustment, I mean that I unchecked several boxes (combine paths, remove ids) to make the output correct and lowered the decimal places to further improve size. – user60561 Apr 12 '15 at 20:29
  • As with SVGOMG (from Dom's answer), here also the biggest savings seem to come from disabling xlink, which, as a side effect, completely deletes the embedded image. Obviously, replacing the image with a gradient isn't really something you can expect an automated tool to do. – Ilmari Karonen Apr 13 '15 at 13:23
3

SVGOMG! is an Awesome Web-App for SVG Optimisation

According to the creator of the app, SVGOMG is SVGO's "Missing GUI".

Running it on the image provided brings it down to just 3.42kb, and just 1.4kb after being gzipped.

SVGOMG screenshot

  • 1
    Looking at the rendered preview, it seems that most of the savings come from the fact that it completely deletes the embedded image. Obviously, replacing the bitmap with a gradient isn't something one can expect a software tool to do automatically. – Ilmari Karonen Apr 13 '15 at 13:15
  • 1
    I don't have the un-optimized version with just the gradient fixed any more, but if I manually edit the original SVG to replace the bitmap with the last <radialGradient> and <path> from my hand-optimized code, SVGOMG optimizes the resulting 5.8 kB image down to 4.02 kB (4.11 kB prettified), and seems to do a pretty thorough job; I don't really see any obvious missed opportunities. (Playing with it a bit more, I did notice that it sometimes fails to merge consecutive groups with identical attrs; Inkscape sometimes seems to generate those, e.g. when adjusting the page to fit the drawing.) – Ilmari Karonen Apr 13 '15 at 13:19
  • @IlmariKaronen thanks for having a look, running it on the original 22kb SVG in the Dropbox brings it down to 3.42kb on disk for me, any idea why mine is smaller? (I did enable every option). This app might be the best (easiest/quickest) option for most cases. I have no affiliation with the app, it's just awesome! – Dom Apr 13 '15 at 13:53
  • 1
    Look closely at the controller: if you select "Remove raster images" when optimizing the original SVG, the shading on the controller disappears completely (because it's actually an embedded semitransparent PNG). You can actually see it if you compare the screenshot in your answer to the original JPEG. The 4.02 kB version I got is bigger because it includes an extra path and gradient to replace the removed shading. – Ilmari Karonen Apr 13 '15 at 13:57
  • @IlmariKaronen I think I see the difference, it's so slight I'm not sure if my eyes are playing tricks. It's a good point, I've only worked with solid colours in SVG's thus far so I'll bear that in mind in future, thanks. – Dom Apr 13 '15 at 14:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.