Fill a svg path with a full background-image

Viewed 7084

I have the next svg :

<svg 
   xmlns="http://www.w3.org/2000/svg"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   width="483px" height="255px">
   <path fill-rule="evenodd"  fill="rgb(0, 0, 0)"
   d="M-0.000,-0.001 L483.001,1.873 L266.099,254.997 L-0.000,254.997 L-0.000,-0.001 Z"/>
</svg>

https://i.stack.imgur.com/1pdB7.png

How can I insert a full-background image, with a position center and no-repeat attributes? Like in this example :

https://i.stack.imgur.com/tUqbr.png

I really apreciate your answers, Thank you!

4 Answers

You can use the path as a clipping path like this:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="483px" height="255px">
 <defs>   
  <clipPath id="theClippingPath" > 
  <path 
   d="M-0.000,-0.001 L483.001,1.873 L266.099,254.997 L-0.000,254.997 L-0.000,-0.001 Z"/>
 </clipPath> 
  </defs> 
  <image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/beagle400.jpg" height="485" width="485" clip-path="url(#theClippingPath)"></image>
</svg>

You can use pattern to fill your background image.

<svg 
   xmlns="http://www.w3.org/2000/svg"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   width="483px" height="255px">
    <defs>
        <pattern id="img1" patternUnits="userSpaceOnUse" width="600" height="450">
            <image xlink:href="download.jpg" x="0" y="0"
                width="600" height="450" />
        </pattern>
    </defs>
    <path d="M-0.000,-0.001 L483.001,1.873 L266.099,254.997 L-0.000,254.997 L-0.000,-0.001 Z"
          fill="url(#img1)" />

</svg>

Although you could explore rendering an image from within an SVG, however there's a much simpler solution to achieve the same effect.

It's probably best to take this approach:

  1. Render your image regularly either as an <img> element, or as a background-image for a <div>. Position and style it how you want within the container.

  2. Position a shape on top of the image, on the side, that matches the background of your page (or parent element). This shape could be an <svg> especially if you wanted curved lines and complex edge shapes, but for your needs you could just do it with a colored <div> rotated 5 degrees. Much more performant.

This way the image can be managed and loaded normally, and not be trapped inside an SVG. Doing actual masks/clipping of elements and images is possible but you'd have to wrestle with browser bugs and compatibility issues.

Codepen

.container { 
  width: 600px;
  height: 200px;
  overflow: hidden;
  position: relative;
  background-color: #000000;
  margin-bottom: 2em;
  color: #ffffff;
}

.container_inner {
  padding: 2em;
}

#side-shape {
    height: 400%;
    background-color: #ffffff;
    position: absolute;
    width: 200px;
    right: -10%;
    top: -200%;
    z-index: 1;
    transform: rotate(5deg); 
}


#side-shape2 {
  fill: #ffffff;
    height: 100%;
    position: absolute;
    width: 200px;
    right: 0%;
    top: 0%;
    z-index: 1;
}
<div class="container">
  
  <div class="container_inner">
  MY IMAGE
  
  <p>Either an &lt;img&gt; element,</p>
  <p>  or a background-image for the container.
    
  <p>The side slash is just a white &lt;div&gt; rotated 5 degrees.</p>
  </div>  
  
  <div id="side-shape"></div>
  
</div>


<div class="container">
  
  <div class="container_inner">
  SAME AS ABOVE
  
  <p>Same as above, except The side slash is a white &lt;svg&gt; triangle.</p>
  
<svg id="side-shape2" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
    <polygon points="100 0, 100 100, 90 100"/>
</svg>
  
</div>

Here is a CSS only solution for this:

.box {
  width: 400px;
  height: 200px;
  position: relative;
  overflow: hidden;
}

.box span {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  transform-origin: top left;
  transform: skewX(-20deg);
  overflow: hidden;
}

.box span::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  transform-origin: top left;
  transform: skewX(20deg);
  background: url(https://picsum.photos/800/600?image=0) center/cover;
}


body {
 background:pink;
}
<div class="box">
  <span></span>
</div>

And in case you don't need to have transparency you can use less of code

.box {
  width: 400px;
  height: 200px;
  position: relative;
  background:
    linear-gradient(to bottom right,transparent 49.8%,pink 50%) right/20% 100% no-repeat,
    url(https://picsum.photos/800/600?image=0) center/cover;
}
body {
 background:pink;
}
<div class="box">
</div>

Another way with clip-path

.box {
  width: 400px;
  height: 200px;
  position: relative;
  background:url(https://picsum.photos/800/600?image=0) center/cover;
  -webkit-clip-path:polygon(0 0,0 100%, 80% 100%, 100% 0);
  clip-path:polygon(0 0,0 100%, 80% 100%, 100% 0);
}
body {
 background:pink;
}
<div class="box">
</div>

Related