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>