Using SVG to Shrink Your PNGs
Wouldn’t it be great if you could get the compression of a JPEG with the transparency of a PNG? Well, you can, sort of. Here’s a little trick that I discovered while working on the new Sapporo Beer website.
Notice how the beer can on the Sapporo website has a transparent area around the edges (it’s hard to notice but there’s a video playing behind it). As a PNG, the beer can graphic would have been over 1.2 MB! So how did I get it down to 271KB?
First, I created two files. The first is a regular JPEG without any transparency. You can compress this one as much as you like. The second is an 8-bit PNG (alpha mask). This is just a grayscale image that represents the transparent areas of the beer can. Notice how the PNG is only 11KB; that’s because it contains so few colors and no transparency.
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>
Here I am loading the two images inside an SVG container. The alpha channel image is included as a mask which is then applied to the JPEG to create the transparent region. The result? A transparent image with JPEG compression!
Caveats
- 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. - No IE8 support
- Masks don’t work in older versions of Android
Discuss on Twitter • Edit on GitHub
Keep Reading
- Why Use a JavaScript Framework
13 Jul 2019 - Rendering Children in React
06 Feb 2019 - Hacking Image Interpolation for Fun and Profit
13 Jan 2019 - The Perils of Jest Snapshot Testing
07 Jan 2019 - A Better Way to Test Your React-Redux App
01 Jan 2019 - Firebase + Create React App
01 Aug 2018 - Partial Application in Action
29 Sep 2017 - Using SVG to Shrink Your PNGs
07 Sep 2014 - Adaptive Content
06 Feb 2013