SVG filter not showing up in Firefox, working fine in Chrome
Asked Answered
P

5

8

I want a piece of dark text on dark background to have a white glow outside of it. Although the default drop shadow filter in CSS (like filter: drop-shadow(2px 2px 2px black)) officially should support a 'spread-radius' fourth attribute, support for this attribute is basically non-existent. Without this extra spread, the drop shadow will not be big enough to allow the text to be read.

So, I decided to define my own filter in an SVG tag, including a dilation operation to implement the extra spread, and apply that to the text instead. This filter works fine in Chrome, but causes the text to become entirely invisible in Firefox (both tested under Ubuntu 14.04). According to caniuse.com (usually very reliable, I've found), Firefox should support the filter perfectly fine.

The HTML code with SVG filter:

<svg xmlns="http://www.w3.org/2000/svg">
<defs>

<filter id="my-drop-shadow" x="0" y="0" width="200%" height="200%">

    <feColorMatrix type="matrix" values=
                "0 0 0 0   1
                 0 0 0 0   1
                 0 0 0 0   1
                 0 0 0 1   0"/>
    <feMorphology operator="dilate" radius="2" />
    <feGaussianBlur stdDeviation="2" in="coloredOut" result="coloredBlur"/>
    <feMerge>
        <feMergeNode in="coloredBlur"/>
        <feMergeNode in="SourceGraphic"/>
    </feMerge>

</filter>

</defs>
</svg>

<p>Hello there.</p>

The CSS:

body {
    color: #000; background: #002;
    font-family: serif; font-size: 30px;
    font-weight: bold;
}

p {
    -webkit-filter: url(#my-drop-shadow);
    filter: url(#my-drop-shadow);
}

Result on Chrome (version 46.0.2490.80 (64-bit)):

Result on Chrome

Result on Firefox (version 42.0):

Result on Firefox

I've put the code above in a working CodePen (edit: note that I've now updated the CodePen to reflect @RobertLongson's answer and it works; see below though for why this was not the full answer).

Any ideas? Typo I haven't spotted in my SVG code?

Paucity answered 12/11, 2015 at 16:24 Comment(0)
Z
6

There's an input called coloredOut but no output called coloredOut so the filter chain fails. Removing the in="coloredOut" attribute seems to fix that. You might want to raise a Chrome bug that it's not enforcing valid filter chains.

In addition the SVG pushes the text down so you can't see it in the codepen. Adding width="0" height="0" to the <svg> element fixes that issue.

Zacarias answered 12/11, 2015 at 21:33 Comment(1)
Thanks for spotting that! Indeed, when I fix it, the codepen example works. However, in my original code, it doesn't... Will investigate and accept in due course.Paucity
P
14

For me, it was that I had a display:none on the parent <svg> tag which I think causes Firefox to completely ignore the filter tags inside. So changing <svg style="display:none"> to <svg style="position:absolute; height:0"> did the trick.

Plutocracy answered 30/5, 2019 at 0:24 Comment(0)
Z
6

There's an input called coloredOut but no output called coloredOut so the filter chain fails. Removing the in="coloredOut" attribute seems to fix that. You might want to raise a Chrome bug that it's not enforcing valid filter chains.

In addition the SVG pushes the text down so you can't see it in the codepen. Adding width="0" height="0" to the <svg> element fixes that issue.

Zacarias answered 12/11, 2015 at 21:33 Comment(1)
Thanks for spotting that! Indeed, when I fix it, the codepen example works. However, in my original code, it doesn't... Will investigate and accept in due course.Paucity
P
3

The answer by @RobertLongson is excellent and provides part of the solution. In the codepen I provided, everything works when I implement his fix. However, my own code still did not work properly.

The crucial thing is that in the real code, my CSS was in an external file. It turns out that Firefox (correctly!) interprets my selector in filter: url(#my-drop-shadow) as referring to the CSS file, and not to the HTML document to which the CSS is linked. When I specify it as a URL + selector, as in filter: url(../../index.html#my-drop-shadow), everything works fine. (Alternatively, I could have put the filter in a <style></style> element in the same HTML document.)


Source (why Firefox is correct); from CSS 2.1 spec:

In order to create modular style sheets that are not dependent on the absolute location of a resource, authors may use relative URIs. Relative URIs (as defined in [RFC3986]) are resolved to full URIs using a base URI. RFC 3986, section 5, defines the normative algorithm for this process. For CSS style sheets, the base URI is that of the style sheet, not that of the source document.

Paucity answered 13/11, 2015 at 10:3 Comment(1)
Very, very usefull observation. However, Chrome refuses one way or the other. My solution was indeed to inline add only the filter: <rect style="filter:url(#mydropshadow)" class="person" x="5" y="5" ...> . Will investigate how to get Chrome to use the relative URL notationDisentail
C
0

To piggyback off of Chris's answer, having display:none; on an SVG element does indeed cause it to be ignored in Firefox.

A problem I ran into recently was that getting rid of the display:none; in Chrome caused it to render the colors my SVG filter was outputting with more muted tones (no clue why).

What I ended up doing was leaving the display:none; inline and then adding some CSS in the header and used @supports (-moz-context-properties: fill) so it would only trigger on Firefox. You don't have to use that particular prefix, there's a list of Firefox only prefixes here, any of them should work.

Something like this, make sure you put it inside <style> tags in the header, otherwise you may end up with a FOUC.

@supports(-moz-context-properties: fill){
     #svg_element_id{
          position:fixed;
          height:0;
     }
}
Collegian answered 6/2, 2021 at 9:32 Comment(0)
C
0

To piggyback off Haveigonemental's biggyback answer, I too experienced tearing and visual artifacts in chrome when the SVG element is not hidden with display:none.

However the @supports CSS for targeting Firefox did not work for me. So I piggybacked once again and used the CSS from this stackoverflow question: Targeting only Firefox with CSS

.svg-filter {
  display: none;
}

@-moz-document url-prefix() {
  .svg-filter {
      display: block;
  }
}
Croom answered 25/3 at 21:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.