The Think Blog

How to Prepare SVGs for the Web

Christine Martino Manager, UX Engineering April 9, 2020

In the course of building digital tools and handing off files between designers and developers, we’ve learned some simple but impactful ways to keep SVG files and the corresponding code as clean and lean as possible. Here’s some information about why this extra step is important, along with some step-by-step instructions (in the video below!) for cleaning up and preparing SVG files for use on your website.

A little symbol cleanup now pays huge dividends later

Taking a few minutes in your design workflow to clean up a symbol before handoff to a developer has a ton of benefits:

  • Less back-and-forth between designers and developers for icon rendering issues
  • Better cross-browser compatibility
  • Cleaner, more streamlined code output
  • Greater flexibility to dynamically customize the SVG in code (animation, color changes, resizing, etc.)
  • Better site performance and better overall user experience

What you see is what you get (in code)

Each layer (yes, even hidden layers), shape, and group in your vector drawing program is included in the exported SVG code. So, in order to create the cleanest resulting SVG code, we have to clean up the source—the SVG file in our drawing program—before export.

If this cleanup doesn’t happen, developers could inadvertently create a lot of code bloat. This might not sound like a big deal, but think about it for a second: if we’re creating a library of 100 SVG icons for use on an application, and several of those icons are repeated throughout a given web page, we’re essentially pasting that same code several times throughout the HTML page.

Note: The larger an HTML document is, the longer it will take to load. Cleaning out the cruft in your SVGs before handoff can dramatically improve a site’s performance!

This process is more of an art than a science

Every SVG is different, and some are much more complex than others, but the goal is largely the same: try to maintain the integrity of the visual as best you can, with as few objects remaining as possible. The more you practice, the better you’ll get at finding patterns—paths that can be combined, squashed, or even removed altogether.

In the video below, I take an exported image from Abstract, open it in Sketch, and remove as much as I can to get the fewest remaining objects possible with the same visual effect—ungrouping objects, combining objects into single paths, and even removing the background circle. We can do that with CSS instead, saving a bit more space and cutting the file size.

When it comes to production-ready SVGs and code, every little bit counts.

Let’s clean up an SVG!

 

Before

It took 40 lines of code to make the original icon above.

