75

The SVG I'm working with has a drop shadow via feGaussianBlur filter.

The shadow itself is displayed properly, but gets cut off on top and bottom edges.

Like so:

image of cutoff shadow

The SVG in question is:

<?xml version="1.0" standalone="no" ?>
<!DOCTYPE svg
  PUBLIC '-//W3C//DTD SVG 1.1//EN'
  'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
<svg height="600" version="1.1" width="700" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs/>
  <filter id="SVGID_0">
    <feGaussianBlur in="SourceGraphic" stdDeviation="6.6"/>
    <feOffset dx="0" dy="0"/>
    <feMerge>
      <feMergeNode/>
      <feMergeNode in="SourceGraphic"/>
    </feMerge>
  </filter>
  <path d="M 0 83 Q 0 83 0 83 Q 0 83 6 79.5 Q 12 76 17 71 Q 22 66 30.5 57.5 Q 39 49 54 36 Q 69 23 82.5 16.5 Q 96 10 120 4.5 Q 144 -1 170.5 0 Q 197 1 218 16.5 Q 239 32 253.5 51 Q 268 70 278 83.5 Q 288 97 299 110 Q 310 123 320 129.5 Q 330 136 338 136.5 Q 346 137 355 129.5 L 364 122" stroke-linecap="round" style="stroke: #005e7a; stroke-width: 30; fill: none; filter: url(#SVGID_0);" transform="translate(50 50)" />
</svg>

The cropping seems to happen consistently in Chrome (30), Firefox (25), and Opera (12).

I can see that it's not a viewbox limitation, as it's set to 600x700.

I can also see in devtools inspector the bounding box of <path> element, and it's almost as if that's what cuts off the shadow:

path bounding box

If that's the case:

  1. Why is the shadow only cut off vertically and not horizontally?
  2. How to work around it, so that it's not clipped like this?

If it's not the bounding box, what causes this and how to avoid this clipping?

BuZZ-dEE
  • 6,075
  • 12
  • 66
  • 96
kangax
  • 38,898
  • 13
  • 99
  • 135

3 Answers3

128

You need to increase the size of the filter region.

<filter id="SVGID_0" y="-40%" height="180%">

works just fine. The silent defaults for the filter region are: x="-10%" y="-10%" width="120%" height="120%" - large blurs usually get clipped. (Your shadow isn't getting clipped horizontally because your width is about 2.5x your height - so that 10% results in a wider horizontal filter region). Also, the y filter region seems to be calculated as if the path had a zero pixel stroke, so it's ignoring the stroke width. (Different browsers have different behavior wrt whether they consider the stroke to be part of the bounding box for purposes of filter region calculation.)

(Update: Moving up observations from comments) Please note that if your particular shape is either zero width or zero height (e.g. a horizontal or vertical line), then you must specify filterUnits="userSpaceOnUse" as part of the filter declaration and explicitly specify a filter region (x,y,width height) in userSpaceUnits (usually pixels) that creates enough room to display a shadow.

Michael Mullany
  • 30,283
  • 6
  • 81
  • 105
  • 2
    Ah, very interesting. Had no idea about filter's region, but do see it in spec now. – kangax Jul 26 '13 at 22:57
  • 1
    How would you set the y-attribute and height-attribute of the filter if you didn't know how large your shadow was going to be beforehand? Do you just have to set this on the fly, or is it possible to say "I'd like my shadow to never get cut off, no matter how big it is?" – Nick Budden Jun 23 '14 at 19:52
  • 1
    Well you can create a very large default shadow area, but that's also going to take up memory. Very large shadows are also very performance intensive, so better to avoid them. – Michael Mullany Jun 24 '14 at 16:54
  • 1
    You can make the shadow area the size of the viewBox by using `filterUnits="userSpaceOnUse"` which will essentially position it absolutely (on the canvas of the SVG). Then you can specify a pixel location and size `` – Nilloc Jun 05 '15 at 20:17
  • 2
    Nilloc - you'd want to make those x and y's negative so that they don't clip the left and top edges of the blur. filterUnits changes the unit system, but doesn't change the 0,0 of the coordinates - which is always at the top left of the bounding box (although light sources are treated differently) – Michael Mullany Aug 21 '15 at 21:08
  • This only works if you're not doing a zero-width line. If you are doing that, then you have to use @Jack's answer: `filterUnits="userSpaceOnUse"` – RoboticRenaissance Aug 23 '21 at 03:01
  • I don't think you read through the answer completely - I mention that in the update section – Michael Mullany Aug 24 '21 at 12:25
24

Add an attribute to the filter shadow svg tag:

filterUnits="userSpaceOnUse"

Final Output:

<filter id="dropshadow" filterUnits="userSpaceOnUse" height="800" width="1600">

Which makes the shadow absolutely positioned and visible outside of its container.

Jack
  • 3,271
  • 11
  • 48
  • 57
15

If you're using it inside an HTML, you can simply use CSS properties to fix this issue.

svg {
  overflow: visible !important;
}

I haven't checked other browsers, but chrome has the overflow: hidden by default on svg tags.

A bit late, but I hope it's helpful.

Daniel Reina
  • 5,764
  • 1
  • 37
  • 50
  • Somebody downvoted; Is there a good general reason not to apply this property? – user66081 Sep 10 '16 at 16:31
  • I am using it in a project and it works great. I don't know if there is a specific case where it shouldn't be used. In my project I couldn't find a combination of `y` and `height` that worked with Michael Mullany solution, so I had to implement the one that I described above. – Daniel Reina Sep 10 '16 at 16:51
  • 1
    Thx, I think it's useful. – user66081 Sep 10 '16 at 17:55
  • 6
    I downvoted. Sometimes the SVG viewBox will cut off a shadow, but that was not the case for this question. Try your solution with the OP's code - it doesn't work. – Michael Mullany Sep 10 '16 at 19:39
  • 2
    Also, « !important » statements are usually frowned upon (with reason). Although there's a good reason for this clause to exist, it's almost never used for it. And "I had to use it because I have no access to original code" is not a good reason neither. :-) – Obsidian Dec 04 '18 at 15:22
  • Is there any way to not show the shadow on one side? For example the bottom? – mikasa May 08 '20 at 20:58
  • 1
    @Eren555 I guess you can wrap your SVG in a div, make that div's height bigger than the SVG so there's extra room at the bottom. Then make the svg's overflow visible and the div's overflow invisible. I haven't checked the solution, but I think that should do the trick – Daniel Reina May 11 '20 at 08:56