创建反向剪辑路径 - CSS 或 SVG
Posted
技术标签:
【中文标题】创建反向剪辑路径 - CSS 或 SVG【英文标题】:Create a Reverse Clip-Path - CSS or SVG 【发布时间】:2018-07-22 01:56:52 【问题描述】:我正在尝试创建本质上与 CSS 剪辑路径相反的内容。使用 clip-path 时,图像或 div 会被剪裁,以便仅保留您指定的形状,而其余的背景将被有效删除。
我想要这样,如果我剪裁一个形状,它基本上会在最上层打一个洞并移除形状,而不是背景。这可能吗?我也愿意接受 SVG 解决方案,但我是 SVG 新手,所以请善待 :)
基本上,在下面的代码中,我有一个绝对位于红色正方形内的蓝色正方形,并且希望能够从蓝色正方形中冲压出一个形状,因此下面的红色层显示了该形状曾经所在的位置。实际上会有一个图像作为背景层,所以我不能接受模仿我想要的但实际上并没有打出形状的伪效果。
任何帮助都会很棒!
codepen: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>
【问题讨论】:
所以说清楚,你想在内盒里面打个洞来看看背景? @TemaniAfif 是的,正确的。 【参考方案1】:您可以将图像上方放在蓝色部分并在其上应用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>
另一个想法是考虑多个背景,您将获得比剪辑路径更好的支持并且代码更少:
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 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" 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 fill="white"/> <polygon points="20,20 20,180 180,100 " fill="black"/></mask></defs><rect fill="blue" mask="url(%23hole)" /></svg>');
<div id="box">
<div id="innerbox"></div>
</div>
更新 3(我在 2020 年推荐的内容)
mask-composite
mask-composite
可以使用CSS mask来获得你想要的效果
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>
【讨论】:
这很聪明。但我确实需要在蓝色层上打一个洞,因为背景要么是图像,要么是视频,但也会有文字。我需要的是你刚刚完成的效果,但是蓝色层的不透明度为 0.9,并让图像或视频填充整个容器,但 100% 清楚形状在哪里。我不确定这是否可行。 @TheChewy 好的,假设你想要剪辑路径的不透明度:) @TheChewy 再次检查,我添加了另一个想法 :) 是的,这将适用于图像。我不确定如果客户沿着视频路线走下去(他们可能会这样做),我是否能侥幸逃脱,因为这意味着加载两个大型视频元素,这意味着对性能的影响很大。我将使用 SVG 覆盖发布一个单独的问题,我已经用它打了一个洞,看看是否可以响应地对齐它。我非常感谢您的帮助,并将考虑上述基于图像的解决方案。 @TheChewy 好的,我也会讨论这个问题:)【参考方案2】:这在 Google 上排名很高,但答案并没有解决我的问题 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 放在图像内部,但您也可以将其放在外部。但是,请确保您可以使用 limited browser support of clip-path。
【讨论】:
以上是关于创建反向剪辑路径 - CSS 或 SVG的主要内容,如果未能解决你的问题,请参考以下文章
为啥带有 SVG 的 CSS 剪辑路径在 Safari 中不起作用?
当引用为 css 剪辑路径属性时,SVG 剪辑路径的位置不正确