phzdjz
phzdjz

Reputation: 99

Clip Path SVG file

Hi i am trying to do clip-path with my SVG file. I found a example that is exactly what i am trying to do but i cannot implement my object in such way. Also i have a svg file to do something like this.

img {
  clip-path: url(#svgClip);
    width: 300px;
    height: 300px;
    object-fit: cover;
    display: block;
    margin-right: auto;
    margin-left: auto;
}
<!DOCTYPE html>
<html>
<head>
<title>HTML, CSS and JavaScript demo</title>
</head>
<body>

  
  <img src="https://media-cdn.t24.com.tr/media/library/2021/07/1627040373809-100496736-steve-jobs-march-2011-getty.jpg" alt="Photographer in a market." />
<svg width="0" height="0">
    <clipPath id="svgClip" clipPathUnits="objectBoundingBox">
        <path d="M0.75815095,0.0579477769 C0.879893708,0.187288937 0.902165272,0.677587654 0.799370955,0.785996249 C0.627963035,0.966765889 0.26163708,0.91434951 0.111342491,0.755791573 C-0.0332137967,0.603287436 -0.035795248,0.382887577 0.0965066612,0.173955315 C0.200239457,0.0101396315 0.648923894,-0.0580965318 0.75815095,0.0579477769 Z"></path>
    </clipPath>
</svg>

</body>
</html>

This is my SVG file : svg file

When i change the "d section" with my svgs one in path tags everything is going. How can i correctly implement my svg file to this example?

Upvotes: 2

Views: 2305

Answers (2)

herrstrietzel
herrstrietzel

Reputation: 17165

For an easily reusable clip-path I recommend these steps:

  1. crop your path to its actual boundaries
  2. Scale the clip-path to fit a 1x1 bBox
  3. create a css image wrap class applying the clip-paths initial aspect ratio to the image

cropped clip-path example

.img-wrp {
  width: 200px;
  display:inline-block;
  border: 1px solid #ccc;
}
.img-wrp-aspect {
  position: relative;
  overflow: hidden;
}
/** add aspect-ratio pseudo element: according to clip-path element **/
.img-wrp-aspect:before {
  content: "";
  display: block;
  width: 100%;
  padding-bottom: var(--aspectRatPad);
}
.img-clipped {
  clip-path: url(#clipPath);
  object-fit: cover;
  object-position: 50%;
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.svgHidden {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}
<div class="img-wrp img-wrp-aspect" style="--aspectRatPad:94.219%">
  <img class="img-clipped" style="clip-path: url(#clipPath); object-position:50% 0%" src="https://media-cdn.t24.com.tr/media/library/2021/07/1627040373809-100496736-steve-jobs-march-2011-getty.jpg" alt="Photographer in a market." />
</div>

<div class="img-wrp img-wrp-aspect" style="--aspectRatPad:94.219%">
  <img class="img-clipped" style="clip-path: url(#clipPath); object-position:20% 0%" src="https://media-cdn.t24.com.tr/media/library/2021/07/1627040373809-100496736-steve-jobs-march-2011-getty.jpg" alt="Photographer in a market." />
</div>

<!-- hidden clip-path svg -->
<!-- 1. cropped and scaled down to 1x1 units -->
<svg viewBox="0 0 1 1" class="svgHidden" aria-hidden="true">
  <clipPath id="clipPath" clipPathUnits="objectBoundingBox">
    <path d="M0 0.101l0.657-0.099c0.12-0.018 0.232 0.071 0.25 0.199l0.093 0.697l-0.657 0.099c-0.12 0.018-0.232-0.071-0.25-0.199l-0.093-0.697z" />
  </clipPath>
</svg>
<p>You can shift the image position by changing the <strong>object-position</strong> attribute</p>

To fit the image to the clipped frames' dimensions you can use object-fit:auto (actually like your original css:

.img-clipped {
  clip-path: url(#clipPath);
  object-fit: cover;
  object-position: 50%;
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

The images layout width is controlled by the wrapping <div>

How to get a cropped clip-path?

  1. Open and crop it in a vector drawing app like AI, Inkscape, Figma etc. (Honestly, I think this option is often overlooked)
  2. Write a js helper like this: Codepen (just paste your path and check the 'clipPath' option.
  3. Use Yoksel's excellent clip-path helper By default, it won't crop anything, but there is also a "Remove offset" option

css path() approach

(Theoretically) you can also define a clip-path directly in css like so (MDN example):

clip-path: path('M 0 200 L 0,75 A 5,5 0,0,1 150,75 L 200 200 z');

Unfortunately, css (pseudo svg) capabilities aren't yet on par with svg based clip paths – this will most likely change in future browser versions introducing more elaborate concepts for path scaling/fitting.

However, @ccprog's pathfit library might be interesting to fix the aforementioned css path() shortcomings.

Further reading: About clip-path caveats and pitfalls

Eric Meyer: Scaling SVG Clipping Paths for CSS Use
Css-tricks: Unfortunately, clip-path: path() is Still a No-Go
Css-tricks: Clipping and Masking in CSS

Upvotes: 1

Alexandr_TT
Alexandr_TT

Reputation: 14545

The main problem is the relative position of the image and the clip-path To show this I've put the image and path from your svg file which will act as clip-path into one svg file

<svg  xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink"
         width="800" height="450" viewBox="0 0 1600 900" >  
         
  <image  xlink:href="https://media-cdn.t24.com.tr/media/library/2021/07/1627040373809-100496736-steve-jobs-march-2011-getty.jpg" alt="Photographer in a market." width="100%" height="100%"  />

     <path fill="none" stroke="white"  d="M 112 199.809 L 636.962 125.131 C 733.54 111.392 823.103 178.647 836.842 275.226 L 911.52 800.191 L 386.558 874.869 C 289.98 888.608 200.417 821.353 186.678 724.774 L 112 199.809 Z"/>
</svg>

To center the frame I used the transform command transform="translate(140,-30)"

 <svg  xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink"
         width="800" height="450" viewBox="0 0 1600 900" >  
         
  <image  xlink:href="https://media-cdn.t24.com.tr/media/library/2021/07/1627040373809-100496736-steve-jobs-march-2011-getty.jpg" alt="Photographer in a market." width="100%" height="100%"  />

     <path transform="translate(140,-30)" fill="none" stroke="white"  d="M 112 199.809 L 636.962 125.131 C 733.54 111.392 823.103 178.647 836.842 275.226 L 911.52 800.191 L 386.558 874.869 C 289.98 888.608 200.417 821.353 186.678 724.774 L 112 199.809 Z"/>
</svg>

SVG clipPath syntax

.container {
width:80vw;
height:80vh;
}
<div class="container">
 <svg  xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink"
         viewBox="0 0 1600 900">  
<defs>
       <clipPath id="cP">
        <path fill="none" stroke="white" transform="translate(140,-30)" d="M 112 199.809 L 636.962 125.131 C 733.54 111.392 823.103 178.647 836.842 275.226 L 911.52 800.191 L 386.558 874.869 C 289.98 888.608 200.417 821.353 186.678 724.774 L 112 199.809 Z"/>
      </clipPath>   
</defs>
  <image clip-path="url(#cP)" xlink:href="https://media-cdn.t24.com.tr/media/library/2021/07/1627040373809-100496736-steve-jobs-march-2011-getty.jpg" alt="Photographer in a market." width="100%" height="100%"  />
</svg>
</div>

CSS clip-path syntax

Since the size of the photo is much larger than the size of the clip, I had to apply a reduction transformation to the size of the image.

img {
 clip-path:url(#cP); 
transform:scale(0.5);
 }

img {
 clip-path:url(#cP); 
transform: scale(0.5);

 }
<img src="https://media-cdn.t24.com.tr/media/library/2021/07/1627040373809-100496736-steve-jobs-march-2011-getty.jpg" alt="Photographer in a market." />  
<svg  xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink"
         width="0" height="0"  >  
<defs>
       <clipPath id="cP">
        <path fill="none"  transform="translate(140,-30)" d="M 112 199.809 L 636.962 125.131 C 733.54 111.392 823.103 178.647 836.842 275.226 L 911.52 800.191 L 386.558 874.869 C 289.98 888.608 200.417 821.353 186.678 724.774 L 112 199.809 Z"/>
      </clipPath>   
</defs>
</svg>

Upvotes: 2

Related Questions