<?xml version="1.0" encoding="UTF-8"?>
<svg width="104px" height="104px" viewBox="0 0 104 104" version="1.1" 
  xmlns="http://www.w3.org/2000/svg" 
  xmlns:xlink="http://www.w3.org/1999/xlink">  <!-- Generator: sketchtool 62 (101010) - https://sketch.com -->
  <title>A47FCF76-72B5-47B1-B438-A9EC3CCAB0C0@1.00x</title>
  <desc>Created with sketchtool.</desc>
  <defs>
    <filter x="-28.8%" y="-28.8%" width="157.5%" height="157.5%" filterUnits="objectBoundingBox" id="filter-1">
      <feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
      <feGaussianBlur stdDeviation="6" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
      <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.45 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
      <feMerge>
        <feMergeNode in="shadowMatrixOuter1"></feMergeNode>
        <feMergeNode in="SourceGraphic"></feMergeNode>
      </feMerge>
    </filter>
  </defs>
  <g id="Lead-Gen-Services-Landing-Page" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
    <g id="Lead-Gen-Services-Landing-Page---Desktop---Floater" transform="translate(-1328.000000, -938.000000)">
      <g id="Chat-Bubble" transform="translate(1340.000000, 950.000000)">
        <g filter="url(#filter-1)">
          <g id="Group-3" fill="#0060C4">
            <g id="Group-27">
              <circle id="Oval" cx="40" cy="40" r="40"></circle>
            </g>
          </g>
          <g id="Group-2" transform="translate(19.469697, 19.525253)">
            <g id="Group-Copy">
              <path d="M20.629625,38.0153621 C30.4527432,38.0153621 38.4159539,30.1593485 38.4159539,20.4684645 C38.4159539,10.7775806 30.4527432,2.921567 20.629625,2.921567 C10.8065068,2.921567 2.84329606,10.7775806 2.84329606,20.4684645 C2.84329606,25.2065879 1.23163919,33.6396829 4.32549014,36.7968275 C7.55949264,40.0969909 15.6092829,38.0153621 20.629625,38.0153621 Z" id="Oval-Copy-10" fill="#FFFFFF"></path>
              <path d="M35.1839473,6.11006574 C28.2160747,-0.80889235 16.9637374,-2.05141961 8.77207236,3.40898082 C6.83111471,4.70278445 5.20573922,6.28518742 3.90733833,8.0659698 C-0.274063611,13.8008449 -1.06436844,21.5931393 1.91692477,28.4295569 C2.11432506,28.8332235 2.17909462,29.2876069 2.10219903,29.7293271 L0.0435961445,38.3403046 C-0.0981820342,39.0093651 0.110702569,39.7039064 0.599418923,40.1884154 C0.99795023,40.5787304 1.54081291,40.7914851 2.10219903,40.7773737 C2.47645644,40.7679662 5.55063674,40.1857774 11.3247399,39.0308075 C11.7725475,38.9776921 12.2958842,38.6095955 12.7245899,38.7464828 C21.9471308,41.6912747 32.7342099,38.0153621 36.4396951,32.4101032 C40.1451803,26.8048442 42.15182,13.0290238 35.1839473,6.11006574 Z M29.7698218,35.3345861 C25.353302,37.7428556 18.8574144,37.7543071 14.206784,35.8219999 C13.3926955,35.4803854 12.5181756,35.3009339 11.6335304,35.2939683 C11.2470886,35.296637 10.8615211,35.3305993 10.4807128,35.3955128 L4.71662469,36.1672514 L5.56065187,30.4604479 C5.79435472,29.2201295 5.64370084,27.9391163 5.12834526,26.7845353 C3.16967127,22.1965095 3.78062689,16.9555241 6.22175781,12.5984575 C8.66288873,8.24139091 12.9940901,5.22891956 17.9740272,4.42442628 C23.2082131,3.576967 28.5357486,4.78105166 32.28639,8.48120369 C36.0370314,12.1813557 38.0398152,17.9855149 37.1807921,23.1492406 C36.3217691,28.3129662 34.1863415,32.9263165 29.7698218,35.3345861 Z" id="Shape-Copy-3" fill="#163045" fill-rule="nonzero"></path>
            </g>
            <path d="M13.6474031,14.3888635 L29.0192268,14.6348127 C29.6568223,14.6450142 30.1683502,15.164792 30.1683502,15.8024691 C30.1683502,16.4369023 29.6547466,16.9515848 29.0203149,16.952932 C26.7693761,16.9576556 24.6545378,16.9764126 22.6758001,17.0092031 C20.6077132,17.0434743 17.5980547,17.1084043 13.6468245,17.2039933 C12.8727917,17.2227042 12.2301345,16.6104071 12.2114089,15.8363747 C12.2111356,15.8250749 12.2109989,15.8137722 12.2109989,15.8024691 C12.2109989,15.0216564 12.8439727,14.3886826 13.6247854,14.3886826 C13.632325,14.3886826 13.6398645,14.3887429 13.6474031,14.3888635 Z" id="Rectangle" fill="#163045"></path>
            <path d="M13.647587,20.1122334 L22.9820671,20.1122334 C23.9420059,20.1122334 24.8130448,20.6742137 25.2087008,21.5488215 C25.4402712,22.0607141 25.2130252,22.6634099 24.7011327,22.8949804 C24.5693831,22.9545814 24.426441,22.9854097 24.2818373,22.9854097 L13.647587,22.9854097 C12.8541813,22.9854097 12.2109989,22.3422273 12.2109989,21.5488215 C12.2109989,20.7554158 12.8541813,20.1122334 13.647587,20.1122334 Z" id="Rectangle-Copy" fill="#163045"></path>
            <path d="M13.2109989,25.8585859 L27.5715651,25.8585859 C28.1298496,25.8585859 28.5824287,26.3111649 28.5824287,26.8694495 C28.5824287,26.9157487 28.5792478,26.9619932 28.5729086,27.0078563 C28.4810734,27.6722637 27.9248897,28.1744749 27.254587,28.1982469 L13.6466844,28.680846 C12.8813989,28.7079866 12.2390106,28.1096018 12.21187,27.3443163 C12.2112893,27.327942 12.2109989,27.3115586 12.2109989,27.295174 L12.2109989,26.8585859 C12.2109989,26.3063011 12.6587141,25.8585859 13.2109989,25.8585859 Z" id="Rectangle-Copy-2" fill="#163045"></path>
          </g>
        </g>
      </g>
    </g>
  </g>
</svg>

After

