10

I'd like to apply a drop-shadow filter to a specific element/path inside an inline placed SVG via CSS, I don't need the whole graphic to be shadowed, just an element inside it.

.shadow {
  fill: red;
  
  -webkit-filter: 
    drop-shadow( 3px 3px 2px rgba(0,0,0,.7) );
          filter: 
    drop-shadow( 3px 3px 2px rgba(0,0,0,.7) );
}
  <svg height="150" width="150">
    <g>
<path d="M0,0 C-72,132 -72,-26 100,100"></path>
    </g>
    <g class="shadow" >
    <circle class="shadow" cx="100" cy="100" r="20"></circle>
    </g>
  </svg>

As you can see above, I'm trying to apply a drop-shadow to the red circle element of the SVG, but it's not working.

Searching around I haven't found any specific info on this, only few comments in other SVG related questions simply stating that it doesn't work on single SVG elements, but without much explanations.

UPDATE

As pointed out by @azeós in the comments, it is rendering correctly with Firefox (v. 43.0.2) so it's a Chrome specific issue. Is there anyway to make this crossbrowser without fiddling out with the SVG code as suggested in the comments?

5
  • Just curious, why not the SVG filters to create a shadow?
    – Harry
    Commented Dec 25, 2015 at 5:20
  • Like Harry suggests, I think your best option for a drop shadow is filters in the svg code w3schools.com/svg/svg_feoffset.asp Commented Dec 25, 2015 at 5:24
  • Yea should have specified in the question, I'd like to avoid messing with the SVG code due to workflow. Is this re<lly the only viable option?
    – Gruber
    Commented Dec 25, 2015 at 5:34
  • 1
    I'm seeing the shadow... Waterfox 40.1.0, which browser are you using? stackoverflow.com/a/13624469/1095101
    – azeós
    Commented Dec 25, 2015 at 5:49
  • Oh nice I'm using chrome, I can see the shadow too on Firefox. I guess it's a Chrome business then. What is the specific issue with chrome? I've updated the quesiton
    – Gruber
    Commented Dec 25, 2015 at 6:01

3 Answers 3

25

Updated 2020-04: I did some experiments on this issue because I too couldn't find any information on this and the results are pretty inconsistent.

The TL;DR: SVG drop-shadows are very inconsistent but HTML drop-shadows reliably work (outside of IE11). If you want SVG drop-shadows, you're going to have use a polyfill or just do the drop-shadow within the SVG itself.

Codepen experiment: http://codepen.io/staypuftman/pen/GoNoMq

Chrome 81 + Canary 83:

Neither Chrome nor edge Canary respect filter or -webkit-filter properly in the context of an SVG object drop-shadow but do work on a simple div.

enter image description here

Firefox 75 + Firefox 53 (pre-quantum):

Looks pretty good for both SVG and HTML objects.

enter image description here

Safari 13+

Safari briefly had dropshadows on earlier versions but has dropped them again.

enter image description here

Safari 10.1 - 11

Safari has fixed this issue in the 10.1 (and maybe the 10.0) series.

enter image description here

Safari 9.x

SVG CSS dropshadow does not show and the div dropshadow has less opacity for some reason

enter image description here

Edge (Chromium version)

No SVG dropshadows but the HTML ones work well.

enter image description here

IE11

Nothing.

enter image description here

2
  • Interesting research, thank you! I can't test myself atm the polyfill, can you confirm that it's working on chrome too?
    – Gruber
    Commented Dec 29, 2015 at 0:23
  • I havent tried the polyfill, I'll have to do it tomorrow as I'm done for the day in my time zone. Let me know if you give it a shot.
    – serraosays
    Commented Dec 29, 2015 at 0:33
2

You can apply a shadow selectively by doing color selection on the object you want to shadow, creating a shadow and then merging it under the original graphic. But you have to do it via the SVG filter trapdoor in CSS Filters - which doesn't work in IE. (So ... hacky, but possible)

Spec is here: w3.org/TR/SVG11/filters.html#feColorMatrixElement

Demo toy is here:
https://beta.observablehq.com/@gitmullany/filter-effects-using-svg-color-matrices

That matrix doubles the opacity of all red values, zeros out the opacity of everything else and then subtracts 1. The effect is to only leave things at 100% opacity that are rgb(255,0,0)

#mySVG {
   filter: url(#selective-shadow);
}

.shadow {
  fill: red;
}
<svg>
 <defs>
   <filter id="selective-shadow">
     <feColorMatrix type="matrix" values="0 0 0 0 0 
                                          0 0 0 0 0
                                          0 0 0 0 0 
                                          2 0 0 0 -1"/>
     <feGaussianBlur stdDeviation="3"/>
     <feOffset dy="2" dx="2"/>
     <feMerge>
       <feMergeNode/>
       <feMergeNode in="SourceGraphic"/>
     </feMerge>         
   </filter>
 </defs>
</svg>



<svg height="150" width="150" id="mySVG">
    <g>
<path d="M0,0 C-72,132 -72,-26 100,100"></path>
    </g>
    <g class="shadow" >
    <circle class="shadow" cx="100" cy="100" r="20"></circle>
    </g>
  </svg>

3
  • Oh wow that's some advanced SVG hackery, and as far as I can see it works! Very nice! May I ask where the documentation for that matrix grid stuff is? :)
    – Gruber
    Commented Mar 17, 2018 at 2:36
  • 1
    spec is here: w3.org/TR/SVG11/filters.html#feColorMatrixElement Demo toy is here: beta.observablehq.com/@gitmullany/…. That matrix doubles the opacity of all red values, zeros out the opacity of everything else and then subtracts 1. The effect is to only leave things at 100% opacity that are rgb(255,0,0) Commented Mar 17, 2018 at 4:05
  • Holy SVG!! I didn't know you can do such things with SVGs, damn guess I need quite some update on this subject x) Thank you!
    – Gruber
    Commented Mar 17, 2018 at 4:21
1

In this CodePen I added different drop-shadows to path and text generated dynamically. Here I found a cross-browser solution that you can apply to a class, for example, instead of #robbie img (in the second link):

#robbie img { filter: "progid:DXImageTransform.Microsoft.Dropshadow(OffX=12, OffY=12, Color='#444')";   filter: url(#drop-shadow);   -webkit-filter: drop-shadow(12px 12px 7px rgba(0,0,0,0.5));   filter: drop-shadow(12px 12px 7px rgba(0,0,0,0.5)); }

In the first CodePen I commented another alternative way that does not use the classes, but it uses #numbers_dropshadows_filter and #strokes_dropshadows_filter defined in <defs></defs>.

Cheers

0

Not the answer you're looking for? Browse other questions tagged or ask your own question.