Can you CSS Blur based on a gradient mask? - css

Can you CSS Blur based on a gradient mask?
Something similar to this effect, http://www.imagemagick.org/Usage/mapping/#blur?

This can help you http://codepen.io/iamvdo/pen/xECmI
.effet{
width: 400px; height: 300px;
margin: 0 auto 50px auto;
box-shadow: 0 1px 5px rgba(0,0,0,.5);
}
.effet img{
position: absolute;
}
.filtre--r{
-webkit-mask: -webkit-radial-gradient( center, closest-side, transparent 30%, black 80%);
-webkit-mask: radial-gradient( closest-side at center, transparent 50%, black 110%);
-webkit-filter: blur(5px);
mask: url('#mask-radial');
filter: url('#filtre1');
}
.filtre--l{
-webkit-mask: -webkit-linear-gradient(black, transparent 30%, black);
-webkit-mask: linear-gradient(black, transparent 30%, black);
-webkit-filter: blur(3px);
mask: url('#mask-linear');
filter: url('#filtre2');
}
.filtre:hover{
-webkit-mask: none;
-webkit-filter: none;
mask: none;
filter: none;
}
p{
text-align: center;
color: rgba(0,0,0,.6);
margin: 1em;
}
p a{
color: rgba(0,0,0,.6);
}
<p><strong>Radial</strong> progressive blur</p>
<div class="effet">
<img src="http://css3create.com/squelettes/images/articles/flou-localise-1.jpg" alt="" />
<img class="filtre filtre--r" src="http://css3create.com/squelettes/images/articles/flou-localise-1.jpg" alt="" />
</div>
<p><strong>Linear</strong> progressive blur</p>
<div class="effet">
<img src="http://css3create.com/squelettes/images/articles/flou-localise-2.jpg" alt="" />
<img class="filtre filtre--l" src="http://css3create.com/squelettes/images/articles/flou-localise-2.jpg" alt="" />
</div>
<p>Hover over images to see without blur</p>
<p>Next demo: iOS 7 background blur with CSS</p>
<svg height="0">
<defs>
<mask id="mask-radial">
<rect width="400" height="300" fill="url(#g1)"></rect>
<radialGradient id="g1" cx="50%" cy="50%" r="50%">
<stop stop-color="black" offset="50%"/>
<stop stop-color="white" offset="110%"/>
</radialGradient>
</mask>
<mask id="mask-linear">
<rect width="400" height="300" fill="url(#l1)"></rect>
<linearGradient id="l1" x1="0" y1="0" x2="0" y2="1">
<stop stop-color="white" offset="0%"/>
<stop stop-color="black" offset="30%"/>
<stop stop-color="white" offset="100%"/>
</linearGradient>
</mask>
<filter id="filtre1">
<feGaussianBlur in="SourceGraphic" stdDeviation="5"/>
</filter>
<filter id="filtre2">
<feGaussianBlur in="SourceGraphic" stdDeviation="3"/>
</filter>
</defs>
</svg>

[EDIT] As of October 2022, it is now possible in all the modern browsers.
Yes you can, but at the moment the backdrop blur is not supported on all the browsers.
Here is a simple example working on Chrome and Safari but not Firefox (because of the lack of backdrop-filter support).
https://codepen.io/antoniandre/pen/vYpWQXd?editors=0100
* {margin: 0}
body {
height: 100vh;
background-image: url("https://images.unsplash.com/photo-1501854140801-50d01698950b?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2600&q=80");
background-size: cover;
&:after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
opacity: 0;
backdrop-filter: blur(20px);
mask: linear-gradient(transparent, black 60%);
transition: 1s;
}
&:hover:after {opacity: 1;}
}

You might nowadays simply use:
backdrop-filter: blur(4px)
All modern browsers except Firefox support it.

Related

How can I obtain any custom shape using clip-path css propery?

