Is there a commonly supported way to make a skewed "frosted glass" effect in CSS/SVG?
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>
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>