Sunday 28 October 2012
We have a large impending problem for CSS and SVG, and the solution may require breaking content using the "SVG Stack" image-bundling technique that's starting to become popular.
The problem arises because we want to unify support for images and SVG paint servers in CSS syntax. For example, we'd like CSS 'background', 'mask' and 'fill' properties to accept both SVG paint server values (e.g. SVG gradients and patterns), and CSS image values (such as CSS gradients and images). This seems like a significant improvement in both simplicity and power for Web authors.
The problem is that if we do this, then syntax such as 'background:url(foo.svg#abc)' becomes ambiguous. It could refer to either an SVG paint server element (such as a <pattern>) with ID "abc" in the external resource document "foo.svg", or an SVG image "foo.svg" in which we should make visible the element with ID "abc".
The obvious way to resolve this ambiguity would be to load the document foo.svg and check if the element with ID "abc" is an SVG paint server element. Unfortunately that is very difficult to do because we load external resource documents differently to SVG images and subject them to different constraints. For example, for security reasons external resource documents for paint servers are required to be same-origin with the main document --- in Gecko, at least, and we think the security reasons are good enough to require the same behavior in every browser. (Webkit hasn't addressed this yet because they don't support references to SVG paint servers in other documents.) On the other hand, we definitely can't disallow cross-origin SVG image loads. We really want to be able to determine the kind of load to perform before we start loading the document!
Relying on checking the kind of element a reference points to is also problematic if that can change dynamically. I don't actually know of a way that an SVG image or external resource document can cause the element referenced by a fragment identifier to change, but there are a lot of "near misses" --- for example, it would be possible if script was allowed to run in an SVG image or an external resource document, or if declarative animations could animate the 'id' attribute, or if we had a declarative Web feature for transclusions, or if <meta refresh> was supported in SVG images or external resource documents. If it turns out that the element referenced by a fragment identifier can change, then it doesn't really make sense to try to reload the document in a different way when such a change happens. (It might also be possible for the element referenced by a fragment identifier to depend on whether the document was loaded as an SVG image or an external resource document!)
Therefore I have proposed on www-svg and www-style that we inspect the URIs in a 'url()' value to determine whether to perform an external resource document load or an image load. A URI without a fragment identifier would be loaded as an image, but a URI with a fragment identifier that isn't obviously supposed to be part of an image (e.g. a Media Fragment URI) would have to be interpreted as a reference to an external resource document. This would work fine with almost all content out there, but would break SVG Stacks :-(. That is not good, but no-one has proposed a better solution yet.
If we do take this approach, we would probably have a workaround for SVG Stacks such as requiring them to use the "=" character in their fragment identifiers to make it clear the URI should be treated as an image load, not an external resource document reference.
I hope that this can be resolved at the upcoming W3C TPAC, since any solution needs concerted effort from browser vendors, and soon.