SVG Patterns — Build More Complex Patterns With Images, Attributes, And Nesting

Patterns for web design elements are usually created with images. While some patterns can be created using CSS alone, most involve images of some kind. Fortunately SVG makes it easy to create simple and more complex patterns that can scale with your design and likely require fewer http requests.

Last week I began a look at the SVG <pattern> element. I walked you through an example and showed you how to create and work with simple patterns. We looked at pattern basics including some of the attributes of the <pattern> element.

Today I want to continue and talk about a few more pattern attributes, one of which will help us build up more complex patterns by referencing one pattern inside another. First a quick review to show you something I skipped last week.

Using an Image as the Pattern

In all of the examples last week I used SVG shapes to create the pattern. I did, however, mention that you could also use images to create the pattern. To show you how to use an image as an SVG pattern I created this one in Pixelmator.

It’s 50px wide, 50px high, and you can see it’s a couple of green squares that will form a checkerboard pattern. Here’s how we can use it as a pattern.

[code type=html]

<defs>
<pattern id="pattern-image" x="0" y="0" width="50" height="50" patternUnits="userSpaceOnUse">
<image xlink:href="images/pattern-50.png" x="0" y="0" width="50" height="50"></image>
</pattern>
</defs>

<rect x="2" y="2" width="600" height="200" stroke="#630" stroke-width="5" fill="url(#pattern-image)" />

[/code]

Here I used an <image> element and through its xlink:href attribute I referenced the image I created. The path to the image was the local path to the file while I was working on this post. I changed it to the path on the server and you’ll likewise have to adjust the path to wherever you store the image.

Here’s the resulting SVG, which you can see is the image repeated both horizontally and vertically to fill the rectangle.

Now let’s look at the different attributes you can add to the <pattern> element.

Attributes of the <pattern> Element

I covered about half of the <pattern> attributes last week, but there are more. First here are the five we’ve covered so far.

x — where the pattern starts in x-direction

y — where the pattern starts in y-direction

width — the x-distance to start the next occurrence of pattern

height — the y-distance to start the next occurrence of pattern

patternUnits — defines the coordinate system for the pattern and whether or not the pattern scales with the SVG object that references it.

Since I covered these in more depth last week, I’ll refer you to that post if you need more details about any of these attributes and continue with the ones I didn’t cover last week here.

Some of the remaining attributes may be familiar as we’ve seen them before when talking about other reusable SVG elements. First every pattern can have a viewBox as well the preserveAspectRatio attribute. The latter defaults to xMidyMid.

Both work the same as they do on other elements and I’ll direct you to more detailed posts about the viewBox and preserveAspectRatio if you want the details.

The <patternContentUnits> attribute

Similar to patternUnits is patternContentUnits and it takes the same two values, userSpaceOnUse and objectBoundingBox. The patternContentUnits attribute defines the coordinate system for the content of the pattern and not the pattern itself.

userSpaceOnUse — (default) doesn’t scale

objectBoundingBox — scales

Up until now patternContentUnits has always been equal to userSpaceOnUse as I haven’t set it otherwise. Here’s an example where I set patternContentUnits to objectBoundingBox instead.

[code type=html]

<defs>
<pattern id="pattern-2" x="0" y="0" width="0.25" height="0.25" patternContentUnits="objectBoundingBox">
<circle cx=".125" cy=".125" r="0.125" stroke="none" fill="#393" />
</pattern>
</defs>

<rect x="10" y="10" width="600" height="200" stroke="#630" stroke-width="5px" fill="url(#pattern-2)" />

[/code]

The code looks similar, but because the content scales, you need to reduce the coordinates and the radius of the circle below 1.0. Here I used 0.125, which means the width and height of the circle will be 0.25 units.

Setting both width and height of the pattern to the same 0.25 or 25% ensures that the pattern will repeat by placing the next circle adjacent to the previous one.

Here’s the result.

Notice that the circles are no longer circles, but elongated ovals instead. Because the circle, defined by a single radius, is allowed to scale inside a rectangle with different x and y dimensions, the circle will distort in one direction unless the x and y of the rectangle are the same.

The xlink:href and patternTransform attributes

Another attribute that should be familiar if you’ve been following along with this series is the xlink:href attribute. You can use it to reference other patterns in the SVG document.

You can also transform patterns with the patternTransform attribute. Let’s look at an example using both xlink:href and patternTransform.

Here I created two patterns. The first (id=“pattern”) is the same pattern of green circles we used last week and in the previous example here.

The second pattern (id=“pattern-transformed”) refers to the first pattern through it’s xlink:href attribute. It inherits everything defined on the first pattern. I added a 10 degree rotation to it through the patternTransform attribute as well.

[code type=html]

<defs>
<pattern id="pattern" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="10" cy="10" r="10" stroke="none" fill="#393" />
</pattern>
</defs>

<defs>
<pattern id="pattern-transformed" xlink:href="#pattern" patternTransform="rotate(10)">
</pattern>
</defs>

<rect x="10" y="10" width="600" height="200" stroke="#630" stroke-width="5px" fill="url(#pattern)" />

<rect x="10" y="250" width="600" height="200" stroke="#630" stroke-width="5px" fill="url(#pattern-transformed)" />

[/code]

Each pattern is referenced by a different rectangle and here’s the resulting SVG graphic showing both of them.

You can see that even though the graphic element was defined only for the first pattern, the second pattern inherited everything from it and added a transform. It’s a nice way to set up variations of the same pattern.

Nested Patterns

You can also nest patterns by referencing one inside another. Here I created two patterns, an inner pattern and and outer pattern. The inner pattern is a series of repeating green squares and the outer pattern is a series of repeating circles with a dark red stroke and the inner pattern as a fill.

[code type=html]

<defs>
<pattern id="pattern-inner" x="2" y="2" width="6" height="6" patternUnits="userSpaceOnUse">
<rect x="0" y="0" width="4" height="4" stroke="none" fill="#6a6" />
</pattern>

<pattern id="pattern-outer" x="13" y="13" width="50" height="50" patternUnits="userSpaceOnUse">
<circle cx="22" cy="22" r="20" stroke="#900" stroke-width="4px" fill="url(#inner-pattern)" />
</pattern>
</defs>

<rect x="10" y="10" width="600" height="200" stroke="#630" fill="url(#outer-pattern)" />

[/code]

Here’s the resulting SVG, which as you can see is a repeating pattern of circles (outer pattern) filled with a repeating pattern of squares (inner pattern).

Here’s the example again, this time without the stroke on the outer pattern. Hopefully this second example of nested patterns is giving you some ideas for creative ways to nest patterns.

Closing Thoughts

Patterns are another element you can add to your SVG toolbox for defining a graphic in one location and referencing and using it in another. If you’ve followed along with the other reusable elements in the series, patterns should be fairly easy to understand and use.

While they’re similar to other reusable SVG elements, patterns might be more fun to work with as you add them to elements and see the results. Perhaps that’s just me, though the ability to nest patterns can be used for some very creative results.

Next week I want to continue with another element that’s similar to a pattern and that you can add to the fill or stroke of graphic elements. I’ll talk about how to create and work with gradients in SVG.