sanjihan
sanjihan

Reputation: 6004

svg shadow does not appear

I am having a problem with setting up shadow for a svg with mask applied to it. This is the code and jsfiddle: http://jsfiddle.net/3kxnmhfL/

.watch-video-svg {
  width: 50px;
  height: 50px;
}
<div class="watch-video-svg">
  <svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" height="100%" width="100%" viewBox="0 0 100 100">
    <defs>
        <filter id="shadow">
            <feDropShadow dx="4" dy="8" stdDeviation="4"/>
        </filter>
        <mask id="cut-off-bottom">
            <circle cx="50%" cy="50%" r="50%" fill="white"/>
            <polygon points="31,20, 31,77, 80,50" fill="black"/>
            <!-- <rect x="0" y="0" width="200" height="200" fill="url(#Gradient)"  /> -->
        </mask>
    </defs>
    <circle cx="50%" cy="50%" r="50%" fill="red" mask="url(#cut-off-bottom)" filter="url(#shadow)" />
</svg>
</div>

I'd like the shadow to appear only around svg circle and not containing div.

What could be the reason for shadow not showing up?

Upvotes: 3

Views: 2941

Answers (2)

Paul LeBeau
Paul LeBeau

Reputation: 101820

SVG filters have a "filter region". The filter region defines the area of pixels that the browser uses to store the result of the filters. The default filter region is the bounds of the element (that the filter is applied to) plus a margin around it to allow for filter elements that have results larger than the original element.

By default, that margin is 10% of the width and height, applied to all four sides. However in your case, a stdDeviation of "4" causes the blur to extend further than that 10% margin allowance. The result is a clipped blur, even though the viewBox has been enlarged enough to cater for the full blur.

To fix, this, you just need to bump up the filter region size. An allowance of 20% seems to work okay:

<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">

In addition, I've simplified the SVG by getting rid of the unnecessary mask. I also tweaked the viewBox to include the part of the blur that extends to the left.

.watch-video-svg {
  width: 500px;
  height: 500px;
  background: linen;
}
<div class="watch-video-svg">
  <svg xmlns="http://www.w3.org/2000/svg"  height="100%" width="100%" viewBox="-5 0 120 120">
    <defs>
        <filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
            <feDropShadow dx="4" dy="8" stdDeviation="4"/>
        </filter>
    </defs>
    <circle cx="50" cy="50" r="50" fill="red" filter=url(#shadow) />
    <polygon points="31,20, 31,77, 80,50" fill="white"/>
</svg>
</div>

Upvotes: 2

Temani Afif
Temani Afif

Reputation: 272866

You need to adjust your mask. Since your element is already a circle you don't need a circle in the mask, a rect to fill all the width/height is enough.

You need to also adjust the viewBox to leave some space for the shadow:

.watch-video-svg {
  width: 50px;
  height: 50px;
}
<div class="watch-video-svg">
  <svg xmlns="http://www.w3.org/2000/svg"  height="100%" width="100%" viewBox="0 0 120 120">
    <defs>
        <filter id="shadow">
            <feDropShadow dx="4" dy="8" stdDeviation="4"/>
        </filter>
        <mask id="cut-off-bottom">
            <rect x="0" y="0" width="100%" height="100%" fill="white"/>
            <polygon points="31,20, 31,77, 80,50" fill="black"/>
        </mask>
    </defs>
    <circle cx="50" cy="50" r="50" fill="red" mask="url(#cut-off-bottom)" filter=url(#shadow) />
</svg>
</div>

Upvotes: 1

Related Questions