I am trying to obtain the shape using clip-path polygon property and it's not working as expected the shape I want to make is given below
I tried the following code but it is giving the corners not round shape
`
#header {
width: 100%;
height: 95vh;
background: linear-gradient(110deg, #2186eb, #37dce2);
clip-path: polygon(100% 0, 100% 51%, 65% 88%, 57% 96%, 50% 100%, 43% 96%, 24% 87%, 0 51%, 0 0);
}
`
You won't be able to have a curvature with polygon. You can consider a mask with radial-gradient for the curvature in addition to the clip-path:
.box {
height: 95vh;
background: linear-gradient(110deg, #2186eb, #37dce2);
clip-path: polygon(0 0,0 30%, 50% 100%, 100% 30%,100% 0);
-webkit-mask:
linear-gradient(#fff,#fff) top/100% 70% no-repeat,
radial-gradient(44% 100% at top,#fff 86%,transparent 86.5%);
}
body {
margin:0;
background:pink;
}
<div class="box">
</div>
Anther idea using border-radius and transformation:
.box {
height: 95vh;
position:relative;
overflow:hidden;
}
.box::before {
content:"";
position:absolute;
width:100vmax;
height:100vmax;
top:50%;
left:50%;
transform:translate(-50%,-100%) rotate(45deg);
border-bottom-right-radius:100px;
background: linear-gradient(75deg, #2186eb, #37dce2);
}
body {
margin:0;
background:pink;
}
<div class="box">
</div>
SVG solution
For the solution used SVG clipPath was used which is well: supported by browsers
body {
margin:0;
padding:0;
background-image:url(https://i.stack.imgur.com/Nlhed.jpg);
background-repeat: no-repeat;
background-size:cover;
}
.container {
width:100vw;
height:100vh;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 758 474" preserveAspectRatio="xMinYMin meet" style="border:0px solid red;" >
<defs>
<clipPath id="cp">
<path d="m0 0 760.2-1v227c0 0-208.4 132.8-319.3 196.8-11.6 6.7-24.9 10.6-38.2 13.1-10.9 2-22.1 1.9-33.1 1-10.9-0.8-23-3-32.1-6C320.5 425.2-1 223.9-1 223.9Z"/>
</clipPath>
</defs>
<image clip-path="url(#cp)" xlink:href="https://i.stack.imgur.com/iCkE2.png" width="100%" height="100%" />
</svg>
Animation option
The cropped image slides out after clicking, and when clicked again, it goes back
var clip = document.getElementById("svg1"),
forward = document.getElementById("forward"),
back = document.getElementById("back")
let flag = true;
clip.addEventListener('click', function() {
if (flag == true) {
forward.beginElement();
flag = false;
} else {
back.beginElement();
flag = true;
}
});
body {
margin:0;
padding:0;
background-image:url(https://i.stack.imgur.com/Nlhed.jpg);
background-repeat: no-repeat;
background-size:cover;
}
.container {
width:100vw;
height:100vh;
}
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 758 474" preserveAspectRatio="xMinYMin meet" style="border:0px solid red;" >
<defs>
<clipPath id="cp">
<path transform="translate(0,-380)" d="m0 0 760.2-1v227c0 0-208.4 132.8-319.3 196.8-11.6 6.7-24.9 10.6-38.2 13.1-10.9 2-22.1 1.9-33.1 1-10.9-0.8-23-3-32.1-6C320.5 425.2-1 223.9-1 223.9Z">
<animateTransform id="forward" attributeName="transform" type="translate" begin="indefinite" dur="3s" values="0 -380;0,0" fill="freeze" />
<animateTransform id="back" attributeName="transform" type="translate" begin="indefinite" dur="3s" values="0,0;0,-380" fill="freeze" />
</path>
</clipPath>
</defs>
<image clip-path="url(#cp)" xlink:href="https://i.stack.imgur.com/iCkE2.png" width="100%" height="100%" />
</svg>

Border gradient from once color to another uing css [duplicate]

I have a problem with CSS3. I don't know how to make a diagonal round gradient border like that:
I found something like this:
.box {
width: 250px;
height: 250px;
margin: auto;
background: #eee;
border: 20px solid transparent;
-moz-border-image: -moz-linear-gradient(top left, #3acfd5 0%, #3a4ed5 100%);
-webkit-border-image: -webkit-linear-gradient(top left, #3acfd5 0%, #3a4ed5 100%);
border-image: linear-gradient(to bottom right, #3acfd5 0%, #3a4ed5 100%);
border-image-slice: 1;
}
<div class="box"></div>
But unfortunately this works only with squares.
Any help would be appreciated.
Conical gradient is a gradient which goes along the circular arc around a center. This is what we see in color wheels. As Paulie_D had noted, these are currently not possible with CSS but Lea Verou has developed a polyfill for it.
Having said that, what you are looking for doesn't seem to be a conical gradient, it is normal angled linear gradient but applied only to the borders.
This cannot be achieved through CSS border-image property because of how it is intended to work as per specs.
A box's backgrounds, but not its border-image, are clipped to the appropriate curve
If the center portion of the circle is a solid color then the approach mentioned in Vitorino's answer can be used. If it is not a solid color (that is, the page background is a gradient or an image which needs to show through) then it would not help. The following approaches can be used for that case.
Using Mask Image:
This approach uses a circular mask image to mask the inner portion of the circle. This makes it look as though only the border has the gradient applied to it. The drawback is that this feature is currently supported only in Webkit powered browsers.
.border-gradient-mask {
height: 200px;
width: 200px;
border-radius: 50%;
background-image: linear-gradient(to bottom left, #7B73A4 0%, #150E5E 100%);
-webkit-mask-image: radial-gradient(circle at center, transparent 57%, white 58%);
mask-image: radial-gradient(circle at center, transparent 57%, white 58%);
}
body {
background: radial-gradient(circle at center, sandybrown, chocolate);
}
<div class="border-gradient-mask"></div>
Using SVG Shape or Mask:
The other approach is to use SVG circle element to create the circle and then assign the gradient to the stroke property. The gradient also has a gradientTransform applied to it because that is the only way to produce angled linear gradients with SVG.
.border-gradient-svg {
position: relative;
height: 200px;
width: 200px;
border-radius: 50%;
}
.border-gradient-svg svg {
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
.border-gradient-svg circle {
fill: transparent;
stroke: url(#grad);
stroke-width: 8;
}
body {
background: radial-gradient(circle at center, sandybrown, chocolate);
}
<div class="border-gradient-svg">
<svg viewBox="0 0 100 100">
<defs>
<linearGradient id="grad" gradientUnits="objectBoundingBox" gradientTransform="rotate(135 0.5 0.5)">
<stop offset="0%" stop-color="#7B73A4" />
<stop offset="100%" stop-color="#150E5E" />
</linearGradient>
</defs>
<circle r="46" cx="50" cy="50" />
</svg>
</div>
The same can be achieved by using SVG mask also. All that is needed is to create a mask with two circle elements, fill the larger circle with white, smaller circle with black and then apply the mask to our original circle element. The area occupied by smaller circle (with black fill) will be transparent.
.border-gradient-svg {
position: relative;
height: 200px;
width: 200px;
border-radius: 50%;
}
.border-gradient-svg svg {
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
.border-gradient-svg .grad-border {
fill: url(#grad);
mask: url(#masker);
}
body {
background: radial-gradient(circle at center, sandybrown, chocolate);
}
<div class="border-gradient-svg">
<svg viewBox="0 0 100 100">
<defs>
<linearGradient id="grad" gradientUnits="objectBoundingBox" gradientTransform="rotate(135 0.5 0.5)">
<stop offset="0%" stop-color="#7B73A4" />
<stop offset="100%" stop-color="#150E5E" />
</linearGradient>
<mask id="masker" x="0" y="0" width="100" height="100">
<circle r="50" cx="50" cy="50" fill="#fff" />
<circle r="42" cx="50" cy="50" fill="#000" />
</mask>
</defs>
<circle r="50" cx="50" cy="50" class="grad-border"/>
</svg>
</div>
Using Clip Path:
Another approach to creating this would be to use a clip-path (with inline SVG) with clip-rule set to evenodd. Advantage of clip path solution over the others is that this will trigger hover effects only while hovering on filled area (and not the transparent area). The drawback is that IE doesn't support clip paths (even with SVG).
.border-gradient-clip {
height: 200px;
width: 200px;
border-radius: 50%;
background-image: linear-gradient(to bottom left, #7B73A4 0%, #150E5E 100%);
-webkit-clip-path: url(#clipper);
clip-path: url(#clipper);
}
body {
background: radial-gradient(circle at center, sandybrown, chocolate);
}
<svg width="0" height="0">
<defs>
<clipPath id="clipper" clipPathUnits="objectBoundingBox">
<path d="M0,0.5 a0.5,0.5 0 1,0 1,0 a0.5,0.5 0 1,0 -1,0z M0.08,0.5 a0.42,0.42 0 1,0 0.84,0 a0.42,0.42 0 1,0 -0.84,0z" clip-rule="evenodd" />
</clipPath>
</defs>
</svg>
<div class="border-gradient-clip"></div>
You can try something like this i have used a pseudo element with -ve z-index
Note: the background is not transparent as i have used a background-color for inner element
.box {
width: 250px;
height: 250px;
position: relative;
margin: auto;
margin: 30px;
border-radius: 50%;
background: #fff;
}
.box:after {
content: '';
position: absolute;
top: -15px;
bottom: -15px;
right: -15px;
left: -15px;
background-image: linear-gradient(to bottom left, #7B73A4 0%, #150E5E 100%);
z-index: -1;
border-radius: inherit;
}
<div class="box"></div>

CSS shadow on SVG shape only, not entire document

Is it possible to get CSS shadow on the SVG shape only, not entire document? Ie. around the blue arrow at:
a:after {
background: #fff;
box-shadow: 0 0 10px rgba(0, 0, 0, .50);
-webkit-filter: drop-shadow(5px 5px 5px #222);
filter: drop-shadow(5px 5px 5px #222);
content:"";
position: absolute;
background-image: url(http://www.domblogger.net/buttons/play.svg);
background-repeat: no-repeat;
background-position: 0;
height: 350px;
width: 350px;
}
Play
Yes it is possible but you will have to apply a filter on the original svg element(use), not through CSS.
Change the file at http://www.domblogger.net/buttons/play.svg to:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="400" viewBox="0 0 400 400" version="1.1">
<defs>
<polygon id="play" fill="rgb(0,0,200)" fill-opacity="0.6" points="0,0 0,350 300,175" />
<filter id="d" width="120%" height="120%">
<feGaussianBlur in="SourceAlpha" stdDeviation="5" />
<feOffset dx="5" dy="5" result="offsetblur" />
<feComponentTransfer>
<feFuncA type="linear" slope="0.5" />
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<g>
<use filter="url(#d)" x="55" y="25" xlink:href="#play" />
</g>
</svg>
If you mean that you want the dropshadow only on the arrow shape, then don't set the background color to white (first line of your a:after stylerule).
a:after {
-webkit-filter: drop-shadow(5px 5px 5px #222);
filter: drop-shadow(5px 5px 5px #222);
content:"";
position: absolute;
background-image: url(http://www.domblogger.net/buttons/play.svg);
background-repeat: no-repeat;
background-position: 0;
height: 350px;
width: 350px;
}
Play

Animation of multiple background image positions via keyframes works in Chrome & Safari but not Firefox

The goal is to create an infinitely scrolling, two-layer parallax background. The effect works perfectly in Mac Chrome and Safari, but it stutters in Firefox. Any ideas why? Thanks!
<style>
body {
background-color: black;
}
#container {
bottom: 0;
left: 0;
position: absolute;
right: 0;
top: 0;
}
#-webkit-keyframes scroll {
100% {
background-position: 0 0;
}
}
#keyframes scroll {
100% {
background-position: 0 0;
}
}
.bg1 {
-webkit-animation: scroll 2.5s linear infinite;
animation: scroll 2.5s linear infinite;
background-image: url(path/to/image);
background-position: 0 -156px;
background-size: 128px 156px;
height: 100%;
opacity: 0.5;
position: fixed;
width: 100%;
}
.bg2 {
-webkit-animation: scroll 5s linear infinite;
animation: scroll 5s linear infinite;
background-image: url(path/to/image);
background-position: 0 -78px;
background-size: 64px 78px;
height: 100%;
opacity: 0.25;
position: fixed;
width: 100%;
}
</style>
<body>
<div id="container">
<div id="bg1" class="bg1"></div>
<div id="bg2" class="bg2"></div>
</div>
</body>
You don't have any -moz- properties in your code.
-webkit- is supported in chrome and safari both.
But for firefox you should have -moz-prefix in some old versions.
I was able to get around Firefox's engine not being to keep up with tandem animations of full-window divs of repeating backgrounds…by instead switching to two animated, patterned, full-window SVGs.
So rather than adding keyframe animations to divs in my CSS, I instead used the following markup in my HTML:
<svg id="parallax2" width="100%" height="200%" style="display: none;">
<defs>
<pattern id="pattern2" patternUnits="userSpaceOnUse" height="100" width="100">
<image x="-40" y="-40" height="100" width="100" xlink:href="path/to/image"></image>
</pattern>
</defs>
<rect width="100%" height="200%" fill="url(#pattern2)">
<animateTransform
attributeName="transform"
type="translate"
from="0 -50"
to="0 50"
dur="3750ms"
repeatCount="indefinite"
/>
</rect>
</svg>
<svg id="parallax1" width="100%" height="200%" style="display: none;">
<defs>
<pattern id="pattern1" patternUnits="userSpaceOnUse" height="200" width="200">
<image x="-40" y="-40" height="200" width="200" xlink:href="path/to/image"></image>
</pattern>
</defs>
<rect width="100%" height="200%" fill="url(#pattern1)">
<animateTransform
attributeName="transform"
type="translate"
from="0 -100"
to="0 100"
dur="3750ms"
repeatCount="indefinite"
/>
</rect>
</svg>

image opacity from 0 to 1 with css

I want my images to look like following:
The bottom part of the image is transparent, and to the top its getting to opacity 1.
I can do this effect with a color, with linear gradient:
-webkit-linear-gradient(black, transparent);
But is it possible with images too?
The newest and coolest way I know is using HTML 5 mask.
It goes like this:
CSS:
.masked
{
mask: url(#m1);
}
HTML 5:
<svg width="0" height="0">
<defs>
<linearGradient id="gradient" x1="0" y1="0" x2 ="0" y2="100%">
<stop stop-color="white" offset="0"/>
<stop stop-color="black" offset="1"/>
</linearGradient>
<mask id="masking" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">
<rect y="0.1" width="1" height="0.9" fill="url(#gradient)" />
</mask>
</defs>
</svg>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="500" height="350">
<image xlink:href="http://upload.wikimedia.org/wikipedia/commons/4/4d/Iss007e10807_darker.jpg"
width="500" height="350" class="masked"></image>
</svg>
jsFiddle Demo
For further reading:
Applying SVG effects to HTML content (Live example)
CSS Masking
Create Vector Masks using the HTML5 Canvas
My attempts with CSS :)
Codepen example: http://cdpn.io/hzBav
CSS (Update with fadeout)
figure {
display: inline-block;
position: relative;
}
.overlay {
display: block;
height: 300px;
position: absolute;
width: 300px;
background-image: -moz-linear-gradient(
rgba(0, 0, 0, 0.8) 0%, rgba(255, 255, 255, 0) 85%
);
}
.overlay:after {
content: '';
display: block;
height: 300px;
width: 300px;
background-image: -moz-linear-gradient(
rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 100%
);
}
HTML
<figure>
<div class='overlay'></div>
<img src='http://placekitten.com/300/300' />
</figure>
Update based on comments.

Resources