Css3 Filter: Drop-Shadow Spread Property Alternatives

CSS3 filter: drop-shadow spread property alternatives

Well, I figured out how to replace the non-functioning spread property using SVG filters. Big thanks to Michael Mullany though his answer wasn't 100% what I need. Here's the filter I'm using:

<filter id="drop-shadow">
<feMorphology operator="dilate" radius="6" in="SourceAlpha" result="dilated"/>

<feGaussianBlur stdDeviation="3" in="dilated" result="blurred"/>

<feFlood flood-color="rgba(255,255,255,0.5)" in="blurred" result="flooded"/>

<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>

feMorphology dilate operator replicates the functionality I wanted very nicely, making it easier to give the text a 'glow' effect that conforms a lot more strictly to the outline of the text.

Sample Image

(Oddly, feFlood does nothing and I'm unable to get a white glow, but that's a problem for another question. The filter also eats up 100% of a single core as long as it's open in a tab in the latest Chrome. Oh well.)

Why doesn't spread radius property for `filter: drop-shadow(...);` work?

This MDN page is a bit misleading.

While it might come to the specs one day, they currently state that

Note: Spread values or multiple shadows are not accepted for this level of the specification.

To put it in context, they say so because the drop-shadow filter takes the same parameters has the box-shadow one, which does have a spread value.

Spreading a box-shadow is an easy thing to do, but drop-shadow filter can apply on far more complex shapes, so it's harder to implement.

Even SVG filters don't have an equivalent, though it might be possible to make something there, with a lot of work.

To the defense of that MDN article, it has a warning box stating

Most browsers do not support this parameter; the effect will not render if used.

Ps: here is an svg filter generator I made, approximating that. It's not entirely equivalent to what box-shadow's spread does, but it might be enough for some cases.

const filtered = document.getElementById( 'filtered' );const box_shadow = document.getElementById( 'box_shadow' );const clipped = document.getElementById( 'clipped' );inp.onchange = function() {  filtered.style.borderRadius = this.value;  box_shadow.style.borderRadius = this.value;};inp.onchange();
filtered.style.filter = clipped.style.filter = 'url( #' + spreadingBoxShadow( 20, 20, 10, 50, "blue" ) + ')';
function spreadingBoxShadow( offset_x, offset_y, blur_radius, spread_radius, color ) {
const _id = "spread-radius-" + Date.now(); const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svg.innerHTML = ` <filter id="${ _id }" x="-100%" y="-100%" width="300%" height="300%" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> <feFlood flood-color="${ color }" result="flood" in="SourceAlpha" /> <feComposite in2="SourceAlpha" in="flood" operator="atop" result="color" /> <feMorphology operator="dilate" radius="${ spread_radius}" result="spread" in="color"/> <feGaussianBlur in="spread" stdDeviation="${ blur_radius }" result="shadow"/> <feOffset dx="${ offset_x }" dy="${ offset_y }" in="shadow" result="offset"/> <feMerge result="merge"> <feMergeNode in="offset"/> <feMergeNode in="SourceGraphic"/> </feMerge> </filter>`; document.body.append( svg ); return _id;
}
#box_shadow,#filtered,#clipped > div {  width: 325px;  height: 200px;  background: green;  margin: 30px 50px 100px;}#box_shadow { box-shadow: 20px 20px 10px 50px blue;}#clipped {  padding: 50px;}#clipped > div {  clip-path: polygon(50% 0, 70% 10%, 70% 80%, 0 40%);}.cont {  position: relative;}
Change border-radius here: <input id="inp" value="120px 200px / 100px 0px"><div class="cont">  Filter:<br>  <div id="filtered"></div>  Box-shadow:<br>  <div id="box_shadow"></div>  Clipped:<br>  <div id="clipped">    <div></div>  </div></div>

Get drop-shadow to spread further

There's no direct alternative to the spread property, which isn't actually part of the standard. It may be possible to use SVG Filters as per CSS3 filter: drop-shadow spread property alternatives. Otherwise it may be possible to use one image on top of the other and use transforms to grow the background, but I'm not exactly sure if that's the effect you're going for.

@keyframes logo-grow {
0% {
transform: scale(1);
}
100% {
transform: scale(1.3);
}
}

Then apply that to the background image. You'd need to make sure the two images match up exactly in terms of sizing or the overlap would look bad (like in the demo above).

CSS3 filter:opacity(X) with fallback to opacity:X, same for filter:drop-shadow() to box-shadow

The support for filter (with and without prefix) should overlap pretty nicely with support for the Conditional Rules module (@supports), with the exception of older versions of Safari/iOS (before Safari 9). If you treat it as an enhancement (i.e. with a fallback to regular opacity for other browsers), that shouldn't be a big issue. Try something like this, perhaps?

.half-transparent {
opacity: 0.5;
}
@supports ((filter: opacity(0.5)) or (-webkit-filter: opacity(0.5))) {
.half-opacity {
opacity: 1;
-webkit-filter: opacity(0.5);
filter: opacity(0.5);
}
}

Why does box-shadow look different than filter: drop-shadow

I believe this is a bug. The W3C specification for CSS filters states that "values are interpreted as for box-shadow [CSS3BG]." Therefore, similar results should be expected from the two properties.

I achieved a similar issue, as seen here:

#box1, #box2 {  position: absolute;  top: 10px;  width: 100px;  height: 100px;  background: red;}
#box1 { /* Using drop shadow, should appear identical to box shadow */ left: 10px; filter: drop-shadow(0 5px 10px black)}
#box2 { left: 120px; box-shadow: 0 5px 10px black;}
<div id="box1"></div><div id="box2"></div>

How to have a drop shadow on a transparent rect svg

You can't do this if the original is a fully transparent shape - because of reasons - but you can do this starting from an almost completely transparent original shape and end up with a fully transparent shape surrounded by a normal drop shadow.

Draw your shapes with 1% fill-opacity. When you pull those into a filter, multiply their alpha by 100 using a colormatrix - and use that as the basis for your dropshadow. You won't end up using the original 1% opacity shape in your final version because if you use the "out" operator - this discards the contents of anything that overlaps with the original (processed) shape.

svg {  background: #33D; }
<svg width="500px" height="400px"><defs>  <filter id="trans-shadow">  <feColorMatrix type="matrix" values="1 0 0 0 0                                        0 1 0 0 0                                        0 0 1 0 0                                        0 0 0 100 0"                                       result="boostedInput"/>                                         <feGaussianBlur stdDeviation="5"/>  <feComposite operator="out" in2="boostedInput"/>  </filter></defs>

<circle filter="url(#trans-shadow)" x="100" y="100" r="050" cx="150" cy="150" fill="black" fill-opacity="0.01" />

</svg>


Related Topics



Leave a reply



Submit