How To Work With SVG Patterns

Patterns are useful design elements. They can provide contrast, create a sense of depth, and add interest to a composition. SVG makes it easy to create and use patterns that are limited only by your imagination.

For the last few weeks, I’ve continued the series on SVG I started at the beginning of the year. I left off last week promising to talk about an element you can define and reuse and if you read the previous paragraph, you should be able to guess what that element is.

I want to talk about the <pattern> element and how you can work with patterns in SVG. I’ll get through the basics of SVG patterns today and continue next week and show you how to build more complex patterns.

SVG Patterns

SVG patterns are used to fill or stroke SVG graphic objects. The graphic can either be an SVG or a bitmapped image and through the <pattern> element you tile the graphic at fixed x and y intervals to create a pattern from it.

You define a pattern inside a <pattern> element and you reference it through an id. If you read any of the last few posts in this series, referencing the pattern should be nothing new. Don’t worry if it is new to you. The examples throughout this post should make it clear.

A Simple Pattern Example

Let’s start with a simple example and build from there. Here I created a pattern from a repeating circle. Again, if you read any of the previous few posts in this series, most of this code should look familiar.

1
2
3
4
5
6
7
8
9
<svg width="660" height="220">
 <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>

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

The pattern is defined inside <defs> tags. The <pattern> element doesn’t display until referenced so you don’t need the <defs>, but they are typically used. The <pattern> gets an id of pattern, which is referenced by the rectangle. The <rect> element uses the pattern as a fill and takes a solid color as a stroke.

Inside the <pattern> element is green circle with a radius of 10 (px). The cx and cy values (10px each) set the center of the first circle at the origin of the circle element, or its top left corner.

That might sound strange. How can a circle have a top left corner or any corner for that matter? Remember that you see SVG graphics through a rectangular viewport so the circle displays inside a rectangular region that does have a top left corner.

Before talking about the rest of the code let’s see the resulting graphic. You can see it is a repeating pattern of green circles.

Now take a look at the attributes on the <pattern> element.

1
<pattern id="pattern" x="0: y="0" width="20" height="20" patternUnits="userSpaceOnUse">

The x and y attributes define where the pattern starts. Here I set both to 0 so there’s no offset before the pattern begins. Remember the circle is set so it’s center is at the origin. Setting x and y to 0 aligns the center of the circle with the start of the pattern.

The width and height attributes define the width and height of the pattern to be repeated. Here I set both to be the same size as the diameter of the circle so when the pattern repeats it’s one circle adjacent to the previous one.

Understanding the Attributes of the <pattern> Element

Let’s change some of these value one at a time to see what effect each change has. Here’s the resulting SVG when x and y are both changed to 10.

1
<pattern id=“pattern" x=“10" y=“10" width=“20" height=“20" patternUnits="userSpaceOnUse">

It might look the same at first glance, but focus your attention on the very first circle in the top left corner. Notice how it now starts at its edge instead of at it’s center. In other words, changing the x or y values on the <pattern> element shifts the entire pattern by the amount x and y change.

Let’s set x and y back to 0 and this time adjust the width and height of the pattern. Here’s the result when both width and height are set to 25 instead of the 20 used in the original example.

1
<pattern id=“pattern" x=“0" y=“0" width=“25" height=“25" patternUnits="userSpaceOnUse">

The pattern starts in the same place as the original example, the center of the first circle. Notice that there is now some space in between circles. That’s because the circle is 20px wide, but the pattern is now 25px in each direction, leaving 5px of empty space between circles.

In other words the width and height of the pattern determine where the next occurrence of the pattern is located and they allow you to include some additional whitespace in the pattern.

The final attribute I’ve included in the example is patternUnits, which defines the coordinate system for the pattern. It takes one of two possible values, userSpaceOnUse and objectBoundingBox.

  • userSpaceOnUse — x, y, width, and height represent values in the current user coordinate system. In other words the values don’t scale.
  • objectBoundingBox (default) — x, y, width, and height represent values in the coordinate system of the bounding box (the element that gets the pattern). In other words the values do scale and a value of 1 on the pattern will be scaled to equal the width or height of the element that takes the pattern.

If the definitions are confusing, don’t worry. Just remember that userSpaceOnUse doesn’t scale the pattern and objectBoundingBox does.

With the reusable SVG elements we’ve talked about to this point in the series, I suggested you want the reusable element to scale most of the time. With patterns that’s probably not as true and you’ll likely use userSpaceOnUse more often than not. Of course, it depends on the specifics of your project.

In all the examples so far in this post, I’ve used userSpaceOnUse. Here’s one with patternUnits is set to objectBoundingBox.

1
<pattern id=“pattern" x=“0" y=“0" width=“20" height=“20" patternUnits="objectBoundingBox">

What happened to the pattern? Because objectBoundingBox is the value of patternUnits, the values of 20 for width and height are scaled so they’re equal to 600px (width) or 200px (height) depending on whether the direction is x or y. The next occurrence of the pattern starts just outside the rectangle.

When working with objectBoundingBox, the width and height need to be less than 1.0 for the pattern to display beyond it’s first occurrence.

1
2
3
4
5
6
7
8
9
<svg width="660" height="220">
 <defs>
   <pattern id="pattern" x="0" y="0" width="0.0333" height="0.1" patternUnits="objectBoundingBox">
     <circle cx="10" cy="10" r="10" stroke="none" fill="#393" />
   </pattern>
 </defs>

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

Here’s the result.

You might be curious how I came up with the values of 0.0333 and 0.1 for x and y.

