9

I want to create a CSS class to fill a path with image that can be applied on any SVG path and fill that path with image. The image must be stretch to fit that path.

To achieve this; I create a pattern with image tag and set the width and height as 100%. but the image takes 100% of the whole screen instead of objectBoundingBox of the container (in this case svg tag).

Below is the sample code:

.myClass {
  fill: url(#image);
  stroke: red;
  stroke-width: 5;
}

<svg id='pattern' xmlns="http://www.w3.org/2000/svg" version="1.1">
  <defs>
    <pattern id='image' x=0 y=0 width="100%" height="100%" patternUnits='objectBoundingBox'>
      <image xlink:href='myImage.png' x=0 y=0 width="100%" height="100%" preserveAspectRatio="none"></image>
    </pattern>
  </defs>
</svg>
<svg id='triangle' xmlns="http://www.w3.org/2000/svg" version="1.1" width='300px' height='300px'>
    <path d='M0 0 L300 0 L300 300 Z' class='myClass'></path>
</svg>

May be I am doing something wrong.

Please suggest any solution for this problem.

Harish Khattri
  • 93
  • 1
  • 1
  • 4

1 Answers1

12

Here's your thing working - http://jsfiddle.net/eAfTc/

.myClass {
  fill: url(#image);
  stroke: red;
  stroke-width: 5;
}

<svg id='pattern' xmlns="http://www.w3.org/2000/svg" version="1.1">
  <defs>
    <pattern id='image' width="1" height="1" viewBox="0 0 100 100" preserveAspectRatio="none">
      <image xlink:href='http://dummyimage.com/600x400/abc/333' width="100" height="100" preserveAspectRatio="none"></image>
    </pattern>
  </defs>
</svg>
<svg id='triangle' xmlns="http://www.w3.org/2000/svg" version="1.1" width='300px' height='300px'>
    <path d='M0 0 L300 0 L300 300 Z' class='myClass'></path>
</svg>

Note that there's a patternContentUnits and a patternUnits, they do different things. Personally I prefer to use a viewBox for defining the coordinate system.

Here's a new example showing the pattern applied to various elements of different sizes and aspect ratios, it also gets rid of the first svg fragment.

Update: I added 'preserveAspectRatio' to the <pattern> element, and a new example showing the stretching and scaling.

Erik Dahlström
  • 59,452
  • 12
  • 120
  • 139
  • Solution looks good. But not working in webkit based browsers [e.g. chrome] – Hoshin Dec 18 '12 at 05:43
  • 1
    @Hoshin works fine for me, you just need to scroll down to see the result (Chrome gives the first svg fragment some default size which isn't the same as in Firefox/Opera). I should add that typically you'd not have a separate svg fragment for the pattern, just add the section to the svg fragment with id='triangle' instead. – Erik Dahlström Dec 18 '12 at 09:55
  • 1
    @ErikDahlström The solution does work, but only for svg-path/group with same height and width. However, when the same pattern is applied to a path having different height and width, the image does not appear to be fully stretched. Is it a caveat, or does any solution exist? – Harish Khattri Dec 19 '12 at 14:13
  • @ErikDahlström I do get your point that the def tag and path should typically be within the same svg fragment, but my requirement is to create a common definition to be applied on svgs with different dimensions. – Harish Khattri Dec 19 '12 at 14:20
  • I've been searching for a solution to add a background image to my shape drawn via svg path.. this fixed it! Thank you! – pourmesomecode Nov 11 '15 at 15:27