创建反向剪辑路径 \- CSS 或 SVG

新手上路,请多包涵

我正在尝试创建本质上与 CSS 剪辑路径相反的东西。使用 clip-path 时,图像或 div 会被裁剪,以便仅保留您指定的形状,而其余背景将被有效删除。

我希望这样,如果我剪辑一个形状,它基本上会在最上层打一个洞并移除形状,而不是背景。这可能吗?我也对 SVG 解决方案持开放态度,但我是 SVG 的新手,所以请善待 :)

基本上,在下面的代码中,我有一个完全位于红色方块内的蓝色方块,并且希望能够从蓝色方块中打出一个形状,以便下面的红色层显示出形状曾经所在的位置。实际上会有一个图像作为背景层,所以我不能接受模仿我想要的但实际上没有冲出形状的伪效果。

任何帮助都会很棒!

代码笔: https ://codepen.io/emilychews/pen/GQmyqx

 body {
  width: 100%;
  height: 100vh;
  padding: 0; margin: 0;
  display: flex;
  }

#box {
  margin: auto;
  position: relative;
  width: 33%;
  height: 200px;
  background: red;
}

#innerbox {
  width: 100%;
  height: 100%;
  background: blue;
  top: 0;
  left: 0;
  position: absolute;
}
 <div id="box">
  <div id="innerbox"></div>
</div>

原文由 pjk_ok 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.5k
2 个回答

您可以将图像 放在蓝色部分上方,然后在其上应用 clip-path 结果将与您在蓝色部分内部创建一个孔相同,如下图 所示

 body {
  width: 100%;
  height: 100vh;
  padding: 0; margin: 0;
  display: flex;
  }

#box {
  margin: auto;
  position: relative;
  width: 33%;
  height: 200px;
  background: blue;
}

#innerbox {
  width: 100%;
  height: 100%;
  background: url(https://lorempixel.com/400/400/) center/cover;
  top: 0;
  left: 0;
  position: absolute;
  z-index:1;
  clip-path:polygon(10% 10%, 10% 90%, 90% 50%);
}
 <div id="box">
  <div id="innerbox"></div>
</div>

另一个想法是考虑多个背景,您将获得比 clip-path 更好的支持,而且代码更少:

 body {
  height: 100vh;
  margin: 0;
  display: flex;
}

#box {
  margin: auto;
  position: relative;
  width: 33%;
  height: 200px;
  background:
    linear-gradient(to bottom right,transparent 49%,blue 50%) bottom/100% 60%,
    linear-gradient(to top right,transparent 49%,blue 50%) top/100% 60%,
    linear-gradient(blue,blue) left/20% 100%,
    url(https://lorempixel.com/400/400/) center/cover;
  background-repeat:no-repeat;
}
 <div id="box">
</div>

更新

如果你想要一些不透明度,这里有一个想法,你必须使用 clip-path 复制内容(缺点):

 body {
  width: 100%;
  height: 100vh;
  padding: 0; margin: 0;
  display: flex;
  }

#box {
  margin: auto;
  position: relative;
  width: 33%;
  height: 200px;
  background: blue;
}

#innerbox,#innerbox-2 {
  width: 100%;
  height: 100%;
  background: url(https://lorempixel.com/400/400/) center/cover;
  top: 0;
  left: 0;
  position: absolute;
  z-index:2;
}
#innerbox {
  /* if you initially planned to have x opacity so you need to set 1-x here*/
  opacity:0.4;
}

#innerbox-2 {
  z-index:1;
  clip-path:polygon(10% 10%, 10% 90%, 90% 50%);
  animation:animate 5s linear alternate infinite;
}

@keyframes animate {
  from {
    clip-path:polygon(10% 10%, 10% 90%, 90% 50%);
  }
  to {
     clip-path:polygon(20% 50%, 90% 50%, 80% 10%);
  }
}
 <div id="box">
  <div id="innerbox">
    <h1>Title</h1>
    <p>Some content</p>
  </div>
  <div id="innerbox-2">
    <h1>Title</h1>
    <p>Some content</p>
  </div>
</div>

更新 2

您可以考虑使用 SVG 来满足您的初始要求。只需使用 SVG 而不是 div,您将在其中获得遮罩。

 body {
  width: 100%;
  height: 100vh;
  padding: 0; margin: 0;
  display: flex;
  }

