1

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?

phzdjz
  • 79
  • 7
  • What does "everything is going" mean? What are you changing the path tags to and how are you doing it? I see that the clipPath in the question and in the link are radically different, one has a path with values in the range 0..1 and the other (in the link) doesn't. – Robert Longson Jan 26 '22 at 14:43
  • I mean everyting is losing when i change path values. Also i changed the path values to the range 0..1, the result is like that: https://i.imgur.com/QNw4OHX.png – phzdjz Jan 26 '22 at 15:50

2 Answers2

2

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>
Alexandr_TT
  • 13,635
  • 3
  • 27
  • 54
  • that works well but when i change the photo, its appearance also changes and photo is not shown completely like this photo https://i.imgur.com/lbffq6u.png. Is there any way to fix photo sizing when photo is changed? Also, when i try to use `width` and `height` attributes instead of `transform:scale(0.5)` the clip path is become broken like this photo https://i.imgur.com/KtQyulA.png. – phzdjz Jan 26 '22 at 17:50
  • @phzdjz To make the clip work the same, you need to select images of the same size and it will be better if they have the same height and width – Alexandr_TT Jan 26 '22 at 17:58
  • Of course but, i am trying to make poster automation. So users will change any random image. Its results has to be same for all sized photos. It should not be dependent on image size or width and height ratio. – phzdjz Jan 26 '22 at 18:03
  • @phzdjz In this case, without JS, a universal solution will not work. You have to compromise somewhere. The question did not contain words about the universality of the solution. I solved your example, so it would be good to accept this answer and ask a new question – Alexandr_TT Jan 26 '22 at 18:16
1

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

herrstrietzel
  • 11,541
  • 2
  • 12
  • 34