Niek Nijland
Niek Nijland

Reputation: 772

How to use background-position: center; behaviour on svg pattern?

I'm using an svg with a pattern in it. The svg is the full width of the browser window. When I resize the browser, I want the svg pattern to expand from the center of the svg(background-position: center; behaviour).

html {
  height: 100%;
  }
  
body {
  height: 100%;
  margin: 0;
}
<svg width="100%" height="100%">
    <defs>
        <pattern id="pat" x="0" y="0" width="24" height="24" patternUnits="userSpaceOnUse">
            <polygon points="12,5 7,5 7,0 5,0 5,5 0,5 0,7 5,7 5,12 7,12 7,7 12,7 "/>
        </pattern>
    </defs>
    <rect x="0" y="0" width="100%" height="100%" fill="url(#pat)" />
</svg>

When you run the snippet en resize the result window. The pattern is expanded and contract from the left top. I want the pattern to expand and contract from the center of the svg. Is this possible

Upvotes: 0

Views: 513

Answers (1)

Paul LeBeau
Paul LeBeau

Reputation: 101918

The problem is that the origin of the coordinates (and therefore the pattern) is at the top left of the SVG. To centre the pattern, you have to get that origin to the centre of the SVG.

Normal transform attributes can't do that because they don't take percentages. The only way to achieve it is to use a <use> element. It's x and y attributes are effectively a trannsform but they do allow percentages.

So the solution is to make the <rect> 100% width and height, but position it at x="-50%" y="-50%" so that its centre is at the origin. We then move the origin to (50%, 50%) with our <use> element.

Click "Full page" for the best view

html {
  height: 100%;
  }
  
body {
  height: 100%;
  margin: 0;
}
<svg width="100%" height="100%">
  <defs>
    <pattern id="pat" x="0" y="0" width="24" height="24" patternUnits="userSpaceOnUse">
      <polygon points="12,5 7,5 7,0 5,0 5,5 0,5 0,7 5,7 5,12 7,12 7,7 12,7 "/>
    </pattern>
    <rect id="rect" x="-50%" y="-50%" width="100%" height="100%" fill="url(#pat)" />
  </defs>
  <use xlink:href="#rect" x="50%" y="50%"/>
</svg>

But if you try this, it will still not appear to be centred. That's because your cross symbol is not centred in your 24x24 pattern. If we reposition the cross so that it is in the centre of the pattern, you get this:

html {
  height: 100%;
  }
  
body {
  height: 100%;
  margin: 0;
}
<svg width="100%" height="100%">
  <defs>
    <pattern id="pat" x="0" y="0" width="24" height="24" patternUnits="userSpaceOnUse">
      <polygon points="18,11 13,11 13,6 11,6 11,11 6,11 6,13 11,13 11,18 13,18 13,13 18,13 "/>
    </pattern>
    <rect id="rect" x="-50%" y="-50%" width="100%" height="100%" fill="url(#pat)" />
  </defs>
  <use xlink:href="#rect" x="50%" y="50%"/>
</svg>

Upvotes: 1

Related Questions