#box {
  margin: auto;
  position: relative;
  width: 33%;
  height: 200px;
  background: blue;
  background: url(https://lorempixel.com/400/400/) center/cover;
}

#innerbox {
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  position: absolute;
  z-index:1;
}
 <div id="box">
  <svg viewBox="0 0 200 200" id="innerbox" preserveAspectRatio="none">
  <defs>
    <mask id="hole">
      <rect width="100%" height="100%" fill="white"/>
      <!-- the hole defined a polygon -->
      <polygon points="20,20 20,180 180,100 " fill="black"/>
    </mask>
  </defs>
  <!-- create a rect, fill it with the color and apply the above mask -->
  <rect fill="blue" width="100%" height="100%" mask="url(#hole)" />
</svg>
</div>

您还可以使用与背景相同的 SVG:

 body {
  width: 100%;
  height: 100vh;
  padding: 0; margin: 0;
  display: flex;
  }

#box {
  margin: auto;
  position: relative;
  width: 33%;
  height: 200px;
  background: blue;
  background: url(https://lorempixel.com/400/400/) center/cover;
}

#innerbox {
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  position: absolute;
  z-index:1;
  background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" preserveAspectRatio="none"><defs><mask id="hole"><rect width="100%" height="100%" fill="white"/> <polygon points="20,20 20,180 180,100 " fill="black"/></mask></defs><rect fill="blue" width="100%" height="100%" mask="url(%23hole)" /></svg>');
}
 <div id="box">
  <div id="innerbox"></div>

</div>

更新 3(我在 2020 年推荐的)

您可以使用 CSS 掩码来获得您想要的效果 mask-composite

 body {
  width: 100%;
  height: 100vh;
  padding: 0; margin: 0;
  display: flex;
  }

#box {
  margin: auto;
  position: relative;
  width: 33%;
  height: 200px;
  background: url(https://lorempixel.com/400/400/) center/cover;
}

#innerbox {
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  position: absolute;
  -webkit-mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" preserveAspectRatio="none"><polygon points="20,20 20,180 180,100 " fill="black"/></svg>') 0/100% 100%;
          mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" preserveAspectRatio="none"><polygon points="20,20 20,180 180,100 " fill="black"/></svg>') 0/100% 100%;
  background:blue;
}
 <div id="box">
  <div id="innerbox"></div>
</div>

和使用相同形状的倒置版本

 body {
  width: 100%;
  height: 100vh;
  padding: 0; margin: 0;
  display: flex;
  }

#box {
  margin: auto;
  position: relative;
  width: 33%;
  height: 200px;
  background: url(https://lorempixel.com/400/400/) center/cover;
}

#innerbox {
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  position: absolute;
  -webkit-mask:
     url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" preserveAspectRatio="none"><polygon points="20,20 20,180 180,100 " fill="black"/></svg>') 0/100% 100%,
     linear-gradient(#fff,#fff);
  -webkit-mask-composite:destination-out;
          mask:
     url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" preserveAspectRatio="none"><polygon points="20,20 20,180 180,100 " fill="black"/></svg>') 0/100% 100%,
     linear-gradient(#fff,#fff);
  mask-composite:exclude;
  background:blue;
}
 <div id="box">
  <div id="innerbox"></div>
</div>

原文由 Temani Afif 发布,翻译遵循 CC BY-SA 4.0 许可协议

这在谷歌上排名很高,答案并没有解决我的问题 b/c 我无法触摸我的背景图片所以这是另一种方法:

使用剪辑路径创建一个框架。

 body {
  width: 100%;
  height: 100vh;
  padding: 0;
  margin: 0;
  display: grid;
  place-items: center;
}

#clip,
#background {
  width: 400px;
  height: 400px;
}

#clip {
  clip-path: polygon(0% 0%, 0% 100%, 25% 100%, 25% 25%, 75% 25%, 75% 75%, 25% 75%, 25% 100%, 100% 100%, 100% 0%);
  position: absolute;
  background: #fff;
  opacity: 0.8;
}

#background {
  background: url(https://picsum.photos/400/400/) center/cover;
  z-index: -1;
}
 <div id="background">
  <div id="clip"></div>
</div>

为方便起见,我将 clip-div 放在图像内部,但您也可以将其放在图像外部。但是,请确保您可以 接受 clip-path 的有限浏览器支持

原文由 leonheess 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题