We cut the number of lines to more than half! But if you look closely at the code, there are still some nested group tags (<g>) for the same paths, created by the Artboard and Group layers in Sketch… a bit unnecessary. We can cut it down further with an SVG Optimization tool like SVGOMG to get rid of unnecessary metadata.

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;svg width="34px" height="35px" viewBox="0 0 34 35" version="1.1" 
  xmlns="http://www.w3.org/2000/svg" 
  xmlns:xlink="http://www.w3.org/1999/xlink"&gt;
  &lt;!-- Generator: Sketch 63.1 (92452) - https://sketch.com --&gt;
  &lt;title&gt;Chat Bubble&lt;/title&gt;
  &lt;desc&gt;Created with Sketch.&lt;/desc&gt;
  &lt;g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"&gt;
    &lt;g id="Chat-Bubble" transform="translate(0.305871, 0.352399)" fill-rule="nonzero"&gt;
      &lt;path d="M29.4665559,5.11718006 C23.6309625,-0.677447341 14.2071301,-1.71806393 7.3466106,2.85502143 C5.72105857,3.93858197 4.3598066,5.26384446 3.27239585,6.75524971 C-0.229528275,11.5582076 -0.891408567,18.0842541 1.60542449,23.8097539 C1.77074723,24.1478247 1.82499174,24.5283708 1.76059168,24.8983115 L0.0365117711,32.1100051 C-0.0822274537,32.6703433 0.0927134019,33.2520216 0.502013348,33.6577979 C0.835783317,33.9846867 1.29043081,34.1628688 1.76059168,34.1510505 C2.07403227,34.1431717 4.64865827,33.6555886 9.4844697,32.6883013 C9.85950853,32.6438171 10.297803,32.3355362 10.656844,32.4501794 C18.380722,34.9164425 27.4149008,31.8378657 30.5182446,27.1434614 C33.6215885,22.449057 35.3021493,10.9118075 29.4665559,5.11718006 Z" id="Outer-Bubble" fill="#163045"&gt;&lt;/path&gt;
      &lt;path d="M24.9322257,29.5927158 C21.2333904,31.6096416 15.7930845,31.6192322 11.8981816,30.0009249 C11.2163825,29.7148227 10.4839721,29.5645321 9.74308168,29.5586984 C9.4194367,29.5609335 9.09652394,29.5893769 8.77759693,29.643742 L3.95017317,30.290073 L4.65704594,25.5106251 C4.85277207,24.4718584 4.72659945,23.3990099 4.29498916,22.4320483 C2.65459969,18.5895767 3.16627502,14.2002515 5.21072217,10.5512082 C7.25516932,6.90216488 10.8825504,4.37922013 15.0532478,3.70545701 C19.4368785,2.99570986 23.8986894,4.00413077 27.0398516,7.10300809 C30.1810138,10.2018854 31.8583452,15.0628687 31.1389134,19.387489 C30.4194816,23.7121092 28.631061,27.5757901 24.9322257,29.5927158 Z" id="Inner-Bubble" fill="#FFFFFF"&gt;&lt;/path&gt;
      &lt;path d="M23.0911857,21.6565657 C23.5587491,21.6565657 23.937784,22.0356006 23.937784,22.5031639 C23.937784,22.5419395 23.9351201,22.5806693 23.9298109,22.6190797 C23.852899,23.1755208 23.3870951,23.5961227 22.8257166,23.6160318 L11.4290982,24.0202085 C10.7881715,24.0429388 10.2501714,23.5417915 10.2274411,22.9008649 L10.2267116,22.6565657 C10.2267116,22.1042809 10.6744268,21.6565657 11.2267116,21.6565657 L23.0911857,21.6565657 Z M19.2474812,16.8439955 C20.05143,16.8439955 20.780925,17.314654 21.1122869,18.047138 C21.3062271,18.4758481 21.1159086,18.9806058 20.6871986,19.1745461 C20.5768584,19.2244619 20.4571443,19.2502806 20.3360387,19.2502806 L11.4298541,19.2502806 C10.7653768,19.2502806 10.2267116,18.7116153 10.2267116,18.047138 C10.2267116,17.3826608 10.7653768,16.8439955 11.4298541,16.8439955 L19.2474812,16.8439955 Z M11.4297001,12.0506732 L24.3036024,12.2566556 C24.8375887,12.2651994 25.2659933,12.7005133 25.2659933,13.2345679 C25.2659933,13.7658923 24.835861,14.1969281 24.3045379,14.1980805 C22.4193676,14.2020364 20.6481825,14.2177455 18.9909826,14.2452076 C17.2589598,14.2739097 14.7383708,14.3282886 11.4292155,14.4083444 C10.7809631,14.4240148 10.2427376,13.9112159 10.227055,13.2629638 L10.2267116,13.2345679 L10.2267116,13.2345679 C10.2267116,12.5806372 10.7568271,12.0505217 11.4107578,12.0505217 L11.4297001,12.0506732 L11.4297001,12.0506732 Z" id="Talk-Lines" fill="#163045"&gt;&lt;/path&gt;
    &lt;/g&gt;
  &lt;/g&gt;
