ChatGPT解决这个技术问题 Extra ChatGPT

SVG drop shadow using css3

Is it possible to set drop shadow for an svg element using css3 , something like

box-shadow: -5px -5px 5px #888;
-webkit-box-shadow: -5px -5px 5px #888;

I saw some remarks on creating shadow using filter effects. Is there an example of using css alone. Below is a working code where the cusor style is correctly applied, but no shadow effect. Please help me to get the shadow effect with least bit of code.

svg .shadow { cursor:crosshair; -moz-box-shadow: -5px -5px 5px #888; -webkit-box-shadow: -5px -5px 5px #888; box-shadow: -5px -5px 5px #888; }


h
hitautodestruct

Use the new CSS filter property.

Supported by webkit browsers, Firefox 34+ and Edge.

You can use this polyfill that will support FF < 34, IE6+.

You would use it like so:

/* Use -webkit- only if supporting: Chrome < 54, iOS < 9.3, Android < 4.4.4 */ .shadow { -webkit-filter: drop-shadow( 3px 3px 2px rgba(0, 0, 0, .7)); filter: drop-shadow( 3px 3px 2px rgba(0, 0, 0, .7)); /* Similar syntax to box-shadow */ }

This approach differs from the css box-shadow effect in that it accounts for opacity and does not apply the drop shadow effect to the box but rather to the outline of the svg element itself.

Please Note: This approach only works when the class is placed on the <svg> element alone. You can NOT use this on an inline svg element such as <rect>.

<!-- This will NOT work! -->
<svg><rect class="shadow" ... /></svg>

Read more about css filters on html5rocks.


This appears to work for images, or for the whole svg, but for selections inside the svg. the fiddle
This doesn't work for applying drop-shadows to svg elements in any way. do not use it. Example of failure: jsbin.com/bepurahuwa/1/edit?html,css,js,output
@AndyRay works like a charm... jsbin.com/peviso/edit?html,css,js,output. You put the class on the <svg> tag.
@hitautodestruct yes, it does work like that. The real problem comes when you need too apply filter to an element, but not to others.
I guess both @AndyRay and hitautodestruct are right, because as pointed out here, this looks like a Chrome rendering issue: Firefox is rendering correctly the filter on SVG specific elements.
N
Nacho Coloma

Here's an example of applying dropshadow to some svg using the 'filter' property. If you want to control the opacity of the dropshadow have a look at this example. The slope attribute controls how much opacity to give to the dropshadow.

Relevant bits from the example:

<filter id="dropshadow" height="130%">
  <feGaussianBlur in="SourceAlpha" stdDeviation="3"/> <!-- stdDeviation is how much to blur -->
  <feOffset dx="2" dy="2" result="offsetblur"/> <!-- how much to offset -->
  <feComponentTransfer>
    <feFuncA type="linear" slope="0.5"/> <!-- slope is the opacity of the shadow -->
  </feComponentTransfer>
  <feMerge> 
    <feMergeNode/> <!-- this contains the offset blurred image -->
    <feMergeNode in="SourceGraphic"/> <!-- this contains the element that the filter is applied to -->
  </feMerge>
</filter>
<circle r="10" style="filter:url(#dropshadow)"/>

Box-shadow is defined to work on CSS boxes (read: rectangles), while svg is a bit more expressive than just rectangles. Read the SVG Primer to learn a bit more about what you can do with SVG filters.


Is there a way of controlling the opacity of the dropshadow?
@HughGuiney: yes, of course. Here's an example of one way of doing that, xn--dahlstrm-t4a.net/svg/filters/…. Just vary the slope attribute to tweak how much opacity you want.
@LorenzoPolidori IE10 and Safari 5.2 both support SVG filters.
Example on how to implement this approach in D3.js: bl.ocks.org/cpbotha/5200394
J
Jonny Ekholm

You can easily add a drop-shadow effect to an svg-element using the drop-shadow() CSS function and rgba color values. By using rgba color values you can change the opacity of your shadow.

img.light-shadow{ filter: drop-shadow(0px 3px 3px rgba(0, 0, 0, 0.4)); } img.dark-shadow{ filter: drop-shadow(0px 3px 3px rgba(0, 0, 0, 1)); }


@Foxhoundn This is definitely the modern solution, and should be accepted as the answer.
Internet Explorer 11: Fail (no drop shadow but the original SVG image is shown). Firefox (Release & ESR): OK. Google Chrome: OK. Edge Legacy: OK.
dam, if this only worked on groups and shapes in the SVG!
n
nikk wong

Easiest way I've found is with feDropShadow.

<filter id="shadow" x="0" y="0" width="200%" height="200%">
  <feDropShadow dx="3" dy="3" stdDeviation="1" flood-color="#ff0000" flood-opacity="1" />
</filter>

On the element:

<path d="..." filter="url(#shadow)"/>

I did some reading and now that I understand your answer you definitely get that upvote. This answer is not appreciated enough. However, a little bit more explanation would bee good. This example for instance: developer.mozilla.org/en-US/docs/Web/SVG/Element/…
For this to work, you need to add filter:url(#shadow) to the element you want to have a shadow (#shadow is the id of the filter tag). For example <path d="..." style="filter:url(#shadow)"/>. Maybe you should add that to your answer.
Having smaller values in feDropShadow dx="40" dy="40" stdDeviation="35" , such as 3,3,1 instead on 40,40,35 might save some confusion.
F
F. Hauri - Give Up GitHub

Black text with white shadow

Another way, I used for white shadow (on text): create a clone for shadow:

Note: This require xmlns:xlink="http://www.w3.org/1999/xlink" at SVG declaration.

Real text value is located in <defs> section, with position and style, but without a fill definition.

The text is cloned two times: first for shadow and second for the text itself.

Black text with white shadow

More distant shadow with biggest value as blur deviation:

Black text with white shadow

You can use this same approach with regular SVG objects.

With same requirement: No fill definition at <defs> section!


Wouldn't it be possible to just use flood-color?
Blur is used to make shadow look a little blurred. See my second text version More distant shadow... (Just added now)
N
NVRM

Probably an evolution, it appears that inline css filters works nicely on elements, in a certain way.

Declaring a drop-shadow css filter, in an svg element, in both a class or inline does NOT works, as specified earlier.

But, at least in Firefox, with the following wizardry:

Appending the filter declaration inline, with javascript, after DOM load.

// Does not works, with regular dynamic css styling: shadow0.oninput = () => { rect1.style.filter = "filter:drop-shadow(0 0 " + shadow0.value + "rem black);" } // Okay! Inline styling, appending. shadow1.oninput = () => { rect1.style += " ;filter:drop-shadow(0 0 " + shadow1.value + "rem black);" rect2.style += " ;filter:drop-shadow(0 0 " + shadow1.value + "rem black);" }

Firefox only

Does not works! | Okay!

https://i.stack.imgur.com/3RLDH.gif


P
Pierre Paquette

If your SVG element is <text>, you can use the CSS property text-shadow without any problem. Syntax is text-shadow: color x-offset-px y-offset-px blur-px.


B
Bhargav Rao

I'm not aware of a CSS-only solution.

As you mentioned, filters are the canonical approach to creating drop shadow effects in SVG. The SVG specification includes an example of this.


-webkit-filter: drop-shadow() is the way to go for sure. See the answer by @hitautodestruct.
@clayzermk1 if you want it to work only in webkit.... then yeah. We're lookin for a more solid solution, methinks, and I think this is also no longer supported.
@jbeard4 link broken, better maybe have the content pasted here.
Submited link point to Removed: Filter Effects This chapter is no longer part of the SVG specification!!
This is a non-answer.