The Many Ways to Draw Rectangles in SVG
Of the four rectangles below, one is special. They all look the same, but each is drawn in a different way. Here’s how you draw each one of them.
Warm-up: A Basic Rectangle
SVG comes with a rect
element you can use to draw a rectangle. Define its dimensions using the width
and height
attributes. Position it on the screen using the x
and y
attributes. And remember, you specify y
in terms of distance from the top of the canvas.
<svg xmlns="http://www.w3.org/2000/svg" height="100px" width="160px">
<rect x="0" y="0" height="100%" width="100%" fill="rgb(170,89,180)" />
</svg>
A Reusable Rectangle
You can reuse a rectangle. Give your rectangle an id
and put it in a defs
element. Children of a defs
element won’t be immediately rendered, but you can include them later in your rendered document. Wherever you would have placed your rectangle, put a use
element there instead. Set its xlink:href
attribute to the id
of your rectangle, preceded by a hash (#
). You can set its x
and y
attributes to position the rectangle, and you can style it as though it were a g
element containing your rectangle.
If you’re not using D3, you need to include the xlink namespace explicitly in your document.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
height="100px" width="160px">
<defs>
<rect id="ruse" x="0" y="0" height="100%" width="100%" fill="rgb(78,62,62)" />
</defs>
<use xlink:href="#ruse" />
</svg>
A Rasterized Rectangle
Rectangles aren’t the only things you can reuse. SVG comes with a number of elements that don’t actually draw anything directly to the screen but can be applied to elements to change the way that they’re rendered. They’re called SVG filters, and you define them in the defs
section of your document.
feImage
is an SVG filters primitive that loads an external graphic as a raster graphic. If you apply this filter to an element, it will draw the loaded raster graphic instead of the element itself.
By default SVG filters use the linearRGB color space to interpret colors. So by default, colors won’t appear as you expect them to. To use the standard RGB color space, set the color-interpolation-filters
attribute of your filter to "sRGB"
.
Not only can you reference external graphics with an feImage
filter, you can also reference other SVG elements by their ids. When you do this, the feImage
filter turns the element into a raster graphic, and when you apply the filter to an element, it’ll draw your rasterized rectangle.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
height="100px" width="160px">
<defs>
<rect id="rimg" x="0" y="0" width="100%" height="100%" fill="rgb(131,190,153)" />
<filter id="rfimage" x="0%" y="0%" width="100%" height="100%"
color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
<feImage xlink:href="#rimg" />
</filter>
</defs>
<g filter="url(#rfimage)"></g>
</svg>
Not a Rectangle at All
Up until now you’ve had to use a rect
element to draw a rectangle. You could have used other basic shapes that SVG provides to replace the rect
elements, such as a path
or a polygon
. But the question is, Can you draw a rectangle without using any basic shapes? It turns out that you can, using another SVG filter: feFlood
.
feFlood
is another primitive SVG filter. Its result is a raster graphic filled with color you specify in its flood-color
attribute. Set the dimensions of your desired rectangle in the filter
element, and apply the filter to a group element. The result is a rectangle, and you didn’t have to use a rectangle to draw it.
<svg xmlns="http://www.w3.org/2000/svg" height="100px" width="160px">
<defs>
<filter id="rfill" x="0" y="0" width="100%" height="100%"
color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
<feFlood flood-color="rgb(194,79,76)" />
</filter>
</defs>
<g filter="url(#rfill)"></g>
</svg>