Is there a commonly supported way to make a skewed “frosted glass” effect in CSS/SVG?

杀马特。学长 韩版系。学妹 提交于 2020-04-12 20:16:57

问题


I'm looking to make a website splash page. The page will have one background that will be cut off on the left side with a slanted div, say at a constant 110 degrees from the horizontal (or equivalent, keep reading). This div will blur the background behind it and will allow for content to be put on it, like text. See the YouTube Brand Resources page: instead of having a plain white background on the left, I would like that to blur the background picture that sits underneath it.

I've not yet found a way to put all of the information I've found together in a way that works and is supported by most browsers. For example, I recently tried a skewed div that shared a background with the parent container, like this post asked about, but CSS clip paths aren't commonly supported yet, and a white div won't cut it for my use case (to be clear, this solution ends with a skewed background image).

Using SVG clip paths and filters (see below) gets me close, but as you can see, I don't know how to make sure the image and the SVG fills the screen and lines up with the background behind it.

<!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

Any ideas?


回答1:


You can consider skew transform without the need of clip-path. here is a basic example where the trick is to specify the correct value of background-position to create the illusion of one image.

.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>

In case you want the skew to be responsive you can add a small JS code to adjust the angle and always cover half the iamge:

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>



回答2:


You can also make it all in a single <svg> image, using a <pattern> element to fill half a triangle with the image, and apply your filter on it.

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>


来源:https://stackoverflow.com/questions/54018409/is-there-a-commonly-supported-way-to-make-a-skewed-frosted-glass-effect-in-css

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!