Image masking with SVG

Abraham Jimenez
Zappos Engineering
Published in
4 min readOct 23, 2015

A few years back, I was reluctant to use SVG files because, with all new web technologies, no one really supported them. Also, there was very little documentation and very few tutorials. However, over the recent months I’ve been hearing more on how SVG has come a long way, even replacing static icons, image animations, and scalable logos. I have also noticed, while browsing website source code, more SVG coordinates than ever before. So I decided to give in and explore SVGs while looking into different solutions for scalable, responsive, and flexibly shaped image masking.

The obvious and seemingly easy choice of using static images would not have worked for use for a few reasons. First off, it would be a nightmare to update hundreds of images if the shape ever needed to change. Also, because many different people needed to create their own images, the shape would have varied resulting in a non-uniform experience. Another possible solution that I came across was http://bennettfeely.com/clippy/, which I think has tons of potential but still needs time before it is adopted by all browsers. With my first two options down, SVG started to look more and more appealing. That’s when I decided to dive in and see what SVG could do.

First, what does a simple SVG file look like:
I won’t get to much into what all the code means, but as reference, you can always look things up on https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute. First, I created my shape using illustrator and saved the file as an .svg file. The following code is what you see when you open the file using a code editor like sublime, brackets, etc. The image is just a hexagon with rounded corners. If you want to see how it works, just past the <svg> in the “html” portion in http://jsfiddle.net/

<svg xmlns=”http://www.w3.org/2000/svg" xmlns:xlink=”http://www.w3.org/1999/xlink" x=”0px” y=”0px” width=”100%” height=”100%” viewBox=”87.5 87.5 65 73" xml:space=”preserve”><path fill=”#000" d=”M122.6,159.883c-1.431,0.822–3.77,0.822–5.201,0l-27.298–15.701c-1.431–0.822–2.601–2.84–2.601–4.483v-31.397 c0–1.647,1.17–3.662,2.601–4.484l27.298–15.7c1.431–0.823,3.77–0.823,5.201,0l27.301,15.7c1.431,0.822,2.6,2.837,2.6,4.484v31.397 c0,1.644–1.169,3.661–2.6,4.483L122.6,159.883z”/>
</svg>
the code above should create the following shape

Adding an image into the shape:
How do we add the image inside the shape, or give it a background image without using css.

After the <svg> tag and before the <path> tag, we will add the following. This is the <defs> sections and it’s purpose is to allow our SVG to access specific features when you want to use them. In this case, it’s where we will be assigning the background images.

<defs><pattern id=”bias” height=”100%” width=”100%” patternContentUnits=”objectBoundingBox” viewBox=”0 0 1 1" preserveAspectRatio=”xMidYMid slice”>
<image height=”1" width=”1" xlink:href=”http://i.imgur.com/jH9b3cB.jpg" />
</pattern>
</defs>
the code above should create the following shape

The text highlighted with purple are two key parts to making this possible. The first part is the id name for your pattern, which will be assigned to the path on the following section. The second highlighted text is the link of your image to be used. This pattern, has an ID of “bias” so “#bias”. The original <path> has a fill of “#000”, which will be replace with “url(#bias)”. Basically assigning it the pattern you created with the Mr. T image.

The final code should look like this:

<div class=”hexagon”>
<svg xmlns=”http://www.w3.org/2000/svg" xmlns:xlink=”http://www.w3.org/1999/xlink" x=”0px” y=”0px” width=”100%” height=”100%” viewBox=”87.5 87.5 65 73" xml:space=”preserve”>
<defs>
<pattern id=”bias” height=”100%” width=”100%” patternContentUnits=”objectBoundingBox” viewBox=”0 0 1 1" preserveAspectRatio=”xMidYMid slice”>
<image height=”1" width=”1" xlink:href=”http://i.imgur.com/jH9b3cB.jpg" />
</pattern>
</defs>
<path fill=”url(#bias)” d=”M122.6,159.883c-1.431,0.822–3.77,0.822–5.201,0l-27.298–15.701c-1.431–0.822–2.601–2.84–2.601–4.483v-31.397 c0–1.647,1.17–3.662,2.601–4.484l27.298–15.7c1.431–0.823,3.77–0.823,5.201,0l27.301,15.7c1.431,0.822,2.6,2.837,2.6,4.484v31.397 c0,1.644–1.169,3.661–2.6,4.483L122.6,159.883z”/>
</div>
<div class=”hexagon”>
<svg xmlns=”http://www.w3.org/2000/svg" xmlns:xlink=”http://www.w3.org/1999/xlink" x=”0px” y=”0px” width=”100%” height=”100%” viewBox=”87.5 87.5 65 73" xml:space=”preserve”>
<defs>
<pattern id=”biasTwo” height=”100%” width=”100%” patternContentUnits=”objectBoundingBox” viewBox=”0 0 1 1" preserveAspectRatio=”xMidYMid slice”>
<image height=”1" width=”1" xlink:href=”http://i.imgur.com/PF5HDRB.jpg" />
</pattern>
</defs>
<path fill=”url(#biasTwo)” d=”M122.6,159.883c-1.431,0.822–3.77,0.822–5.201,0l-27.298–15.701c-1.431–0.822–2.601–2.84–2.601–4.483v-31.397 c0–1.647,1.17–3.662,2.601–4.484l27.298–15.7c1.431–0.823,3.77–0.823,5.201,0l27.301,15.7c1.431,0.822,2.6,2.837,2.6,4.484v31.397 c0,1.644–1.169,3.661–2.6,4.483L122.6,159.883z”/>
</div>
the code above should create the following shape

Benefits of going with SVG files:
Other than using SVG for masking, there is tons one can do with them, especially for resizing from web to mobile, creating cool vector animations and tons more. You’ll always have crisp vector logos and icons when using SVG. Now a days, I only use raster images now for photography. Forget about raster icons that never look great when downsized, or having multiple size versions because you are using them across your project. Now just resize SVG images via CSS and save yourself of having tons of changes and variations in your directories.

Other stuff that can improve this project:

Live example:
http://jsfiddle.net/jimenezdesign/d7mcdrev/3/

Making the image fit the shape:
http://stackoverflow.com/questions/22883994/crop-to-fit-an-svg-pattern

A cool way of making a honeycomb pattern: https://github.com/Tiotao/honeycombs.js/tree/master

--

--