svgbackgroundsvg-patternsvg-rect

Force SVG fill pattern to be relative to rect container


For an SVG <rect> container, a fill background made with the <pattern> tag seems to start relative to the overall view.

What's the cleanest way to make the <pattern> start relative to the <rect> container?

The goal is to be able to have multiple <rect> containers reusing a <pattern> such that each container renders with the same background starting in the upper left corner of the container.  Below is an example SVG with two <rect> containers filled with marbles.

SVG:

<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
   width="400px" height="250px" viewBox="0 0 400 250">
   <defs>
      <pattern id="marbles" width="50" height="50"
         patternUnits="userSpaceOnUse">
         <circle cx="25" cy="25" r="22" fill="plum" stroke="black"/>
      </pattern>
   </defs>
   <rect width="100%" height="100%" fill="teal"/>
   <rect x="10" y="10"  width="150" height="100" fill="url(#marbles)"/>
   <rect x="90" y="120" width="250" height="100" fill="url(#marbles)"/>
</svg>

Actual output:
Actual output

The fill background ignores the x and y attributes of the rect container.

Desired output:
Desired output

Experiment with the code:
https://jsfiddle.net/pilafmon/b5edq3go/


Solution

  • Use a transform to position the rect elements rather than x and y.

    <?xml version="1.0" encoding="utf-8"?>
    <svg xmlns="http://www.w3.org/2000/svg"
       width="400px" height="250px" viewBox="0 0 400 250">
       <defs>
          <pattern id="marbles" width="50" height="50"
             patternUnits="userSpaceOnUse">
             <circle cx="25" cy="25" r="22" fill="plum" stroke="black"/>
          </pattern>
       </defs>
       <rect width="100%" height="100%" fill="teal"/>
       <rect transform="translate(10,10)" width="150" height="100" fill="url(#marbles)"/>
       <rect transform="translate(90,120)" width="250" height="100" fill="url(#marbles)"/>
    </svg>