How to Use SVG Patterns
SVG patterns are one of several paint options that we have for coloring the fills and strokes of shapes and text. While generally regarded as one of the more complex options, establishing a foundation and understanding the basic syntax can make more seemingly complex patterns much more obtainable.
SVG patterns provide for very unique design opportunities. We are essentially defining a canvas within a target shape or text, which is then repeated (or tiled) throughout, enabling more detailed design outside of solid color fills and strokes.
In this article we will discuss the basic syntax and attribute options for SVG patterns and then review some examples for further understanding.
Before we get started it’s important to note that this article assumes a basic knowledge of how inline SVG works. There are a lot of great resources out there on getting started with inline SVG in general, like this one at CSS Tricks, and this one on SitePoint.
Concerning the use of SVG shapes the W3C has a great guide to get you started.
Let’s take a look at the syntax of a basic SVG pattern and then walk through the specific attribute options.
<svg> <defs> <pattern id="basicPattern" x="10" y="10" width="40" height="40" patternUnits="userSpaceOnUse"> <circle cx="20" cy="20" r="20” fill= "#64bee3" /> </pattern> </defs> <rect x="10" y="10" width="200" height="200" stroke= "#333333" stroke-width="2" fill="url(#basicPattern)" /> </svg>
This code will render the following pattern within a rectangle:
<svg> contains a
<defs> element which allows us to create reusable definitions to be called on later. These definitions have no visual output until they are referenced using their unique ID within the
The rectangle is located within the
<svg>, but outside of the
<defs> element where we have defined our pattern. The pattern is then applied to the rectangle through the “fill” attribute:
While there are a great number of SVG specific attributes, this article will touch on those essential for generating and manipulating basic SVG patterns.
Perhaps the most significant and more challenging concepts to understand in regards to SVG patterns are the coordinates for which each pattern detail is mapped, so these attributes specifically will be addressed in the following descriptions.
Each pattern requires a unique ID in order to be reference via the
fill attributes of SVG shapes or text.
x,y, width, height
The x and y attributes within the
<pattern> element define how far into the shape the pattern will start. Width and height used within the
<pattern> element define the actual width and height of the allotted pattern space.
For example, the
<pattern> element referenced above contains the following values:
x="10" y="10" width="40" height="40”. The pattern will start 10px in from the start of the x axis, 10px in from the start of the y axis, and essentially create a “canvas” that is 40px wide, and 40px high.
Determining within what coordinate system these values are applied is determined by the values within the
patternUnits attribute defines the coordinates for which x, y, width, and height are referenced. The two options here are
Used in the context of patterns, a value of
userSpaceOnUse results in a pattern coordinate system that is determined by the coordinate system for the element referencing the
<pattern> (like the rectangle in the above example) “stroke” and/or “fill”.
A value of
objectBoundingBox establishes the mapping coordinate system of x, y, width, and height as the bounding box of the element to which the pattern is applied (the pattern target).
If left unspecified the default value is
patternContentUnits attribute values are the same as the values for
userSpaceOnUse, except the coordinate system is now being defined for the contents of the pattern.
patternUnits, if this value is left unspecified it defaults to “userSpaceOnUse”. This means that unless one or both of these attributes are specified, the shapes drawn within the
<pattern> are being drawn in a different coordinate system than the
<pattern> element itself is using.
An approach to making this less difficult would be to define
patternUnits=”userSpaceOnUse” within the
<pattern> element. By default
patternContentUnits will be set to
userSpaceOnUse, ensuring that they are both now working within the same coordinate space, which we will discuss further in the next section.
Also worth noting here is that this value will have no effect if you have already specified the viewBox attribute coordinates in the
A Closer Look at Pattern Units
Pattern units are both the most significant and most complex aspect of SVG patterns. As mentioned,
patternContentUnits have different values by default, making it important to set either one of them to coordinate with the other for a consistently positioned pattern area.
patternUnits=”userSpaceOnUse” will ensure it is working within the same coordinate system as
patternContentUnits and is the much more straightforward option. If we were to resize the target shape/text set within this coordinate system, the pattern will repeat to fill the additional space.
patternContentUnits=”objectBoundingBox” will also ensure consistent coordinate space. If we were to resize the target shape/text set within this coordinate system, the pattern will scale to fill the additional space without repeating. In order to ensure proper scaling values within this system must be set in percentages or decimal based numbers.
Working within an
objectBoundingBox system, however, can prove difficult. There seems to be a number of bugs when working within this space, and the idea of scaling in general is not really true to the concept of a repeating, tiled pattern.
For reference here is a look at the details for a basic pattern set within the
objectBoundingBox coordinate space:
<svg> <defs> <pattern id="boundingPattern" width=".50" height=".50" patternContentUnits="objectBoundingBox"> <circle cx=".250" cy=".250” r=".1" fill="#ec7677" /> </pattern> </defs> <rect x="2" y="2" width="200" height="200" stroke="#333333" stroke-width="2" fill="url(#boundingPattern)" /> </svg>
If we were to expand the
height of the target shape referencing the pattern, the circles will scale appropriately; there will always be only four circles within the rectangle.
A Note on Sizing
It can seem like there are a lot of
height values being specified within the SVG, the pattern, and the shapes involved in generating SVG patterns which can very quickly become overwhelming.
height within the
<pattern> element define how far the pattern should go before it begins repeating itself. These values essentially determine the canvas size of the pattern area.
height within the pattern shapes determine their size, but the size cannot exceed the
height set within the
<pattern> element; the excess of any shape set larger than the bounds set by
<pattern> will not render.
Now that we have a stronger understanding of SVG pattern attribute options, let’s take a more in-depth look at another example that further utilizes these values options:
<svg> <defs> <pattern id="secondPattern" x="2" y="2" width="20" height="20" patternUnits="userSpaceOnUse"> <rect x="5" y="5" width="10" height="10" fill= "#876fc1" /> </pattern> </defs> <rect x="2" y="2" width="200" height="200" stroke= "#333333" stroke-width="2" fill="url(#secondPattern)" /> </svg>
Our SVG shape is 200px by 200px, our pattern “canvas” is 20px by 20px, and the pattern shape itself is 10px by 10px. This allows for 10 pattern units (20px by 20px) to fit across the shape (200px by 200px).
Within each pattern unit there is a rectangle (10px by 10px) with an x and y value of 5px. This means that on the top and left sides of each rectangle there is a 5px padding from the sides of the
Both the SVG shape itself and the pattern start 2px in from the left and 2px in from the top, to ensure the shape’s border is not hidden out of view.
Altering x and y Values
If we set this pattern rectangle to the same size as the pattern “canvas” (20px by 20px) and set its x and y values to “0” the SVG shape would fill solid purple. Adding x and y values greater than “0” for the shape inside the pattern pushes the shape into the pattern along the appropriate axis, with any overflow simply not being visible.
Depending on the values used throughout, a greater x and y value on the rectangle within the pattern can make the rectangle appear as if it is getting smaller, even though the
height are the same. This is because the shape is moving beyond the bounds set within the
<pattern> element, and if you then expand the width and height within the
<pattern> it will reveal the parts of the shape that had been cut out of view.
The following pattern is identical to that on the rectangle above, except with different x and y values on the purple pattern shape:
It appears as if the pattern rectangles have gotten smaller, but we have just pushed it further down and over an additional 10px, moving a portion of it off the pattern canvas.
It is also possible to fill a pattern with another pattern.
<svg> <defs> <pattern id="yellowPattern" x="5" y="5" width="75" height="75" patternUnits="userSpaceOnUse"> <circle cx="22" cy="22" r="14" stroke="#f19450" stroke-width="2" fill="#f6bf35" /> </pattern> <pattern id="greenPattern" x="10" y="10" width="50" height="50" patternUnits="userSpaceOnUse"> <rect x="2" y="2" width="30" height="30" stroke="#5cbc8f" stroke-width="2" fill="url(#yellowPattern)" /> </pattern> </defs> <rect x="2" y="2" width="200" height="200" stroke="#333333" stroke-width="2" fill="url(#greenPattern)" /> </svg>
Paths as Patterns
Paths can be used within patterns as well.
<svg> <defs> <pattern id="pathPattern" x="4" y="4" width="25" height="25" patternUnits="userSpaceOnUse"> <path d="M 0 0 Q 5 20 10 10 T 20 20" stroke="#f0934e" fill="none" /> </pattern> </defs> <rect x="2" y="2" width="200" height="200" stroke= "#333333" stroke-width="2px" fill="url(#pathPattern)" /> </svg>
<text> with a pattern is very similar to filling a shape.
<svg width="600" height="400"> <defs> <pattern id="textPattern" x="7" y="7" width="10" height="10" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"> <rect x="5" y="5" width="5" height="5" fill= "#876fc1" /> </pattern> </defs> <text x="0" y="50%" font-size="200" fill="url(#textPattern)">Text</text> </svg>
Browser support for inline SVG is strong across modern desktop and mobile browsers, though no support present in Opera Mini.
In this article we reviewed the basic syntax for SVG patterns, reviewed the meaning for potential attributes for further customization, and then dove into some examples for further understanding.
Hopefully establishing a basic foundation of how these patterns work inspires you to test the limits of their capabilities with more complex shapes and paths.