Search code examples
svgscaling

SVG patterns scaling the way pattern is not cut off


I'm trying to discover the way to scale svg patterns so that the pattern is not cut by the bounds of the element using it. And yet so that pattern is beeing repeated to cover that element.

Let's say i have a 20px radius circle as a pattern. Applying it to 80px width element:

80px width element

Now the element is beeing scaled to 90px, the pattern should stretch horizontally (no need to keep aspect ratio):

90px width element

And at last, scale up above 90px adds another circle occurance (95px width in this example - aspect ratio is still ignored):

95px width element

I can add some scripting to achieve that effect. But i'm curious about if i can get that behavior with pure SVG.

<svg style='display: block; height: 60px; width: 95px; '>
    <defs>
        <pattern patternUnits='userSpaceOnUse' viewBox='0 0 20 20' width='20'  height='20' id='the_pattern'>
            <circle cx='10' cy='10' r='10' stroke-width='0' fill='black'></circle>
        </pattern>
    </defs>

    <rect x='0' y='0' width='80' height='20' fill='url(#the_pattern)'></rect>
    <rect x='0' y='20' width='90' height='20' fill='url(#the_pattern)'></rect>
    <rect x='0' y='40' width='95' height='20' fill='url(#the_pattern)'></rect>

</svg>

Solution

  • The answer is no. You cannot achieve that with pure SVG. Unless by "pure SVG" you include SVGs that have embedded Javascript (ie <script> elements).

    You could do it with CSS border-image though.

    https://developer.mozilla.org/en-US/docs/Web/CSS/border-image

    Here's an example:

    Ignore the fact that I've used a diamond image here. Just replace it with a circle version of the border image file. :)

    .circle-border {
      border-top: 30px solid;
      border-image: url('https://interactive-examples.mdn.mozilla.net/media/examples/border-diamonds.png') 30 / 20px 0 0 0;
      border-image-repeat: round;
    }
    
    div {
      width: 80px;
      height: 0px;
      margin-bottom: 50px;
    }
    
    div:nth-child(2) {
      width: 90px;
    }
    
    div:nth-child(3) {
      width: 100px;
    }
    <div class="circle-border"></div>
    <div class="circle-border"></div>
    <div class="circle-border"></div>