How to add border in my clip-path: polygon(); CSS style

橙三吉。 提交于 2019-11-26 18:45:26
Harry

Can border be applied to a clipped element along the clip path?

No, adding border property to the clipped element would not apply the borders along the clipped path because the border is applied to the original rectangle (or square) container before the clip-path is applied and so, it also gets clipped out. You can see this in the below snippet:

div {
  display: inline-block;
  height: 200px;
  width: 200px;
  border: 3px solid;
  background: darkseagreen;
}
div + div {
  -webkit-clip-path: polygon(50% 0%, 100% 100%, 100% 0%);
}
<div></div>
<div></div>

Are there any alternate ways to create such a border effect?

We can mimic it by applying the same clip-path on a container element. The container element's background color will look as though it is the border of the inner element because both are clipped and the container has slightly higher dimensions than the inner element.

.poligon {
  display: inline-block;
  position: relative;
  width: 150px;
  height: 150px;
  background: red;
  box-sizing: border-box;
  -webkit-clip-path: polygon(92.32051% 40%, 93.79385% 43.1596%, 94.69616% 46.52704%, 95% 50%, 94.69616% 53.47296%, 93.79385% 56.8404%, 92.32051% 60%, 79.82051% 81.65064%, 77.82089% 84.50639%, 75.35575% 86.97152%, 72.5% 88.97114%, 69.3404% 90.44449%, 65.97296% 91.34679%, 62.5% 91.65064%, 37.5% 91.65064%, 34.02704% 91.34679%, 30.6596% 90.44449%, 27.5% 88.97114%, 24.64425% 86.97152%, 22.17911% 84.50639%, 20.17949% 81.65064%, 7.67949% 60%, 6.20615% 56.8404%, 5.30384% 53.47296%, 5% 50%, 5.30384% 46.52704%, 6.20615% 43.1596%, 7.67949% 40%, 20.17949% 18.34936%, 22.17911% 15.49361%, 24.64425% 13.02848%, 27.5% 11.02886%, 30.6596% 9.55551%, 34.02704% 8.65321%, 37.5% 8.34936%, 62.5% 8.34936%, 65.97296% 8.65321%, 69.3404% 9.55551%, 72.5% 11.02886%, 75.35575% 13.02848%, 77.82089% 15.49361%, 79.82051% 18.34936%);
  clip-path: polygon(92.32051% 40%, 93.79385% 43.1596%, 94.69616% 46.52704%, 95% 50%, 94.69616% 53.47296%, 93.79385% 56.8404%, 92.32051% 60%, 79.82051% 81.65064%, 77.82089% 84.50639%, 75.35575% 86.97152%, 72.5% 88.97114%, 69.3404% 90.44449%, 65.97296% 91.34679%, 62.5% 91.65064%, 37.5% 91.65064%, 34.02704% 91.34679%, 30.6596% 90.44449%, 27.5% 88.97114%, 24.64425% 86.97152%, 22.17911% 84.50639%, 20.17949% 81.65064%, 7.67949% 60%, 6.20615% 56.8404%, 5.30384% 53.47296%, 5% 50%, 5.30384% 46.52704%, 6.20615% 43.1596%, 7.67949% 40%, 20.17949% 18.34936%, 22.17911% 15.49361%, 24.64425% 13.02848%, 27.5% 11.02886%, 30.6596% 9.55551%, 34.02704% 8.65321%, 37.5% 8.34936%, 62.5% 8.34936%, 65.97296% 8.65321%, 69.3404% 9.55551%, 72.5% 11.02886%, 75.35575% 13.02848%, 77.82089% 15.49361%, 79.82051% 18.34936%);
}
.poligon img {
  position: absolute;
  top: 2px; /* equal to border thickness */
  left: 2px; /* equal to border thickness */
  width: 146px; /* container height - (border thickness * 2) */
  height: 146px; /* container height - (border thickness * 2) */
  -webkit-clip-path: polygon(92.32051% 40%, 93.79385% 43.1596%, 94.69616% 46.52704%, 95% 50%, 94.69616% 53.47296%, 93.79385% 56.8404%, 92.32051% 60%, 79.82051% 81.65064%, 77.82089% 84.50639%, 75.35575% 86.97152%, 72.5% 88.97114%, 69.3404% 90.44449%, 65.97296% 91.34679%, 62.5% 91.65064%, 37.5% 91.65064%, 34.02704% 91.34679%, 30.6596% 90.44449%, 27.5% 88.97114%, 24.64425% 86.97152%, 22.17911% 84.50639%, 20.17949% 81.65064%, 7.67949% 60%, 6.20615% 56.8404%, 5.30384% 53.47296%, 5% 50%, 5.30384% 46.52704%, 6.20615% 43.1596%, 7.67949% 40%, 20.17949% 18.34936%, 22.17911% 15.49361%, 24.64425% 13.02848%, 27.5% 11.02886%, 30.6596% 9.55551%, 34.02704% 8.65321%, 37.5% 8.34936%, 62.5% 8.34936%, 65.97296% 8.65321%, 69.3404% 9.55551%, 72.5% 11.02886%, 75.35575% 13.02848%, 77.82089% 15.49361%, 79.82051% 18.34936%);
  clip-path: polygon(92.32051% 40%, 93.79385% 43.1596%, 94.69616% 46.52704%, 95% 50%, 94.69616% 53.47296%, 93.79385% 56.8404%, 92.32051% 60%, 79.82051% 81.65064%, 77.82089% 84.50639%, 75.35575% 86.97152%, 72.5% 88.97114%, 69.3404% 90.44449%, 65.97296% 91.34679%, 62.5% 91.65064%, 37.5% 91.65064%, 34.02704% 91.34679%, 30.6596% 90.44449%, 27.5% 88.97114%, 24.64425% 86.97152%, 22.17911% 84.50639%, 20.17949% 81.65064%, 7.67949% 60%, 6.20615% 56.8404%, 5.30384% 53.47296%, 5% 50%, 5.30384% 46.52704%, 6.20615% 43.1596%, 7.67949% 40%, 20.17949% 18.34936%, 22.17911% 15.49361%, 24.64425% 13.02848%, 27.5% 11.02886%, 30.6596% 9.55551%, 34.02704% 8.65321%, 37.5% 8.34936%, 62.5% 8.34936%, 65.97296% 8.65321%, 69.3404% 9.55551%, 72.5% 11.02886%, 75.35575% 13.02848%, 77.82089% 15.49361%, 79.82051% 18.34936%);
}
<div class="poligon">
  <img src="http://lorempixel.com/g/600/400/">
