Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plugin idea/request for filter cross browser compatibility #732

Closed
drschwabe opened this issue May 29, 2017 · 25 comments
Closed

Plugin idea/request for filter cross browser compatibility #732

drschwabe opened this issue May 29, 2017 · 25 comments

Comments

@drschwabe
Copy link

drschwabe commented May 29, 2017

Firefox and Chrome treat SVG filters (ID's) differently - the long and short of it is to ensure filters work in Firefox (otherwise anything that uses a filter disappears) you must create a class with a relative reference to the appropriate filter ID.

For example, this doesn't work in Firefox but works in Chrome:

<svg>
    <defs>
        <filter id="a" color-interpolation-filters="sRGB">
            <feBlend in2="BackgroundImage" mode="lighten"/>
        </filter>
    </defs>
    <path transform="matrix(123456789)" filter="url(#a)"/>
</svg>

This however, works in both Chrome and Firefox:

<svg>
    <defs>
        <style>
          .filterA {
            filter:"url(.#a)"; 
          }          
        </style> 
        <filter id="a" color-interpolation-filters="sRGB">
            <feBlend in2="BackgroundImage" mode="lighten"/>
        </filter>
    </defs>
    <path transform="matrix(123456789)" class="filterA" />
</svg>

This may be specific to my workflow which involves creating the SVGs in Inkscape which generates filters in this way (first example is saved from Inkscape and run through SVGO, second example is the manual hack/fix).

There is some discussion about the issue on SO:
https://stackoverflow.com/questions/33676342/svg-filter-not-showing-up-in-firefox-working-fine-in-chrome

At any rate, it seems like my solution above could be automated with SVGO so I just wanted to put this out there; I don't have any immediate intentions to write a plugin myself but would certainly welcome any feedback or insight if you care to share. Thanks.

@GreLI
Copy link
Member

GreLI commented May 29, 2017

That's strange, looks like you have a bad filter. It should work in SVG, otherwise file a bug. The topic on SO is about using filters in HTML–that's a different topic.

@drschwabe
Copy link
Author

drschwabe commented May 29, 2017

To clarify context, this class/filter workaround is necessary when using including the SVG in an HTML via the img tag ie:

<img src="/img/star.svg" />

The SO topic there touches on Firefox wanting a relative path, hence note the workaround/second example uses a dot prefix before the id anchor character ie: .#a

@GreLI
Copy link
Member

GreLI commented May 29, 2017

Well, then it may be related to SVG as an Image restrictions. Still it could be a bug.

@drschwabe
Copy link
Author

drschwabe commented May 29, 2017

Thanks for the link. Regardless of if it is a browser bug in the interest of ensuring compatibility with existing browsers I am still interested in an automated (maybe SVGO) solution; currently working on a project that involves many SVGs created from Inkscape that save filters this way and so instead of hand-editing every file to fix for Firefox it would be great to automate the solution.

If I was to use a blunt hammer on it; from the top of my head I would probably reach for something like Cheerio to parse and then rebuild the XML to reflect the workaround as indicated in the second example (removing the filter attribute, changing it to a class and populating said class(es) in the defs). Though I admit to only having briefly looked at how SVGO plugins are supposed to modify SVG structure, probably that methodology is better!

@strarsis
Copy link
Contributor

strarsis commented May 29, 2017

CSS support for svgo, feature PR: #592

@strarsis
Copy link
Contributor

@drschwabe: So the filter has to be daisy-chained with a CSS filter to make it work in this browser?

@drschwabe
Copy link
Author

@strarsis Yes, for Firefox. Chrome is OK either way.

@strarsis
Copy link
Contributor

strarsis commented Jun 2, 2017

@drschwabe: PR ready: #733

@drschwabe
Copy link
Author

Thanks, I tested it out however the CSS definitions did not fill in with the graphic I tried. Here's the graphic in question:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 77.701826 65.509313" height="69.877" width="82.882">
    <defs>
        <filter id="a" color-interpolation-filters="sRGB">
            <feBlend in2="BackgroundImage" mode="lighten"/>
        </filter>
    </defs>
    <path transform="matrix(.94722 0 0 .94722 -6046.588 -1734.377)" d="M6425.129 1837.273c2.362 0 5.727 7.016 10.31 16.252 22.193 3.58 19.472 4.295 19.472 5.512 0 1.217-12.743 14.104-12.743 14.104s2.22 16.108 2.72 18.542c.501 2.435-4.152 2.721-6.586 1.576-2.434-1.146-13.388-6.802-13.388-6.802s-13.674 6.444-15.75 7.59c-2.077 1.145-4.153-1.79-4.081-4.153.04-1.362 2.506-16.467 2.506-16.467s-10.238-10.452-11.885-12.958c-1.476-2.246.573-4.08 2.434-4.582 1.862-.501 16.216-2.72 16.216-2.72 8.913-16.037 8.412-15.894 10.775-15.894z" fill="#ffbd56" fill-rule="evenodd" stroke="#000" stroke-width="3.037" filter="url(#a)"/>
</svg>

@strarsis
Copy link
Contributor

strarsis commented Jun 3, 2017

@drschwabe: Edit: chainFilters was missing in .svgo config file in feature PR and there were also
some other issues with creating a new <style> element.
This has been fixed now, thanks for your issue report.
You may need to reinstall from PR branch to get the current fixed code.

Note: The chainFilters plugin isn't enabled by default, you have to enable it when using svgo so it is used:

svgo -i input.svg --enable=chainFilters -o output.svg

@strarsis
Copy link
Contributor

strarsis commented Jun 3, 2017

@drschwabe: According to the SO thread you linked to the reason for the filter problem is not the browser but some incorrect markup/CSS used in the example?

@drschwabe
Copy link
Author

drschwabe commented Jun 4, 2017

Hi @strarsis, tried your plugin on the example SVG I provided above however that graphic still does not appear in Firefox. With this file it seems your plugin gets as far as creating <style></style> but there are no classes.

You may test this by copy/pasting the contents of that svg into a new file on your system and opening it directly with Chrome - you should see a star. In Firefox nothing appears.

To get the file working in Firefox, the file needs to look like this:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 77.701826 65.509313" height="69.877" width="82.882">
    <defs>
        <style>
          .filterA {
            filter:"url(.#a)"; 
          }          
        </style> 
        <filter id="a" color-interpolation-filters="sRGB">
            <feBlend in2="BackgroundImage" mode="lighten"/>
        </filter>
    </defs>
    <path transform="matrix(.94722 0 0 .94722 -6046.588 -1734.377)" d="M6425.129 1837.273c2.362 0 5.727 7.016 10.31 16.252 22.193 3.58 19.472 4.295 19.472 5.512 0 1.217-12.743 14.104-12.743 14.104s2.22 16.108 2.72 18.542c.501 2.435-4.152 2.721-6.586 1.576-2.434-1.146-13.388-6.802-13.388-6.802s-13.674 6.444-15.75 7.59c-2.077 1.145-4.153-1.79-4.081-4.153.04-1.362 2.506-16.467 2.506-16.467s-10.238-10.452-11.885-12.958c-1.476-2.246.573-4.08 2.434-4.582 1.862-.501 16.216-2.72 16.216-2.72 8.913-16.037 8.412-15.894 10.775-15.894z" fill="#ffbd56" fill-rule="evenodd" stroke="#000" stroke-width="3.037" class="filterA" />
</svg>

(again, you may test by saving the contents above into a file and opening with Chrome/Firefox)

Regarding the SO thread, they talk about this issue however none of the answers provided fix this issue; this daisy chain technique I came up with as an independent solution/iteration on the answers & comments there.

@strarsis
Copy link
Contributor

strarsis commented Jun 4, 2017

@drschwabe:
Input SVG from above:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 77.701826 65.509313" height="69.877" width="82.882">
    <defs>
        <style>
          .filterA {
            filter:"url(.#a)"; 
          }          
        </style> 
        <filter id="a" color-interpolation-filters="sRGB">
            <feBlend in2="BackgroundImage" mode="lighten"/>
        </filter>
    </defs>
    <path transform="matrix(.94722 0 0 .94722 -6046.588 -1734.377)" d="M6425.129 1837.273c2.362 0 5.727 7.016 10.31 16.252 22.193 3.58 19.472 4.295 19.472 5.512 0 1.217-12.743 14.104-12.743 14.104s2.22 16.108 2.72 18.542c.501 2.435-4.152 2.721-6.586 1.576-2.434-1.146-13.388-6.802-13.388-6.802s-13.674 6.444-15.75 7.59c-2.077 1.145-4.153-1.79-4.081-4.153.04-1.362 2.506-16.467 2.506-16.467s-10.238-10.452-11.885-12.958c-1.476-2.246.573-4.08 2.434-4.582 1.862-.501 16.216-2.72 16.216-2.72 8.913-16.037 8.412-15.894 10.775-15.894z" fill="#ffbd56" fill-rule="evenodd" stroke="#000" stroke-width="3.037" class="filterA" />
</svg>
$ ./node_modules/.bin/svgo -i input.svg --enable=chainFilters -o output.svg

Output SVG:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 77.701826 65.509313" height="69.877" width="82.882"><style>.filterA{filter:&quot;url(#a)&quot;}</style><defs><filter id="a" color-interpolation-filters="sRGB"><feBlend in2="BackgroundImage" mode="lighten"/></filter></defs><path d="M39.423 5.925c2.237 0 5.424 6.645 9.766 15.394 21.021 3.391 18.444 4.068 18.444 5.221 0 1.153-12.07 13.36-12.07 13.36s2.102 15.257 2.576 17.563c.474 2.306-3.933 2.577-6.239 1.493-2.305-1.086-12.681-6.443-12.681-6.443s-12.952 6.104-14.919 7.19c-1.967 1.084-3.933-1.696-3.865-3.935.038-1.29 2.373-15.597 2.373-15.597s-9.697-9.9-11.257-12.275c-1.398-2.127.542-3.864 2.305-4.34 1.764-.474 15.36-2.576 15.36-2.576C37.66 5.79 37.184 5.925 39.423 5.925z" fill="#ffbd56" fill-rule="evenodd" stroke="#000" stroke-width="2.8767071399999997" class="filterA"/></svg>

The star icon is displayed in Chrome and also in Firefox.
Have you really installed the last commit from the fork?

@drschwabe
Copy link
Author

drschwabe commented Jun 5, 2017

My mistake! The example star graphic gets updated and now working in Firefox, good stuff!

However, there is indeed a scenario which results in an empty <style></style> entry.

Here is that same star graphic but saved raw from Inkscape (v0.91 r13725 using it's "plain SVG" save option). Something in here seems to break your plugin:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.1"
   id="svg4272"
   viewBox="0 0 71.781273 68.434828"
   height="19.313829mm"
   width="20.25827mm">
  <defs
     id="defs4274">
    <filter
       id="filter6239-1"
       style="color-interpolation-filters:sRGB">
      <feBlend
         id="feBlend6241-2"
         in2="BackgroundImage"
         mode="lighten" />
    </filter>
  </defs>
  <metadata
     id="metadata4277">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     transform="translate(478.74778,-452.4305)"
     id="layer1">
    <path
       style="display:inline;fill:#ffbd56;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.03742242;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter6239-1)"
       d="m -442.83654,458.13345 c 2.3626,0 5.7275,7.0161 10.3095,16.2516 22.1937,3.5796 19.4733,4.2956 19.4733,5.5127 0,1.217 -12.7436,14.1037 -12.7436,14.1037 0,0 2.2193,16.1083 2.7205,18.5425 0.5011,2.4342 -4.1524,2.7205 -6.5865,1.5751 -2.4342,-1.1455 -13.3879,-6.8013 -13.3879,-6.8013 0,0 -13.6742,6.4433 -15.7504,7.5888 -2.0761,1.1455 -4.1524,-1.7898 -4.0807,-4.1525 0.041,-1.3614 2.5057,-16.4662 2.5057,-16.4662 0,0 -10.2378,-10.4525 -11.8845,-12.9583 -1.4758,-2.2458 0.5728,-4.0808 2.4342,-4.5819 1.8615,-0.5012 16.2158,-2.7205 16.2158,-2.7205 8.9133,-16.0368 8.4121,-15.8937 10.7746,-15.8937 z"
       id="path6625" />
  </g>
</svg>

@strarsis
Copy link
Contributor

strarsis commented Jun 7, 2017

@drschwabe: Does it work now?
Ensure to have from the latest commit installed when testing this plugin again.

@drschwabe
Copy link
Author

drschwabe commented Jun 8, 2017

Using that next example SVG I provided above, there are no style declarations created.
Installed with npm install -g github:strarsis/svgo#chain-filters

@strarsis
Copy link
Contributor

strarsis commented Jun 8, 2017

@drschwabe: Right, because the <path> element uses the filter already by inline styles (style="[...];filter:url(#filter6239-1)") and not by attribute (filter="url(#filter6239-1)") - hence there is no need for changing it.
However, the star icon isn't visible anymore in Firefox, so a CSS filter property alone doesn't seem to be sufficient - what has to be changed to make it work in Firefox? Must the filter property be in CSS class instead inlined?

@drschwabe
Copy link
Author

Indeed, the inline filter/style does not work on Firefox; it needs to be daisy chained with a CSS class like how was done on the first example.

@strarsis
Copy link
Contributor

strarsis commented Jun 8, 2017

@drschwabe: Test adjusted, I tested the output SVG (in test) and icon is displayed in Chrome and Firefox:
https://raw.githubusercontent.com/strarsis/svgo/6964351c1a9ca3977446ad4574ce24e378b23827/test/plugins/chainFilters.07.svg

For cleanly and correctly implementing this, CSSStyleDeclaration interface from inlineStyles PR is required.

You may notice that the chain class got the name "filterFilter" - this is because "filter" is always prefixed to original filter ID name for the chain class name - so when the <filter> element already got "filter" in its ID name, "filter" is appears twice in resulting chain class name. If this happens often in (exported) SVGs (that "filter" is used in ID for a <filter> element), it may be worth to add an exception for this.

@drschwabe: Just noticed that I have the same issue with an SVG using filters looking differently in Firefox.

@strarsis
Copy link
Contributor

@drschwabe: PR #733 ready now.

@strarsis
Copy link
Contributor

@drschwabe: Does Firefox still have this issue or has this been fixed now?

@SethFalco
Copy link
Member

This is no longer an issue in modern versions of Firefox and Chromium.
Tested with the following SVGs:

I've also tested an SVG based on the examples from MDN:

<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <filter id="a" color-interpolation-filters="sRGB">
      <feFlood result="b" flood-color="red" />
      <feComposite in="b" in2="SourceAlpha" operator="atop" result="c" />
      <feBlend in="SourceGraphic" in2="c" mode="lighten" />
    </filter>
  </defs>
  <image
    href="https://live.mdnplay.dev/en-US/docs/Web/SVG/Element/feBlend/mdn_logo_only_color.png"
    x="1"
    y="1"
    width="8"
    height="8"
    filter="url(#a)"
  />
</svg>

All of them render fine, and produce the same output between Firefox and Chrome.

@SethFalco SethFalco closed this as not planned Won't fix, can't repro, duplicate, stale Dec 9, 2023
@webknjaz
Copy link

webknjaz commented Jan 3, 2025

This is no longer an issue in modern versions of Firefox and Chromium.

@strarsis I've found that this is still an issue with style="filter:url(#filter2753)" but it does indeed work when converted into filter="url(#filter2753)".

@webknjaz
Copy link

webknjaz commented Jan 3, 2025

Posted too soon. No, it doesn't work. Only the class workaround works for me: tox-dev/tox#3465. Example of an SVG that breaks in FF: /~https://github.com/tox-dev/tox/blob/e3e77a6/docs/_static/img/tox.svg.

@strarsis
Copy link
Contributor

strarsis commented Jan 3, 2025

@webknjaz, @SethFalco: So re-open the issue and re-evaluate the associated PR (#733)?

webknjaz added a commit to webknjaz/tox that referenced this issue Jan 16, 2025
It appears that Firefox has bugs around interpreting `<feBlend>`
filters in SVG documents. This makes it render the logo as a
transparent image in the docs, both in the mobile and the desktop
versions.

This patch applies a workaround [[1]] found on the internet to make it
work without waiting for Firefox to fix their bug.

Resolves tox-dev#3465.

[1]: svg/svgo#732
gaborbernat pushed a commit to tox-dev/tox that referenced this issue Jan 16, 2025
It appears that Firefox has bugs around interpreting `<feBlend>`
filters in SVG documents. This makes it render the logo as a
transparent image in the docs, both in the mobile and the desktop
versions.

This patch applies a workaround [[1]] found on the internet to make it
work without waiting for Firefox to fix their bug.

Resolves #3465.

[1]: svg/svgo#732
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants