将具有混合(固定和百分比)值的 CSS 剪辑路径转换为 SVG 剪辑路径
Transform CSS clip-path with mixed (fixed and percentage) values to SVG clip-path
我有一张带有渐变和剪角的卡片图像,使用 clip-path
:
.card {
width: 200px;
height: 200px;
background: linear-gradient(to bottom, blue, green);
clip-path: polygon(20px 0, 100% 0, 100% 100%, 0 100%, 0 20px);
}
<div class="card"></div>
无论卡片大小如何,剪角必须具有固定大小,所以我使用像素来剪角。
但是 clip-path
目前还没有最好的浏览器支持,所以我尝试将这个 HTML 和 CSS 转换为 SVG。
.container {
width: 200px;
height: 200px;
}
<div class="container">
<svg viewBox="0 0 100 100" clip-path="url(#myClip)">
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(0,255,0);stop-opacity:1" />
</linearGradient>
</defs>
<polygon points="20,0 100,0 100,100 0,100 0,20" fill="url(#grad1)" />
</svg>
</div>
但问题是无论卡片大小如何,我都无法使这个剪角具有固定大小。
如果渐变总是底部或顶部方向,您可以考虑使用倾斜变换和伪元素的技巧,如下所示:
.card {
width: 200px;
height: 200px;
padding-top: 20px;
background-image: linear-gradient(to bottom, blue,red,yellow,green);
background-clip:content-box;
background-size:100% 200px; /*same as height*/
position: relative;
z-index:0;
overflow:hidden;
box-sizing: border-box;
display:inline-block;
}
.card:before {
content: "";
position: absolute;
z-index:-1;
top: 0;
padding: inherit;
left: 0;
right: 0;
background-image: inherit;
background-size:inherit;
transform: skewX(-45deg);
transform-origin: left bottom;
}
body {
background:pink;
}
<div class="card"></div>
<div class="card" style="background-image:linear-gradient(to top,white,purple,green ,red 90%, blue"></div>
对于任何渐变或任何图像,您可以添加额外的元素来纠正倾斜:
.card {
width: 200px;
height: 200px;
padding-top: 20px;
background-image: linear-gradient(to bottom, blue,red,yellow,green);
background-clip:content-box;
background-size:auto 200px; /*same as height*/
position: relative;
z-index:0;
overflow:hidden;
box-sizing: border-box;
display:inline-block;
}
.image {
background-size:cover; /*less restriction when it comes to image*/
}
.card span,
.card span::before {
position: absolute;
top: 0;
left: 0;
right: 0;
background-image: inherit;
background-size:inherit;
transform-origin: left bottom;
}
.card span {
z-index:-1;
padding: inherit;
transform: skewX(-45deg);
overflow:hidden;
}
.card span:before {
content:"";
bottom:0;
transform: skewX(45deg);
}
body {
background:pink;
}
<div class="card">
<span></span>
</div>
<div class="card" style="background-image:linear-gradient(60deg,white,purple,green ,red 90%, blue)">
<span></span>
</div>
<div class="card image" style="background-image:url(https://picsum.photos/400/400?image=0)">
<span></span>
</div>
<div class="card image" style="background-image:url(https://picsum.photos/600/600?image=15)">
<span></span>
</div>
要保持固定大小,您不能在 SVG 上使用 viewBox
。只需夹住您需要的角,让其他角延伸很长一段距离,以便覆盖您可能需要的任何尺寸。在下面的示例中,我将剪切路径延伸到 (10000,10000)。
这里我们将渐变应用于 100% x 100% <rect>
。这是为了让渐变始终缩放以适合屏幕。然后我们将剪辑路径应用到矩形以获得缺口。
html, body {
height: 100%;
}
.container {
width: 50%;
height: 50%;
}
<div class="container">
<svg width="100%" height="100%">
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(0,255,0);stop-opacity:1" />
</linearGradient>
<clipPath id="clip1">
<polygon points="20,0 10000,0 10000,10000 0,10000 0,20"/>
</clipPath>
</defs>
<rect width="100%" height="100%" fill="url(#grad1)" clip-path="url(#clip1)"/>
</svg>
</div>
在 Stack Overflow in Russian using SVG mask
的帮助下,我的解决方案是这样
.container {
width: 200px;
height: 200px;
}
svg {
width: 100%;
height: 100%;
}
<div class="container">
<svg>
<defs>
<mask id="triangle-clip">
<rect x="0" y="0" width="100%" height="100%" fill="#fff" />
<path d="M0,20 v-20 h20 z" fill="#000" />
</mask>
<linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(0,255,0);stop-opacity:1" />
</linearGradient>
</defs>
<rect width="100%" height="100%" fill="url(#grad1)" mask="url(#triangle-clip)" />
</svg>
</div>
我有一张带有渐变和剪角的卡片图像,使用 clip-path
:
.card {
width: 200px;
height: 200px;
background: linear-gradient(to bottom, blue, green);
clip-path: polygon(20px 0, 100% 0, 100% 100%, 0 100%, 0 20px);
}
<div class="card"></div>
无论卡片大小如何,剪角必须具有固定大小,所以我使用像素来剪角。
但是 clip-path
目前还没有最好的浏览器支持,所以我尝试将这个 HTML 和 CSS 转换为 SVG。
.container {
width: 200px;
height: 200px;
}
<div class="container">
<svg viewBox="0 0 100 100" clip-path="url(#myClip)">
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(0,255,0);stop-opacity:1" />
</linearGradient>
</defs>
<polygon points="20,0 100,0 100,100 0,100 0,20" fill="url(#grad1)" />
</svg>
</div>
但问题是无论卡片大小如何,我都无法使这个剪角具有固定大小。
如果渐变总是底部或顶部方向,您可以考虑使用倾斜变换和伪元素的技巧,如下所示:
.card {
width: 200px;
height: 200px;
padding-top: 20px;
background-image: linear-gradient(to bottom, blue,red,yellow,green);
background-clip:content-box;
background-size:100% 200px; /*same as height*/
position: relative;
z-index:0;
overflow:hidden;
box-sizing: border-box;
display:inline-block;
}
.card:before {
content: "";
position: absolute;
z-index:-1;
top: 0;
padding: inherit;
left: 0;
right: 0;
background-image: inherit;
background-size:inherit;
transform: skewX(-45deg);
transform-origin: left bottom;
}
body {
background:pink;
}
<div class="card"></div>
<div class="card" style="background-image:linear-gradient(to top,white,purple,green ,red 90%, blue"></div>
对于任何渐变或任何图像,您可以添加额外的元素来纠正倾斜:
.card {
width: 200px;
height: 200px;
padding-top: 20px;
background-image: linear-gradient(to bottom, blue,red,yellow,green);
background-clip:content-box;
background-size:auto 200px; /*same as height*/
position: relative;
z-index:0;
overflow:hidden;
box-sizing: border-box;
display:inline-block;
}
.image {
background-size:cover; /*less restriction when it comes to image*/
}
.card span,
.card span::before {
position: absolute;
top: 0;
left: 0;
right: 0;
background-image: inherit;
background-size:inherit;
transform-origin: left bottom;
}
.card span {
z-index:-1;
padding: inherit;
transform: skewX(-45deg);
overflow:hidden;
}
.card span:before {
content:"";
bottom:0;
transform: skewX(45deg);
}
body {
background:pink;
}
<div class="card">
<span></span>
</div>
<div class="card" style="background-image:linear-gradient(60deg,white,purple,green ,red 90%, blue)">
<span></span>
</div>
<div class="card image" style="background-image:url(https://picsum.photos/400/400?image=0)">
<span></span>
</div>
<div class="card image" style="background-image:url(https://picsum.photos/600/600?image=15)">
<span></span>
</div>
要保持固定大小,您不能在 SVG 上使用 viewBox
。只需夹住您需要的角,让其他角延伸很长一段距离,以便覆盖您可能需要的任何尺寸。在下面的示例中,我将剪切路径延伸到 (10000,10000)。
这里我们将渐变应用于 100% x 100% <rect>
。这是为了让渐变始终缩放以适合屏幕。然后我们将剪辑路径应用到矩形以获得缺口。
html, body {
height: 100%;
}
.container {
width: 50%;
height: 50%;
}
<div class="container">
<svg width="100%" height="100%">
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(0,255,0);stop-opacity:1" />
</linearGradient>
<clipPath id="clip1">
<polygon points="20,0 10000,0 10000,10000 0,10000 0,20"/>
</clipPath>
</defs>
<rect width="100%" height="100%" fill="url(#grad1)" clip-path="url(#clip1)"/>
</svg>
</div>
在 Stack Overflow in Russian using SVG mask
的帮助下,我的解决方案是这样
.container {
width: 200px;
height: 200px;
}
svg {
width: 100%;
height: 100%;
}
<div class="container">
<svg>
<defs>
<mask id="triangle-clip">
<rect x="0" y="0" width="100%" height="100%" fill="#fff" />
<path d="M0,20 v-20 h20 z" fill="#000" />
</mask>
<linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(0,255,0);stop-opacity:1" />
</linearGradient>
</defs>
<rect width="100%" height="100%" fill="url(#grad1)" mask="url(#triangle-clip)" />
</svg>
</div>