</div>

Adding a Border to a Complex Clip Path With SVG Dilation Filter

Copy-Shrink Method Only Works In Simple Cases -- used in currently accepted answer

The currently accepted answer works by making a copy and shrinking it. This works for the example, but if you have a more complex shape (like text), it will not work. A better approach is to use dilation with a filter.

Shape Dilation Works on ANY Shape

A better approach is to use dilation with the feMorphology filter!!

Key aspects:

  • Create matching <image> and <rect> shapes of equal height and width
  • Clip both with the desired shape path/polygon
  • Use filter to dilate/enlarge the clipped rect to make a border

The filter radius= becomes the stand in for border thickness.

The result:

.clipper{
  clip-path: url(#clip_shape);
}
.dilate{
  filter: url("#dilate_shape");
}
<svg xmlns="http://www.w3.org/2000/svg" height="400" width="400">
 <defs>
  <clipPath id="clip_shape" clipPathUnits="objectBoundingBox">
    <text x="0" y=".8" lengthAdjust="spacing" font-weight="700" font-style="italic" font-size="1"> M </text>
  </clipPath>
   <filter id="dilate_shape">
      <feMorphology operator="dilate" in="SourceGraphic" radius="5" />
   </filter>
   
 </defs> 
 
 <g transform="translate(5,5)">
 <g class="dilate">
   <rect class="clipper" x=0 y=0 height="400px" width="400px" fill="lightgreen"></rect>
 </g>
 <image class="clipper" xlink:href="http://placekitten.com/400/300" height="400px" width="400px">
 </g>
</svg>
Stewartside

Pseudo-Element

A nice way to do this would be with a pseudo-element like a :before

Make exactly the same shape but slightly smaller which holds the main color you want and position it correctly and you get the border you want.

The below example isn't the correct shape but shows how to achieve this effect:

.shape {
  width: 400px;
  height: 40px;
  background-color: black;
  -webkit-clip-path: polygon(5% 0, 100% 0, 100% 100%, 0 100%, 0 100%);
  clip-path: polygon(5% 0, 100% 0, 100% 100%, 0 100%, 0 100%);
  position: relative;
}

.shape:before {
  content: '';
  width: 398px;
  height: 38px;
  -webkit-clip-path: polygon(5% 0, 100% 0, 100% 100%, 0 100%, 0 100%);
  clip-path: polygon(5% 0, 100% 0, 100% 100%, 0 100%, 0 100%);
  background: green;
  display: block;
  position: absolute;
  top: 1px;
  left: 1px;
}
  
<div class="shape"></div>

Solution with pseudo element

I am write some simple code, use pseudo element - ::before, that I want to share.

I create the same shape-poligon, just bigger.

And so it seems that it has a border as you wanted (5px)

link to some nice clip-path: https://bennettfeely.com/clippy/

.poligon {
  height: 160px;
  width: 160px;
  background-color: black;
  clip-path: polygon(92.32051% 40%, 93.79385% 43.1596%, 94.69616% 46.52704%, 95% 50%, 94.69616% 53.47296%, 93.79385% 56.8404%, 92.32051% 60%, 79.82051% 81.65064%, 77.82089% 84.50639%, 75.35575% 86.97152%, 72.5% 88.97114%, 69.3404% 90.44449%, 65.97296% 91.34679%, 62.5% 91.65064%, 37.5% 91.65064%, 34.02704% 91.34679%, 30.6596% 90.44449%, 27.5% 88.97114%, 24.64425% 86.97152%, 22.17911% 84.50639%, 20.17949% 81.65064%, 7.67949% 60%, 6.20615% 56.8404%, 5.30384% 53.47296%, 5% 50%, 5.30384% 46.52704%, 6.20615% 43.1596%, 7.67949% 40%, 20.17949% 18.34936%, 22.17911% 15.49361%, 24.64425% 13.02848%, 27.5% 11.02886%, 30.6596% 9.55551%, 34.02704% 8.65321%, 37.5% 8.34936%, 62.5% 8.34936%, 65.97296% 8.65321%, 69.3404% 9.55551%, 72.5% 11.02886%, 75.35575% 13.02848%, 77.82089% 15.49361%, 79.82051% 18.34936%);
}

.poligon::before {
  content: "";
  display: block;
  position: relative;
  top: 5px;
  left: 5px;
  height: 150px;
  width: 150px;
  background-color: red;
  clip-path: polygon(92.32051% 40%, 93.79385% 43.1596%, 94.69616% 46.52704%, 95% 50%, 94.69616% 53.47296%, 93.79385% 56.8404%, 92.32051% 60%, 79.82051% 81.65064%, 77.82089% 84.50639%, 75.35575% 86.97152%, 72.5% 88.97114%, 69.3404% 90.44449%, 65.97296% 91.34679%, 62.5% 91.65064%, 37.5% 91.65064%, 34.02704% 91.34679%, 30.6596% 90.44449%, 27.5% 88.97114%, 24.64425% 86.97152%, 22.17911% 84.50639%, 20.17949% 81.65064%, 7.67949% 60%, 6.20615% 56.8404%, 5.30384% 53.47296%, 5% 50%, 5.30384% 46.52704%, 6.20615% 43.1596%, 7.67949% 40%, 20.17949% 18.34936%, 22.17911% 15.49361%, 24.64425% 13.02848%, 27.5% 11.02886%, 30.6596% 9.55551%, 34.02704% 8.65321%, 37.5% 8.34936%, 62.5% 8.34936%, 65.97296% 8.65321%, 69.3404% 9.55551%, 72.5% 11.02886%, 75.35575% 13.02848%, 77.82089% 15.49361%, 79.82051% 18.34936%);
}
<div class="poligon"></div>
Cyberpunk Interactive

I have another solution to this..

This is what I'm working on:

.top-angle-left {
    -webkit-clip-path: polygon(0 0, 100% 15%, 100% 100%, 0 100%);
    clip-path: polygon(0 0, 100% 15%, 100% 100%, 0 100%);
    position: relative;
}

.top-angle-left:after {
    -webkit-clip-path: polygon(0 0, 100% 15%, 100% 100%, 0 85%);
    clip-path: polygon(0 0, 100% 15%, 100% 100%, 0 85%);
    background: #e99d15;
    content: '';
    position: absolute;
    left: 0;
    top: -82%;
    right: 0;
    height: 100%;
    display: block;
    z-index: 9;
}

The idea that the :after element can ALWAYS scale with the its parent container, so now this is 100% responsive. This is only accomplished by applying the negative top to the :after element. Hope this is helpful!!

Here's how to do it.

<div class="screenshot"><img src="assets/img/tutorial/1.jpg"></div>

Just add duplicate the mask and add a padding to the parent.

.screenshot {
    mask: url(../assets/img/bubble.svg) center center no-repeat;
    background: white;
    padding: 10px;

    img {
        mask: url(../assets/img/bubble.svg) center center no-repeat;
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!