Tips for Smaller Svg Sizes

January 05, 2019 ·  Thomas Yip
Software Development Director · Web Design · Everything SVG

You fire up your favourite editor and produce SVGs but found their sizes to be bigger than expected. Is there anything you can do to reduce SVG file sizes? Read on to find out how to reduce SVG sizes to a bare minimum.

We made the world's best SVG compressor with Nano, which minifies SVG files 22% smaller than the current industry average. Naturally, we recommend compressing SVG using Nano before embedding onto your web site. However, there are still many more tips you can apply, to ensure Nano generates the smallest SVG.

Updated (2019-01-15): Included avoiding base64 raster images using image tag

1. Avoid paths if possible

Consider the case of a simple ellipse with the same radius horizontally and vertically, which is essentially a circle:

<!-- Original : 47 characters -->
<ellipse cx="50.5" cy="50.5" rx="50" ry="50" />

<!-- Converted to path, compressed : 94 characters -->
<path d="M.5 50.5a50 50 0 0 1 50-50 50 50 0 0 1 50 50 
50 50 0 0 1-50 50 50 50 0 0 1-50-50z" />

<!-- Compressed by Nano: 37 characters -->
<circle cx="50.5" cy="50.5" r="50" />

When converted to paths, even after compression, Nano still requires 94 characters. On the other hand, Nano is smart to detect a circle from an ellipse and requires only 37 characters for the same SVG.

How about a rounded rectangle?

<!-- Converted to path, compressed : 150 characters -->
<path d="M 0 10 C 0 4.46 4.46 0 10 0 L 140 0 C 145.54 0 150 4.46 150 10 
L 150 90 C 150 95.54 145.54 100 140 100 L 10 100 C 4.46 100 0 95.54 0 90 Z" />

<!-- Compressed by Nano: 53 characters -->
<rect x="0" y="0" width="150" height="100" rx="10" />

Not using paths requires only 53 characters, as compared to 150 characters for paths.

Automatic conversion to paths with Nano

If you have a normal rectangle:

<!-- Original: 45 characters -->
<rect x="0" y="0" width="150" height="100" />

<!-- Automatic conversion to paths by Nano: 30 characters -->
<path d="M.5.5h150v100H.5z" />

Compressors like Nano will be able to understand your SVG better, and will automatically convert to paths if conversion to paths makes a smaller SVG.

2. Avoid premature merging of paths

Consider the case of this beautiful logo, for which the original file have merged paths:

OriginalNano (Merged Paths)Nano (No paths)
Size40.9 KB19.6 KB3.46 KB
Gzip5.49 KB2.92 KB851 B
Savings46.8%84.5%

Once paths are merged, it is extremely difficult for compressors to understand your complicated merged paths, resulting in less compression. If elements are not converted to paths and merged, compressors can dynamically choose the best compression, resulting in higher compression ratio at 84.5%.

At Nano, we will automatically merge paths, but only when they result in higher compression.

3. Arrange shapes with same formatting as siblings

Consider the following example, where we have 2 rectangles with the same formatting as siblings, followed by an ellipse, and then followed by 2 of the same rectangles as earlier, also as siblings.

Shapes with the same formatting as siblings in DOM
Shapes with the same formatting as siblings in DOM
<!-- Original: 480 characters -->
<svg width="600" height="120" fill="none">
    <rect x="10" y="10" width="100" height="100" stroke-width="3" stroke="#ff6666"/>
    <rect x="130" y="10" width="100" height="100" stroke-width="3" stroke="#ff6666"/>
    <ellipse cx="300" cy="60" rx="50" ry="50" stroke-width="3" stroke="#66b2ff"/>
    <rect x="370" y="10" width="100" height="100" stroke-width="3" stroke="#ff6666"/>
    <rect x="490" y="10" width="100" height="100" stroke-width="3" stroke="#ff6666"/>
</svg>

<!-- Normal Compression: 263 characters -->
<svg width="600" height="120" fill="none" stroke-width="3">
    <path d="M10 10h100v100H10zm120 0h100v100H130z" stroke="#f66"/>
    <circle cx="300" cy="60" r="50" stroke="#66b2ff"/>
    <path d="M370 10h100v100H370zm120 0h100v100H490z" stroke="#f66"/>
</svg>

<!-- Nano Compression: 243 characters -->
<svg width="600" height="120" fill="none" stroke-width="3">
    <path d="M10.5 10.5h100v100h-100zm120 0h100v100h-100zm240 
    0h100v100h-100zm120 0h100v100h-100z" stroke="#f66"/>
    <circle cx="300.5" cy="60.5" r="50" stroke="#66b2ff"/>
</svg>

What happens is that shapes with the same formatting can be grouped or merged and share their same styling, resulting in better compression.

At Nano, we automatically scan and arrange these shapes, but only on a rudimentary level, mainly because calculating if a shape overlaps another is computational intensive and may cause long processing times, but only yield a small improvement in compression.

How to arrange shapes as siblings

Select shapes with the same formatting, and then select Bring to front or Send to back.

4. Avoid complex gradients with transformations

Consider the example below where the left image uses a complex gradient fill, but the fill actually results in the same color for the entire shape, therefore we can use a simple fill for better compression.

