Bug 91790 - SVG Fragment Identifier With CSS Backgrounds
: SVG Fragment Identifier With CSS Backgrounds
Status: NEW
: WebKit
SVG
: 528+ (Nightly build)
: All Unspecified
: P2 Normal
Assigned To:
: http://jsfiddle.net/simurai/7GCGr/
:
:
: 91791
  Show dependency treegraph
 
Reported: 2012-07-19 15:02 PST by
Modified: 2014-02-26 13:55 PST (History)


Attachments
Version 13.0.1 of Firefox renders the SVG fragment identifier in CSS background correctly. (122.25 KB, image/png)
2012-07-19 15:02 PST, Ken Collins
no flags Details
Patch (8.64 KB, patch)
2014-02-25 09:37 PST, Antoine Quint
no flags Review Patch | Details | Formatted Diff | Diff


Note

You need to log in before you can comment on or make changes to this bug.


Description From 2012-07-19 15:02:57 PST
Created an attachment (id=153357) [details]
Version 13.0.1 of Firefox renders the SVG fragment identifier in CSS background correctly.

A upcoming technique for SVG sprites, dubbed stacks, has been described here. http://simurai.com/post/20251013889/svg-stacks

It relies on using an SVG fragment identifier (target) in the IRI. Tho Webkit supports this in many other places, it does not support the fragment identifier when used in a CSS background. Here is a JSFiddle linked form the above article that demonstrates the issue. http://jsfiddle.net/simurai/7GCGr/
------- Comment #1 From 2013-03-04 06:35:19 PST -------
SVG stacks will not be supported for CSS properties taking CSS Image values. This includes, but is not limited to, background-image, mask-image, border-image.

This is a resolution of the SVG and CSS WG to differ between resources (like SVG gradients, masks, clipPath) and image values during parse time of CSS. This is a security requirement to protect the users privacy and safety.

See following discussions for further information:
http://lists.w3.org/Archives/Public/www-style/2012Oct/0406.html
http://lists.w3.org/Archives/Public/www-style/2012Oct/0765.html



As an alternative, use SVG image sprites. They work exactly like normal image sprites.

For CSS properties:
Short-term: use background-position to shift your sprites
Long-term: the fragment identifier #xywh=0,0,100,100 will allow to get a sprite out of an image.

For image element:
Short-term: use the fragment identifier #viewbox(0,0,100,100)
Long-term: the fragment identifier #xywh=0,0,100,100 will allow to get a sprite out of an image.
------- Comment #2 From 2014-02-24 07:13:14 PST -------
Dirk, you say "This is a resolution of the SVG and CSS WG to differ between resources (like SVG gradients, masks, clipPath) and image values during parse time of CSS. This is a security requirement to protect the users privacy and safety."

In the example, the reference is not to a paint server, but to an SVG image which should respect the :target pseudo-class to display only the element referenced by the identifier in the URL. It seems odd to me that opening http://example.com/sprite.svg#foo would render something if opened as a standalone document but wouldn't if referenced as a CSS background-image.

I'll also note that the <img src=""> fails as well. I think both of these should just work…
------- Comment #3 From 2014-02-24 08:03:09 PST -------
(In reply to comment #2)
> Dirk, you say "This is a resolution of the SVG and CSS WG to differ between resources (like SVG gradients, masks, clipPath) and image values during parse time of CSS. This is a security requirement to protect the users privacy and safety."
> 
> In the example, the reference is not to a paint server, but to an SVG image which should respect the :target pseudo-class to display only the element referenced by the identifier in the URL. It seems odd to me that opening http://example.com/sprite.svg#foo would render something if opened as a standalone document but wouldn't if referenced as a CSS background-image.
> 
> I'll also note that the <img src=""> fails as well. I think both of these should just work…

The resolution changed. The UA doesn't deal with it at parse time anymore. (Which makes implementing URL correctly a bit harder in WebKit for CSS though.)

Instead, all resources (image or SVG resources like <linearGradient>, <clipPath> or <mask>) are loaded with the same restrictions. On rendering we shall decide if we interpret the resources as image or SVG resources.

The restrictions say that the resource in question is not allowed to fetch any other resources (CSS, images or scripts) and is not allowed to execute scripts.

This keep the door open for SVG stacks IMO. Even if me comments was correct at the time, it isn't anymore.

Note that the original resolution just affected CSS's url() function. <img src=""> was never affected.

Reopening the bug.
------- Comment #4 From 2014-02-25 07:02:20 PST -------
When loading an SVG file standalone, the fragment identifier is parsed and results in a call to Document::setCSSTarget() as a result of shouldPerformFragmentNavigation() returning true in FrameLoader::loadWithDocumentLoader(). This doesn't happen when loading the same URL through an <img>.
------- Comment #5 From 2014-02-25 07:56:15 PST -------
I think the problem actually stems from the fact that when we create the SVGDocument for an SVG image loaded by an <img>, SVGImage::dataChanged() is called higher up in the call stack and calls the following line:

        loader.activeDocumentLoader()->writer().begin(URL()); // create the empty document

Note the empty URL, which eventually causes us to bail in FrameView::scrollToFragment() when we notice that we don't have a fragment identifier for the URL nor do we have a pre-set CSS target.

I think we might be able to deal with this in SVGImage::dataChanged() by getting the loaded resource's URL through the image observer's resource request.
------- Comment #6 From 2014-02-25 09:12:46 PST -------
My proposed fix is to pass a new URL parameter when creating an SVGImage in CachedImage::createImage(). Patch coming up.
------- Comment #7 From 2014-02-25 09:37:10 PST -------
Created an attachment (id=225157) [details]
Patch
------- Comment #8 From 2014-02-25 10:20:27 PST -------
Hmm, as it turns out the original test case at http://jsfiddle.net/simurai/7GCGr/ isn't fixed, it seems SVG resources served through the network fail to load completely.
------- Comment #9 From 2014-02-26 06:18:36 PST -------
MemoryCache::removeFragmentIdentifierIfNeeded() is stripping the resource identifier when loading an SVG resource for an <img> element via HTTP:

URL MemoryCache::removeFragmentIdentifierIfNeeded(const URL& originalURL)
{
    if (!originalURL.hasFragmentIdentifier())
        return originalURL;
    // Strip away fragment identifier from HTTP URLs.
    // Data URLs must be unmodified. For file and custom URLs clients may expect resources 
    // to be unique even when they differ by the fragment identifier only.
    if (!originalURL.protocolIsInHTTPFamily())
        return originalURL;
    URL url = originalURL;
    url.removeFragmentIdentifier();
    return url;
}
------- Comment #10 From 2014-02-26 13:30:21 PST -------
(From update of attachment 225157 [details])
Marking my original patch as obsolete, it would only work with non-HTTP URLs (file and custom protocols). A complete patch will be more complex, I'll break this into individual tasks for the various paths needed, starting with <img src> support.
------- Comment #11 From 2014-02-26 13:55:16 PST -------
I'll start with https://bugs.webkit.org/show_bug.cgi?id=129387 to make fragment identifiers work with SVG images via <img>.