Using SVG to Shrink Your PNGs

07 Sep 2014

Wouldn’t it be great if you could get the compression of a JPEG with the transparency of a PNG? You can, with a little layering trick I used while working on the new Sapporo Beer website.

Saporro Beer

Notice how the beer can has a transparent area around the edges (there’s a video playing behind it). As a single PNG, the can graphic weighed in at over 1.2 MB. The trick below brought it down to 271 KB without giving up transparency.

First, create two files. The first is a regular JPEG without any transparency; you can compress it aggressively. The second is a tiny 8-bit PNG (alpha mask) that represents the transparent areas. The PNG is only 11 KB because it contains so few colors and no blended transparency.

Files

Next, I created a little snippet of inline SVG:

<svg viewBox="0 0 560 1388">
  <defs>
    <mask id="canTopMask">
      <image
        width="560"
        height="1388"
        xlink:href="img/can-top-alpha.png"></image>
    </mask>
  </defs>
  <image
    mask="url(#canTopMask)"
    id="canTop"
    width="560"
    height="1388"
    xlink:href="can-top.jpg"></image>
</svg>

Load both images inside an inline SVG. The PNG is included as a mask and applied to the JPEG to carve out the transparent area. The result: full transparency with JPEG compression.

Caveats

  1. To work in most browsers the SVG must be inline. You can’t move it into an external file and load it with an <img> tag.
  2. No IE8 support
  3. Masks don’t work in older versions of Android

Discuss on TwitterEdit on GitHub


Keep Reading