SVG adds style.filter – now, where have we seen that before?

We've been working away on Opera's SVG support for a while.
Recently, integrating SVG-specific CSS properties into the DOM implementation caused an unexpected problem: the "filter" concept in SVG styling and IE's proprietary "filter" suddenly exist in the same namespace – the CSSStyleDeclaration interface.

If that was greek to you, here's a translation: in SVG, you can do something like

<circle style="filter: url(#someCoolEffectDefinedOverThere)">

and IE allows you to do something like

<div style="filter: alpha(opacity=50)">

This means that a browser supporting SVG will define element.style.filter – and all versions of IE you want to care about also define element.style.filter. So if you're writing a generic script and see a random element with a style.filter property – how do you know what filter syntax is supported?

We discovered this problem due to failing opacity effects – scripts doing

if(typeof element.style.filter != 'undefined'){
 // IE syntax
}else{
 // standards-compliant syntax
}

suddenly saw style.filter defined and started giving us IE-code. Seems Firefox is about to come across those compatibility problems too..

Of course it raises a red flag when we add something that causes new compatibility issues. It has been raised as an issue with the SVG working group, who discussed it and decided to sweep the issue under the carpet with an informative warning in the spec.

For compatibility, we're considering hiding style.filter like we hide document.all. That is not a good solution, however. We want scripts to be able to detect that SVG filters can be manipulated from JavaScript, and we want them to do so through good, old, best-practice object detection.

Microsoft will actually save us by re-naming filter to ms-filter. That's excellent, if late, and they still have the problem that millions of existing sites use IE-style CSS filters. It would have been the perfect solution had they done it back when their CSS filters were invented.. I still welcome their initiative, but at this point it probably won't make any difference for many years ahead. Right now, we're stuck with confusion. I'm worried that we're breaking established best-practice (object detection) and forcing people down the dirty road of browser sniffing. I think it will be confusing that HTML elements get a "filter" property that will presumably only work when set on SVG elements.

Now.. changing SVG's footprint in the CSS DOM wouldn't suffer from legacy content problems. My preferred solution would be to make sure "filter" only appears on the .style object of real SVG elements, and that it's named svgFilter in the DOM rather than just "filter", to make it easier to detect.

What do you all think?

