CSS/SVG中是否有一种常见的方法来制作倾斜的“磨砂玻璃”效果?

7
我想制作一个网站启动页面。该页面将有一个背景图,左侧将以斜角状切割一块区域,与水平线保持110度倾斜(或相当的角度,继续阅读)。这个斜角状的区域将会模糊背景,并允许在其上添加内容,如文本。参见YouTube品牌资源页面:不同于左侧纯白背景图,我想要它可以使其下方的背景图片变得模糊。
但我还没有找到一种方法可以将我发现的所有信息结合在一起,以便能够适应大多数浏览器并且可行。例如,最近我尝试了一个共享父容器背景的斜角状区域,就像这篇文章中提到的,但CSS裁剪路径目前还不被广泛支持,而一个白色区域对于我的用例来说不够好(明确一下,这种解决方案的结束点是一个斜角背景图)。
使用SVG裁剪路径和滤镜(见下文)可以让我接近目标,但是你可以看到,我不知道如何确保图像和SVG填充屏幕并与其背景对齐。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Page</title>
</head>
<body>
<div class="splash">
    <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none">
        <filter id="blur" x="0" y="0">
            <feGaussianBlur stdDeviation="1"></feGaussianBlur>
        </filter>
        <clipPath id="clip">
            <polygon points="0,0 100,100 0,100"></polygon>
        </clipPath>
        <image clip-path="url('#clip')" filter="url('#blur')" x="0" y="0" width="100" height="100" xlink:href="https://cdn.pixabay.com/photo/2018/11/17/22/15/tree-3822149_960_720.jpg"></image>
    </svg>
</div>
</body>
</html>

Sass:

html, body
  position: relative

  margin: 0
  overflow-x: hidden
  height: 100%

.splash
  position: absolute
  width: 100%
  height: 100%
  overflow: hidden

  background-image: url("https://cdn.pixabay.com/photo/2018/11/17/22/15/tree-3822149_960_720.jpg")
  background-size: cover
  background-repeat: no-repeat
  background-color: lightgrey
  background-attachment: fixed

  svg
    position: absolute
    width: inherit
    height: inherit

有什么想法吗?

我不确定如何让这个问题更具体。你是否希望我关闭这个问题,并提出多个变体,例如“如何使用{SVG、CSS、HTML、clip-path、背景图像}制作一个全屏闪屏页面,其中一个角度为110度的倾斜div将其分成两半?”并且有些可能是错误的,因为我不知道如何做?对我来说,在一个问题中询问似乎是更好的选择。 - Pheric
1
我不认为这个问题太宽泛,但我希望看到使用编译后的CSS而不是Sass,除非你的问题特别是如何在Sass中实现。 - TylerH
2个回答

6
您可以考虑使用倾斜变换而无需使用clip-path。以下是一个基本示例,其中的技巧是指定background-position的正确值以创建一个图像的幻觉。

.box {
  height:300px;
  background-image:url(https://picsum.photos/600/800?image=1069);
  background-position:left center;
  background-size:cover;
  position:relative;
  overflow:hidden;
}
.skew,
.skew::before{
  position:absolute;
  top:0;
  left:0;
  right:0;
  bottom:0;
  transform-origin:top left;
  transform:skewY(30deg);
  overflow:hidden;
  background-image:inherit;
  background-position:inherit;
  background-size:0 0;
}
.skew::before {
  content:"";
  transform:skewY(-30deg);
  filter:blur(10px);
  background-size:cover;
}

/*to illustrate the separation*/
.skew {
  border-top:1px solid;
}
/**/
.container {
  position:relative;
  z-index:1;
  margin-top:150px;
  padding-left:50px;
}

body {
 margin:0;
}
<div class="box">
  <div class="skew"></div>
  <div class="container">
    <h1>some text</h1>
    <p>Lorem ipsum</p>
  </div>
</div>

<div class="box" style="background-image:url(https://picsum.photos/600/800?image=3)">
  <div class="skew"></div>
  <div class="container">
    <h1>some text</h1>
    <p>Lorem ipsum</p>
  </div>
</div>

如果您希望倾斜角度能够响应式地调整,您可以添加一小段JS代码来调整角度,始终覆盖图像的一半:

var w = window.innerWidth;
var h = 300; /*the height of the box*/
document.querySelector('.box .skew').style.transform="skewY("+(Math.atan(h/w)*180/Math.PI )+"deg)";
document.querySelector('.box .skew span').style.transform="skewY(-"+(Math.atan(h/w)*180/Math.PI )+"deg)";

window.onresize = function(event) {
    w = window.innerWidth;
    document.querySelector('.box .skew').style.transform="skewY("+(Math.atan(h/w)*180/Math.PI )+"deg)";
    document.querySelector('.box .skew span').style.transform="skewY(-"+(Math.atan(h/w)*180/Math.PI )+"deg)";
};
.box {
  height:300px;
  background-image:url(https://picsum.photos/600/800?image=1069);
  background-position:left center;
  background-size:cover;
  position:relative;
  overflow:hidden;
}
.skew,
.skew span{
  position:absolute;
  top:0;
  left:0;
  right:0;
  bottom:0;
  transform-origin:top left;
  transform:skewY(30deg);
  overflow:hidden;
  background-image:inherit;
  background-position:inherit;
  background-size:0 0;
}
.skew span{
  transform:skewY(-30deg);
  filter:blur(10px);
  background-size:cover;
}
/*to illustrate the separation*/
.skew {
  border-top:1px solid;
}
/**/
.container {
  position:relative;
  z-index:1;
  margin-top:150px;
  padding-left:50px;
}

body {
 margin:0;
}
<div class="box">
  <div class="skew"><span></span></div>
  <div class="container">
    <h1>some text</h1>
    <p>Lorem ipsum</p>
  </div>
</div>


3
你也可以将所有内容放在一个单独的<svg>图像中,使用<pattern>元素填充三角形的一半,并对其应用过滤器。

svg {
  width: 100vw;
  height: 200px;
  position: absolute;
  top: 0;
}

.container {
  position: relative;
  z-index: 1;
  margin-top: 100px;
  padding-left: 50px;
}
<svg width="1024" height="200" viewBox="0 0 1024 200" preserveAspectRatio="none">
  <defs>
    <pattern id="pat" viewBox="0 0 1024 200" width="100%" height="100%">
      <image xlink:href="https://picsum.photos/1024/200?image=1029" width="1024" height="200"/>
    </pattern>
    <filter id="blur">
      <feGaussianBlur in="SourceGraphic" stdDeviation="10" />
    </filter>
  </defs>
  <!-- background no filter -->
  <rect width="1024" height="200" fill="url(#pat)"/>
  <!-- foreground triangle, blurred -->
  <path d="M0,0L1024,200H0Z" fill="url(#pat)" filter="url(#blur)"/>
</svg>
<div class="container">
  <h1>some text</h1>
  <p>Lorem ipsum</p>
</div>


如果我不知道图像的尺寸怎么办? - Pheric
@Pheric 我真的看不出你为什么不这样做,但是在加载HTML <img>元素中的图像后,您可以从JavaScript构建该SVG。 - Kaiido
如果我在幻灯片或其他地方有多个分辨率不同的图片,它就无法正常工作。 - Pheric

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接