20 (circle height) ÷ 200 (rectangle height) = 0.1
20 (circle width) ÷ 600 (rectangle width) = 0.0333

I find userSpaceOnUse easier to work with and expect much of the time you’ll want the pattern to remain the same size, but sometimes you might want the pattern to scale and you’ll find objectBoundingBox useful.

Adding Patterns to Strokes

I mentioned you could add patterns to both fills and strokes, though I’ve only presented examples where a pattern is added as a fill. Let’s try one as a stroke so you can see how it works.

1
2
3
4
5
6
7
8
9
<svg width="660" height="220">
 <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>

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

The pattern is the same one we’ve seen throughout this post. It’s a copy of the very first example I presented, with a couple of changes to the rectangle.

Earlier I referenced the pattern on the rectangle’s fill. Here I added it to the stroke and used a solid color for the fill. I also bumped up the stroke-width to 20px so a single circle can fit inside its width.

Here’s the result.

The pattern now fills the stroke instead of the background of the element. One thing to note is that shifting the pattern only shifts it within the border. It doesn’t shift the entire border.

For example here’s what the SVG looks like when I change both x and y on the pattern element to 10.

1
<pattern id=“pattern" x=“10" y=“10" width=“20" height=“20" patternUnits="userSpaceOnUse">

With a little trial and error you can come up with some interesting patterns.

Let’s leave things here for today, though we’re not yet finished talking about patterns. I’ll pick things up again next week.

Closing Thoughts

Patterns can add a lot of interest to the elements in a composition and SVG makes them easy to create. You define patterns using simple shapes and lines and add them to SVG objects through the object’s fill or stroke attributes.

Today I covered the very basics of patterns, but there’s more. Next week I want to continue and talk about a few more attributes you can add to the <pattern> element. Then I’ll show you how you can nest one pattern inside another to create even more complex patterns.

Download a free sample from my book, Design Fundamentals.

14 comments

  1. There seems to be an issue with the inline demos. On initial load, the demos look fine, but after resizing the window or, on mobile, switching to the other device orientation, some of the demos get replaced by others.

    Also, in Firefox/Windows, most of the demos don’t render correctly at all.

  2. I think, I’ve found the culprit. You’re reusing the same “pattern” ID for all the demos on the page. Looks like the one-ID-per-page rule applies for elements inside inline SVG, too.

    • Thanks Šime. I completely missed that. The SVG worked for me. I didn’t test it everywhere, because I wasn’t expecting any problems. Then I introduced one.

      Nice catch.

      I changed things behind the scenes to pattern1, pattern2, etc. Do the demos work better now?

        • Thanks Šime. Weird about the objectBoundingBox example. I assume it doesn’t work in Firefox on Windows. It’s working for me in Firefox on the Mac. I assume you’re using a recent version of FF, if not the very latest.

          I wonder if the dimensions are just off a little and both circles are occurring outside the viewport. Maybe turning off the overflow: hidden would make them visible, assuming they are there and just outside the viewport.

          I’ll keep looking to see if there is a bug or maybe if it’s something I did, which is probably more likely.

          Thanks again for letting me know and checking the new code for me. Oh and I was wrong about how it looked in the email. I means in an RSS reader. The email I received had all the images in it the way they should look.

  3. “The cx and cy values (10px each) set the center of the first circle at the origin of the circle element, or its top left corner.”

    I’m unable to decipher this sentence. From what I see (in the demo), cx and cy translate the center of the circle to the right and down from its original position, which is the top left corner of the pattern.

    • Sorry again for the late reply. Would the sentence make more sense if it read

      The cx and cy values (10px each) set the center of the first circle as the origin of the circle element, or its top left corner.

      I only changed one work. Instead of circle at the origin it now reads circle as the origin.

      Does that make it more understandable?

  4. Sorry for spamming with comments, but there’s no option to edit existing comments which forces me to create new ones 🙂

    Anyway, I’m trying to wrap my head around the various x and y attributes used in the demo. From what I see, the PATTERN is actually aligned with the SVG element, not the RECT element on which it’s set. And since the RECT element is translated by 10px relative to its SVG container, the initial PATTERN is only partially visible (only its bottom right quadrant) which makes it seem as if the circle’s center is at the top left edge of the pattern. In reality, the circle’s center is in the center of the pattern and the circle fits the pattern perfectly. I’ve described my current understanding in this image: http://i.imgur.com/hhOXVKg.png.

    I think, removing x, y and the stroke from RECT would make these demos much easier to follow.

    • Don’t worry. You’re not spamming at all.

      The attribute can get confusing. I felt the same way looking at other examples and I tried to make things clearer, but I guess I didn’t do as well as I thought.

      What I found worked for me was to take any of these example, copy the code into your editor of choice, and load it in a browser. Then change one attribute at a time so you can see what it does.

      Until I did that, I had a hard time really understand what some of the attributes do.

    • Sime, your SVG patterns diagram you left in here in the comments http://i.imgur.com/hhOXVKg.png. just made this whole article much much clearer to me. Big thanks!!!! I wonder if you could do a similar diagram for Steven’s final example where he changes the x and y to 10px? Would be a great help if you could.

  5. Good article, I really think SVG is going to be a little revolution in the markup workflow. Tools for making SVG sprites have boomed.A lot of great resources here, many thanks for sharing. Again, bookmarked!

    • Thanks Alex. I’m with you. I think SVG is about ready to explode and I expect it’s going to be what adds back some of the aesthetics we’ve removed with flat design.

      I think the next revolution will be SVG and CSS/Javascript animation.

Leave a Reply

Your email address will not be published. Required fields are marked *