Convenient patterns

The <pattern> element lets you repeat a visual with concise syntax. With it, a graphic is laid in columns and rows, and while the result is often rigid, there are ways to break free of the grid-like structure. Some more elegant than others.

Tile

When it comes to designing a pattern, I like to start with an empty <svg> element.

<svg viewBox="0 0 1 1">
	<!-- ... -->
</svg>

In this manner you have a canvas — a squared canvas — where you are free to design your one tile.

As a sample, consider two shapes, a rectangle and a diamond right in the center.

<rect fill="hsl(0 0% 90%)" width="1" height="1" />
<path fill="hsl(0 0% 30%)" d="M 0.5 0.2 0.8 0.5 0.5 0.8 0.2 0.5Z" />

There’s nothing inherently complicated in the syntax. The <rect> element covers the canvas to add a background. The <path> element marks the rhombus point by point.

Diamond tile

Columns and rows

Drawing the tile directly in SVG has another benefit: you can use the same exact markup. Not in an <svg> element, mind you, but a <pattern> instead.

The viewBox remains valid as well, as the canvas for the tile itself.

-<svg viewBox="0 0 1 1">
+<pattern viewBox="0 0 1 1">

-</svg>
+</pattern>

Using the pattern is then a matter of tweaking a few attributes.

Immediately, a pattern means little on its own. Its usefulness is made evident in the fill or stroke attribute of other drawing elements. To create the connection, set a unique id on the pattern definition.

<pattern id="diamond-pattern" viewBox="0 0 1 1">
	<!-- ...rect & path -->
</pattern>

In the mentioned attributes, then, point to the construct with a specific formula.

<rect fill="url(#diamond-pattern)" width="100" height="100" />

There are just two more attributes standing between you and a complete set. Indeed, you need to decide how many times to repeat the graphic, and you do this with width and height.

<pattern width="0.2" height="0.2" viewBox="0 0 1 1">
	<!-- ...rect & path -->
</pattern>

By default, both attributes are relative to the benefiting shape. Setting the value to a decimal number means the tile occupies a fraction of the graphic, and grows in a fitting number of columns and rows.

Diamond pattern

It is possible to set the dimensions of the pattern irrespective of the size of the drawing with the patternUnits attribute. It is also possible to tailor the pattern when the shapes have a different aspect ratio. But both topics are beyond the scope of this article. Here focus on the result, and the fact that the pattern works, repeating the tile with very little effort, but in a perfect grid.

Checkboards

What if you wanted to lay the tiles in diagonals?

One way you have to create the sequence is directly through the tile. Past the single diamond you need to elaborate the tile so that, when positioned in the grid, the path seamlessly blends between the squares. To this end you can repeat the <path> with vertical and horizontal offsets.

To simplify the task you can even add an id to the element and rely on <use> elements, positioned on the four corners.

<path id="diamond" ... />

<use x="-0.5" y="-0.5" href="#diamond" />
<use x="0.5" y="-0.5" href="#diamond" />
<use x="0.5" y="0.5" href="#diamond" />
<use x="-0.5" y="0.5" href="#diamond" />

The viewBox acts as a hard-clip. Nothing drawn outside of the canvas will be visible. In this manner, copying the entire diamond creates the tile without excess.

Tile repeated with offsets

You can design the tile in this way, and may even picture how the squares, laid side by side or one above the other, lead to the more ornate pattern. But there is another way. A solution which relies on just the one diamond and a change in perspective.

Among the attributes available in the <pattern> element you find patternTransform. Similar to the transform attribute, the property lets you alter the graphic with different functions. translate, scale, and most pertinently, rotate.

<pattern id="diamond" patternTransform="rotate(45)" ...>
	<!-- ...rect & path -->
</pattern>

Rotate the pattern 45 degrees and you find a very different picture.

Rotated diamond pattern

Instead of diamonds, you have squares. But these squares are laid in the desired structure.

To understand the change, think of the pattern as wallpaper. When you rotate the element you tilt the sheet from the top left corner, so that the pattern is applied at an angle.

It is no wonder that you then see squares. The diamond is rotated as part of the larger scheme.

Rotated diamond — a square

The good news is that a pattern is like wallpaper, but even more customizable than wallpaper. You can update the sheet and modify the composing tile at the same time.

In other words, just like you can rotate the pattern, you can rotate the nested shapes.

<path transform="rotate(-45, 0.5 0.5)" ... />

Rotate the diamond with an opposite angle, from the center of the canvas, and the diamond is restored. You retain the arrangement, and you rediscover the shimmering shapes.

Diagonal diamond pattern

Personally, I find the solution incredibly neat. The attribute solves the issue with clear instructions. You don’t need to repeat shapes, not even in the <pattern> element, and you can tilt and rotate in a more express manner.

The change suits the diamond, but what if you were to rotate the rectangle as well?

<g transform="rotate(-45, 0.5 0.5)">
	<!-- ...rect & path -->
</g>

What happens if you rotate both shapes? Remember, the viewBox acts as a clip, hiding the bits falling outside of the area.

For the individual tile, the rectangle is rotated and doesn’t cover the entire surface. In the four corners, you appreciate evident gaps.

Rotated diamond with gaps

And for the pattern, you can almost appreciate how the change is going to look right side up.

Diagonal diamond pattern with gaps