Complex gradient fillSimple fill
Size747 B449 B
<!-- Original using complex gradient: 677 characters -->
<svg height="200" width="200">
    <linearGradient id="A" gradientUnits="userSpaceOnUse" x1="-572.42"
    x2="-553.096" y1="-391.288" y2="-381.081">
        <stop offset="0" stop-color="#ffc35a"/>
        <stop offset="1" stop-color="#faae2a"/>
    </linearGradient>
    <path d="M59.6 10.55v131.3a28.5 28.5 0 0 0-20.45-8.61c-15.87 0-28.64 
        12.77-28.64 28.63s12.77 28.63 28.64 28.63a28.5 28.5 0 0 0 28.55-27.81
        h.08V51.43h114.55v65.85c-5.2-5.3-12.4-8.6-20.46-8.6-15.86 0-28.63 12.77
        -28.63 28.63s12.77 28.63 28.63 28.63c15.87 0 28.64-12.77 28.64-28.63
        V10.5H67.77zm8.18 16.36h114.55v16.36H67.77z" fill="url(#A)" stroke="none"/>
</svg>

<!-- Using simple fill: 437 characters -->
<svg  width="200" height="200">
    <path d="M59.6 10.55v131.3a28.5 28.5 0 0 0-20.45-8.61c-15.87 0-28.64 
        12.77-28.64 28.63s12.77 28.63 28.64 28.63a28.5 28.5 0 0 0 28.55-27.81
        h.08V51.43h114.55v65.85c-5.2-5.3-12.4-8.6-20.46-8.6-15.86 0-28.63 12.77
        -28.63 28.63s12.77 28.63 28.63 28.63c15.87 0 28.64-12.77 28.64-28.63
        V10.5H67.77zm8.18 16.36h114.55v16.36H67.77z" fill="#f9ad2e" stroke="none"/>
</svg>

Compressors generally cannot calculate the resultant colors, and will leave color information intact. In all other SVG minifier that we have come across, none of them optimize gradients, except Nano.

Even though Nano does optimize and apply transformations to gradients, the resultant compression is not as good as using simple fill and gradients without transformations.

5. Avoid gradients with userSpaceOnUse attribute

Consider the image below where on the left, you have an image that uses gradients with userSpaceOnUse while on the right, you have (almost) the same image without userSpaceOnUse.

With userSpaceOnUseWithout userSpaceOnUse
Size20.2KB6.21KB
Savings69.3%

Using gradients with userSpaceOnUse attributes results in repeated gradients that perform almost the same, bloating the file size substantially, while with simple gradients, we can have 69.3% more compression savings.

6. Avoid mask and clip paths

Consider the circle below where on the left we have a rectangle with a gradient, but a circle clip path is applied, and therefore showing only a circle, while on the right, there is just a circle, without clip path.

With clip pathWithout clip path
Size490 B381 B
Savings22.2%
<!-- With clip path: 455 characters -->
<svg height="200" width="200" fill-rule="evenodd">
    <defs>
        <linearGradient id="A" x1="0%" y1="0%" x2="100%" y2="100%">
            <stop offset="0%" stop-color="#ff00e7"/>
            <stop offset="100%" stop-color="#016fff"/>
        </linearGradient>
        <clipPath id="B">
            <circle cx="95.5" cy="95.5" r="95"/>
        </clipPath>
    </defs>
    <path d="M0 0h200v200H0z" clip-path="url(#B)" fill="url(#A)"/>
</svg>

<!-- Without clip path: 346 characters -->
<svg height="200" width="200" fill-rule="evenodd">
    <defs>
        <linearGradient id="A" x1="0%" y1="0%" x2="100%" y2="100%">
            <stop offset="0%" stop-color="#ff00e7"/>
            <stop offset="100%" stop-color="#016fff"/>
        </linearGradient>
    </defs>
    <circle cx="95.5" cy="95.5" r="95" fill="url(#A)"/>
</svg>

Obviously, not using clip path can render substantive savings amounting to 22.4% in this case. While there are cases where you might need mask and clip paths, they are few and far in between, so if you can avoid them, your SVG will compress better.

SVG minifiers normally do not calculate these clip paths to remove them due to their complexity, therefore, you would have to decide if you need clip paths, and avoid them if possible.

How to avoid using clip paths

Use your editor's shape operations to fragment, union or join different shapes into the desired outcome.

Advanced shape operations in vecta.io
Advanced shape operations in vecta.io

Vecta.io is one of only two, cloud based diagramming editor to have these advanced shape operations, so do check us out.

6. Avoid base64 raster images with image tag

<image xlink:href="data:image/png;base64,data">

SVG permits the inclusion of raster images using the image tag. However, these raster based images will not be compressed as they are already compressed in their native format.

AUTHOR

Thomas Yip
Software Development Director

As the creator and founder of Electra Cloud, which is now known as Capital Electra X, he introduced the market to an innovative, disruptive, and fully cloud-native electrical CAD solution. The driving force behind Capital Electra X, he is committed to shaping the future of easy-to-use Electrical CAD software development. Find him on Linkedin.

Keep yourself updated with the latest development on SVG, Web development, CSS and Javascript.

vecta.io Early Access