&lt;/svg&gt;

Voilà! Here we have a fully-optimized SVG that’s ready to be added into an icon sprite.

&lt;svg xmlns="http://www.w3.org/2000/svg" width="34" height="35"&gt;
  &lt;g fill="none" fill-rule="nonzero"&gt;
    &lt;path fill="#163045" d="M29.7724269 5.46957906C23.9368335-.32504834 14.5130011-1.36566493 7.6524816 3.20742043c-1.62555203 1.08356054-2.986804 2.40882303-4.07421475 3.90022828C.07634273 11.9106066-.58553757 18.4366531 1.91129549 24.1621529c.16532274.3380708.21956725.7186169.15516719 1.0885576l-1.7240799 7.2116936c-.11873923.5603382.05620162 1.1420165.46550157 1.5477928.33376997.3268888.78841746.5050709 1.25857833.4932526.31344059-.0078788 2.88806659-.4954619 7.72387802-1.4627492.37503883-.0444842.8133333-.3527651 1.1723743-.2381219 7.723878 2.4662631 16.7580568-.6123137 19.8614006-5.306718 3.1033439-4.6944044 4.7839047-16.2316539-1.0516887-22.02628134z"/&gt;
    &lt;path fill="#FFF" d="M25.2380967 29.9451148c-3.6988353 2.0169258-9.1391412 2.0265164-13.0340441.4082091-.6817991-.2861022-1.4142095-.4363928-2.15509992-.4422265-.32364498.0022351-.64655774.0306785-.96548475.0850436l-4.82742376.646331.70687277-4.7794479c.19572613-1.0387667.06955351-2.1116152-.36205678-3.0785768-1.64038947-3.8424716-1.12871414-8.2317968.91573301-11.8808401 2.04444715-3.64904332 5.67182823-6.17198807 9.84252563-6.84575119 4.3836307-.70974715 8.8454416.29867376 11.9866038 3.39755108 3.1411622 3.09887731 4.8184936 7.95986061 4.0990618 12.28448091-.7194318 4.3246202-2.5078524 8.1883011-6.2066877 10.2052268z"/&gt;
    &lt;path fill="#163045" d="M23.3970567 22.0089647c.4675634 0 .8465983.3790349.8465983.8465982a.84658774.84658774 0 01-.0079731.1159158c-.0769119.5564411-.5427158.977043-1.1040943.9969521l-11.3966184.4041767c-.6409267.0227303-1.1789268-.478417-1.2016571-1.1193436l-.0007295-.2442992c0-.5522848.4477152-1 1-1h11.8644741zm-3.8437045-4.8125702c.8039488 0 1.5334438.4706585 1.8648057 1.2031425.1939402.4287101.0036217.9334678-.4250883 1.1274081-.1103402.0499158-.2300543.0757345-.3511599.0757345h-8.9061846c-.6644773 0-1.2031425-.5386653-1.2031425-1.2031426 0-.6644772.5386652-1.2031425 1.2031425-1.2031425h7.8176271zm-7.8177811-4.7933223l12.8739023.2059824c.5339863.0085438.9623909.4438577.9623909.9779123 0 .5313244-.4301323.9623602-.9614554.9635126-1.8851703.0039559-3.6563554.019665-5.3135553.0471271-1.7320228.0287021-4.2526118.083081-7.5617671.1631368-.6482524.0156704-1.1864779-.4971285-1.2021605-1.1453806l-.0003434-.0283959c0-.6539307.5301155-1.1840462 1.1840462-1.1840462l.0189423.0001515z"/&gt;
  &lt;/g&gt;
&lt;/svg&gt;
Summary
How to Prepare SVGs for the Web
Article Name
How to Prepare SVGs for the Web
Description
We believe cleaning up SVG files during the design-to-developer handoff can be useful for website performance. Learn more about why, plus how to do it.
Author
Publisher Name
Think Company
Publisher Logo