Build in pieces
In the context of scalable vector graphics, the <use> element helps to repeat drawing instructions with a concise syntax. And yet, it is also possible to repeat the element to solve a rather peculiar need.
Pieces
Say you’ve drawn a flower.
An <ellipse>, a handful of <path>s. There’s not much to the composition, but the code adds up to a few lines already.
The moment you want to repeat the flower for a comforting bed, you don’t need to copy-paste everything. Add an identifier to a parent group element.
<g id="flower">
<!-- ...flower -->
</g> Repeat the youngling with the <use> element.
<use href="#flower" x="10" />
<use href="#flower" x="-10" /> Once you offset the instances with the x attribute you find the stylish flower now on the right, now on the left. A veritable copy, without actually copying the underlying code. Quite convenient.
Puzzles
Say you add the flowers to a far more elaborate drawing. Well, I did, and to keep you intrigued, I won’t show you the result until the very, satisfying end.
<svg viewBox="0 0 60 60">
<!-- ...work of art -->
</svg> The entire graphic fits in a viewBox 60 units wide and tall; a perfectly squared canvas.
Say you now want to make a puzzle out of the complex markup. In this instance, you can swap the <svg> element for a <symbol>, add an identifier and relish in the possibility of using the <use> element once more.
<symbol id="painting" viewBox="0 0 60 60">
<!-- ...work of art -->
</symbol> Indeed, as you add the <symbol> element to the body of a brand new <svg>, you don’t see the painting immediately.
<svg viewBox="0 0 2 2">
<!-- symbol#painting -->
</svg> It is only as you refer to the symbol, through the now-infamous <use> element, that you find the drawing in the fresh canvas.
<svg viewBox="0 0 2 2">
<!-- symbol#painting -->
<use href="#painting" />
</svg> A word on said canvas: why 2 units wide and tall? Just a preference to work with small integers. The instructions in the <symbol> element are still relative to the symbol’s own canvas, but the visual is scaled to the new boundaries. And as an appetizer, let me offer an example with a secretive placeholder image.
You can very well repeat the painting, as many times as you want puzzle pieces.
<use href="#painting" />
<use href="#painting" />
<use href="#painting" />
<use href="#painting" /> But in this instance, you need to craft the pieces first. Starting with a single copy, you want to show only parts of the complete image.
<use href="#painting" /> In SVG, there are several ways to hide content, and the most immediate solution goes through the <clipPath> element.
<clipPath id="clip-piece">
<!-- ... -->
</clipPath> In the body of the clip you define the clip area, the visible area. For instance, a square 1 unit in measure.
<clipPath id="clip-piece">
<rect width="1" height="1" />
</clipPath> When you apply the clip to the image with the clip-path attribute.
<use clip-path="url(#clip-piece)" href="#painting" /> You no longer see the entire picture. Just a quarter.
Expand the concept to the remaining quadrants — add <clipPath> elements with the square in a different position.
<clipPath id="clip-piece-1-0">
<rect x="1" width="1" height="1" />
</clipPath>
<clipPath id="clip-piece-0-1">
<rect y="1" width="1" height="1" />
</clipPath>
<clipPath id="clip-piece-1-1">
<rect x="1" y="1" width="1" height="1" />
</clipPath> And finally, you have the recipe to craft the puzzle pieces. All four of them.
At this point you can repeat the use elements, and on each copy, apply a different clip.
<use clip-path="url(#clip-piece-0-0)" href="#painting" />
<use clip-path="url(#clip-piece-1-0)" href="#painting" />
<use clip-path="url(#clip-piece-0-1)" href="#painting" />
<use clip-path="url(#clip-piece-1-1)" href="#painting" /> And with that, the puzzle is complete.
If the result is anticlimactic, I share your sentiment. It may seem as little has changed, after all you find the same, promising placeholder. But there are indeed four pieces. You can inspect the page, or even notice a thin border separating the <use> elements.
What you need is to move the copies. What you need is to mess the pristine order which completes the set.
As you move the copies, you can have the first quarter end up in the lower right corner.
<use x="1" y="1" clip-path="url(#clip-piece-0-0)" href="#painting" /> You can move this last piece in the otherwise empty spot.
<use x="-1" y="-1" clip-path="url(#clip-piece-1-1)" href="#painting" /> And there you have it. An improper puzzle, just waiting to be put back into place.
Before I show you the highly anticipated work of art, expanded to consider a few more pieces and a touch of interaction, let me share a final update. One final excuse to repeat the <use> element.
While you can move the pieces to your heart’s content, you need to be careful not to push them outside of the visible area, outside of the viewBox. Remember the lower right corner?
<use x="-1" y="-1" clip-path="url(#clip-piece-1-1)" href="#painting" /> We shifted the piece with a negative offset and, while the result speaks for itself — it does work — I find the logic conceptually wrong. Wouldn’t it be nice to have actual puzzle pieces, pieces you position anywhere in manageable, positive increments?
In the specific example, wouldn’t it be nice to have the lower right corner in the opposite end without specifying an offset at all?
As editorialized, this is possible through the <use> element, once more.
Move the clipped element in the body of a <defs> block, so that you don’t see the element on the page.
<svg viewBox="0 0 2 2">
<defs>
<use clip-path="url(#clip-piece-1-1)" href="#painting" />
</defs>
</svg> And on this element, add a different, fittingid.
<defs>
<use id="piece-1-1" clip-path="url(#clip-piece-1-1)" href="#painting" />
</defs> And there you have it, a puzzle piece with a descriptive label. You can position the quarter at a fraction of the square canvas, resting sure that it will be visible in the predictable spot.
<use href="#piece-1-1" /> Personally, I find the change simplifies the task immensely. If you find the update way too technical, once again I understand your position. And as promised, I offer a last example to make it worth your day.