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? You can, with a little layering trick I used while working on the new Sapporo Beer website.

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.

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
- 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
- Structured output was my LLM aha moment
11 Jun 2024 - Why Use a JavaScript Framework
13 Jul 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 everywhere
06 Feb 2013