Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS Clip-path positioning issues

I have created a fairly simple shape using an SVG element which is then put into my CSS using clip-path. It should make the corners rounded for me but for some reason only 1 of the corners does the effect perfectly.

This is the shape:

<svg height="500" width="500">

  <path fill="#555555" d="M50,0 L450,0 Q500,0 500,50 L500,400 Q500,450 450,450 L200,450 L175,500 L150,450 L50,450 Q0,450 0,400 L0,50 Q0,0 50,0z" />

</svg>

This is what happens when i use it as a clip-path

body {
  background: #555;
}
img {
  clip-path: url(#svgPath);
  -webkit-clip-path: url(#svgPath);
}
<svg height="0" width="0">
  <defs>
    <clipPath id="svgPath">
      <path fill="#FFFFFF" d="M50,0 L450,0 Q500,0 500,50 L500,400 Q500,450 450,450 L200,450 L175,500 L150,450 L50,450 Q0,450 0,400 L0,50 Q0,0 50,0z" />
    </clipPath>
  </defs>
</svg>

<img src="https://dummyimage.com/500" />

It seems to work perfectly within FireFox but shows the corners aren't cut correctly in Chrome apart from the bottom right corner.

like image 875
Stewartside Avatar asked Sep 16 '15 08:09

Stewartside


1 Answers

The default units for the clip-path is userSpaceOnUse and this seems to calculate the coordinates of the path with reference to the root element. This is the reason why the clip-path seems like it is producing an incorrect output. Nullifying the margin and padding on the root element or absolutely positioning the element (like in the below snippet) should solve the issue.

body {
  background: #555;
}
img {
  position: absolute;
  top: 0px;
  left: 0px;
  clip-path: url(#svgPath);
  -webkit-clip-path: url(#svgPath);
}
<svg height="0" width="0">
  <defs>
    <clipPath id="svgPath">
      <path fill="#FFFFFF" d="M50,0 L450,0 Q500,0 500,50 L500,400 Q500,450 450,450 L200,450 L175,500 L150,450 L50,450 Q0,450 0,400 L0,50 Q0,0 50,0z" />
    </clipPath>
  </defs>
</svg>

<img src="http://lorempixel.com/500/500/" />

However, in a real life scenario the actual element that has to be clipped could be present anywhere within the body and hence I think it is a much better approach to use the objectBoundingBox as the units like in the below snippet:

body {
  background: #555;
}
img {
  clip-path: url(#svgPath);
  -webkit-clip-path: url(#svgPath);
}
<svg height="0" width="0">
  <defs>
    <clipPath id="svgPath" clipPathUnits="objectBoundingBox">
      <path fill="#FFFFFF" d="M0.1,0 L0.9,0 Q1,0 1,0.1 L1,0.8 Q1,0.9 0.9,0.9 L0.4,0.9 L0.35,1 L0.3,0.9 L0.1,0.9 Q0,0.9 0,0.8 L0,0.1 Q0,0 0.1,0z" />
    </clipPath>
  </defs>
</svg>

<img src="https://dummyimage.com/500" />

As mentioned in the question itself, this behavior is visible only in Chrome and not Firefox for reasons unknown to me. Firefox produces an output similar to the expected one even when (a) extra padding + margin is added to the body and (b) when the image itself is wrapped inside another container which also has padding + margin.

The only case where Firefox's output matches with Chrome is when a padding is added directly to the img tag itself. I believe this happens because padding is part of the element and thus affects the coordinates.

like image 148
Harry Avatar answered Sep 30 '22 11:09

Harry