30 thoughts on “SVG adds style.filter – now, where have we seen that before?

  1. I think svgFilter sounds about right as a DOM attribute. It would be just another irregular name, like labelFor or className (albeit for different reasons).

  2. 😥 Don't believe MS! :'(They will make the oposite, as usually. It will cause only new problems. 😥 Use differente syntax or keyword-name!!! Please

  3. Was this not thought of when SVG filters were being added to the spec? Seems a fairly obvious thing to miss – they were surely aware of the filter property in IE…

  4. You'd think a lot of the ridiculous stuff in SVG 1.0 and 1.1 would have been obvious, too, but there you go. I'm not at all surprised they waved this off, as to me it seemed like there was an expectation from the SVG working group that SVG would somehow live in its own little pocket universe and that the extant Web didn't matter.The realities of SVG adoption on the Web and inline in Web browsers at large has really changed the game, no doubt.

  5. … decided to sweep the issue under the carpet with an informative warning in the spec.

    jeah, that will fix it *rolleyes* :ko:+1 to your prefered solution 🙂

  6. The main problem with the preferred solution is that CSSStyleDeclaration is not just used on elements from a single namespace. It exists here:HTMLDivElement.style -> CSSStyleDeclarationSVGCircleElement.style -> CSSStyleDeclarationCSSStyleRule.style -> CSSStyleDeclarationgetComputedStyle() -> CSSStyleDeclarationIn particular, CSSStyleRule.style poses a problem, since it is what is used by DOM StyleSheets to represent each style rule in the stylesheet. A stylesheet can be applied to multiple documents or namespaces at the same time, so it can apply to a HTMLDivElement at the same time as a SVGCircleElement. That means that both the SVGCircleElement.style and CSSStyleRule.style would need to use the same CSSStyleDeclaration prototype, so the property was correctly exposed within a stylesheet. The only way I can see this working is for CSSStyleDeclaration (by default) to use a hidden 'filter' property, then have SVGCircleElement.style and CSSStyleRule.style use a special custom one that is not exposed for custom prototyping (CompleteCSSStyleDeclaration?) that inherits from CSSStyleDeclaration (including its .toString), and then also provides a visible 'filter' property.I am not sure how it should work with getComputedStyle, as it would need to cope with all of those scripts (jQuery, for example) that frequently read all computed properties, and change the element's properties accordingly.Are there any obvious problems with using the CompleteCSSStyleDeclaration approach? The first one I can see is that if someone uses CSSStyleDeclaration.prototype.filter, it won't work properly.This all feels very messy, of course.

  7. +1 to your solutionMicrosoft's solution is useless because it's only for IE8 (if I understood correctly), but where I work we are still expected to support IE6 and IE7 (since most people companies here still use IE6 :bomb: ), and according to microsoft solution we would still need 'filter' for IE6 :irked:

  8. My understanding is that SVG was developed by the W3C without consideration of the real-world web, hence why they would introduce a property whose name collided with a non-vendor-prefixed extension created by the most widely used browser engine of the time. This is about par for the course, really, with the W3C, and it's a notable part of the impetus for forming WHATWG versus simply remaining entirely within the W3C.I tentatively think svgFilter makes sense. Regarding not exposing it on non-SVG content, do consider that Mozilla has proposed extending its use into non-SVG content and has implemented such as an extension. It doesn't seem unreasonable to think this may eventually be standardized more broadly; a sui generis decision (I think this culling of properties in this manner is without precedent) to remove filter from non-SVG content seems pretty odd and perhaps even premature.

  9. Robert Longson writes:Firefox has implemented filters on html content so we do want filter as a style of non SVG objects. IMHO naming it svgFilter will confuse people and we'll just get bugs saying the filter property doesn't work.However, we've already written the code to hide filters and we may still go down that route depending on the feedback from the next Firefox 3.7 alpha – alpha 2.

  10. @Tarquin: This could be done by an implementation, though, couldn't it?Do not override .filter in CompleteCSSStyleDeclaration (make it 'magic' if necessary). By default, CSSStyleDeclaration.prototype.filter is 'invisible'. If the user changes the property, make it visible (and inherit that to CompleteCSSStyleDeclaration). That should work.Of course a user could break his own content that way if he relies on the IE filter property elsewhere, but that's his own fault, isn't it?

  11. Tarquin, good point about the CSSStyleDeclaration interface usage.Robert Longson: cool idea to extend it to HTML elements.

    IMHO naming it svgFilter will confuse people

    I think on the contrary – isn't that a fairly obvious way to signal that we're dealing with the "filter" syntax from the SVG spec? There is presedence for re-naming things in the DOM so that it doesn't conflict with the host language, for example when attributes have same name as an ECMAScript reserved word.Such naming would also work better if other languages define "filter" style and are integrated into HTML. For example if MathML wants to use CSS to define number formatting, they might invent something like 'filter:"### ###.##"'.zoquete: don't know how hypotethical namespaces in CSS would be integrated with the DOM interfaces. So the answer is "it depends.." 🙂

  12. The proposed "preferred solution" – limiting it to the style object on SVG elements – would preclude the addition of it to HTML (which Mozilla are already experimenting with, and where it could be potentially just as useful as it's use in SVG).Naming it svgFilter would confuse people if it were added to HTML, and also just generally be a hackish and unconventional naming system.Renaming properties to avoid clashes with ECMAScript reserved words doesn't generally restrict those properties to be tied to a certain language or usage in future – renaming class to className is fine because "name" is a generic word that doesn't imply anything about the behaviour of html class attributes, "SVG" implies a lot.Surely the best (only good?) solution would be to change it in spec. Obviously SVG1.1 is a recommendation, and therefore set in stone, but there are sections of previous W3C specs that have never been implemented (things like DOM2's createCSSStylesheet that was only ever added to Konqueror) – couldn't filter be changed to something different for SVG1.2 and SVG1.1 just skipped over by implementors?

  13. You can apply (theoretically) svg filters to html elements. IMO, the only acceptable solution would be to rename it to svgFilter or something.

  14. Couldn't this be solved by a code snippet from a hacker like Dean Edwards that figures out whether the filter property used is the IE version or the svg version?edit: We could even hold a contest to create this snippet.That way, we can avoid rewriting browsers, since web devs will be able to just drop a line of code into their product and be done with it. If this were published on ALA, maybe it would gain even more traction.

  15. Another point, isn't this just as much of an issue outside of javascript? e.g.:

    <circle class="bob" ... />
    <div class="bob" ... > ... </div>
    <style>
    .bob{ filter:url(#someCoolEffectDefinedOverThere); }
    ... ...
    .bob{ filter:alpha(opacity=50); }
    </style>
    

    ?
    Edit: Excessive linespacing above seems a myOpera editor bug – inserts breaks into pre tags..

  16. Originally posted by João Eiras:

    You can apply (theoretically) svg filters to html elements

    I actually thought that was the whole point of this: svg applied to html.https://developer.mozilla.org/En/Applying_SVG_effects_to_HTML_contenthttps://developer.mozilla.org/web-tech/2008/09/15/svg-effects-for-html-content/BONUS: svg + css3 transformations + + filter:url(…) = http://people.mozilla.com/~prouget/demos/round/index.xhtml

    Is that not where we're going with this? I'd be curious to know if those have all been sent to w3c for discussion and standardization.

  17. Jeff Schiller writes:I agree that we're in a bad situation, but it's really a temporary one – IE8 is already the most-deployed browser, which means that only about 30% of browser users will actually see the old-style IE CSS filter syntax, right?Authors need to update to -ms-filter now.And I agree with other comments: SVG Filters applied to HTML content is going to rock once all browsers start supporting it.

  18. Originally posted by anonymous:

    I agree that we're in a bad situation, but it's really a temporary one –

    All experience tells me that we'll struggle with this problem for YEARS due to object detection in legacy content. Further, SVG-supporting browser vendors are likely to work around that in the hackish "hide style.filter" way, breaking object detection for future script and probably making authors resort to browser sniffing.Originally posted by anonymous:

    But I think you should do this:if(typeof element.filters != 'undefined'){ // IE syntax

    I don't think you really paid attention to what the blog post was about :)This is one example of a script that will no longer work as expected (unless browsers do weird things to work around your scripting).Somebody suggesting to do the wrong thing after presumably having read this article might indicate just how much this is going to confuse people…

  19. Originally posted by Jeff Schiller:

    Authors need to update to -ms-filter now.

    Getting them to update to -ms-filter is one thing, getting them to drop filter as well is another – most will simply keep both for compatibility, particularly if they're unaware of this issue as they'll see no reason not to.Consider that even today we have many sites that, while some may have been updated to include modern standards-compliant code, still have IE4 compat code in their scripts that they've just never bothered removing.

  20. Robert O'Callahan writes:Hallvord, we're aware of the problem, but none of the solutions we considered are very good. Naming it svgFilter would be confusing (not consistent with other properties, and 'filter' works on non-SVG elements in Gecko), cssFilter would be consistent with cssFloat but still confusing, making style.filter undetectable would be ugly and breaks feature detection… Got any better ideas?We've deliberately turned this on early in a development cycle so we've got some time to estimate the compatibility damage. If the damage isn't too great (and/or we can persuade some sites to fix their detection logic) then we can leave it this way and everybody wins — especially you, since we'll have fixed the problem for the Web at the cost of annoying our own users!

  21. Anonymous writes:Halvord,Have you looked closely at this code(posted by anonymous)if(typeof element.filters != 'undefined'){// IE syntax// See http://msdn.microsoft.com/en-us/library/ms537452(VS.85).aspx}else{// standards-compliant syntax}It actually works in Opera! And it IS different from the code you posted earlier. Have you read the page on the link ? Isn't the goal to filter out MS from the rest ?

  22. Originally posted by anonymous:

    Isn't the goal to filter out MS from the rest ?

    No. The post was about the implementation in the browser, not about how web developers should or shouldn't detect support. The code sample was merely one example of how they might fail to properly detect support – there are obviously ways to detect support successfully (as you've demonstrated) but that doesn't help the browser deal with those using the unsuccessful methods.

  23. Originally posted by anonymous:

    Have you looked closely at this code(posted by anonymous)if(typeof element.filters != 'undefined'){

    You're right, I didn't at first notice the plural form. This might help with the feature detection – sort of – except that all browsers supporting "SVG filters" will already have hidden style.filter when scripts get updated to pay attention to element.filters :-/

  24. Garrett Smith writes:This is one example of a script that will no longer work as expected (unless browsers do weird things to work around your scripting). Indeed they do.SVG filter has been implemented in Safari for a few years now, as a special string value. Try it:javascript: var f = document.body.style.filter; alert([f, typeof f, f.length])Result:,undefined,0The style.filter property is present, the value is a string, and the typeof reports "undefined". This has been discussed on es-discuss and another (www-style?). It is considered by some to be a cleverly stupid design hack.

  25. Anonymous writes:Well, just found this blog after running across exactly the problem described above – our opacity functionality for image js/css image slideshows running in Firefox 4 beta just started running through the "IE hack code path" instead of the standards compliant path because their is now a elem.style.filter property.After an exhaustive search of the web looking for discussion of this issue – this blog seems to be the only one taking it seriously. There are SO MANY pages out there mentioning the "IE only filter property" and how to perform "best practice" object detection instead of browser sniffing to solve this problem that I believe this new incompatibility issue will be huge.Even mozilla's MDC docs still make no mention of it and simply recommend the same methods that will no longer work.So what will the new object detection pattern be for opacity now that simply checking for .filter no longer works?This seems to work for me (so far…):if (elem.style.filter != undefined && elem.filters != undefined) isIE = true;But how long since the other browsers add elem.filters? And then what? And why do the browsers not correctly report the filter string value, even when declared statically in the css? eg alert(elem.style.filter); In terms of Embrace,Extend,etc, MS was pretty clever (or lucky) to add .filter in the first place without a vendor-part to the name…

Leave a reply to lucideer Cancel reply