People are proposing all sorts of extensions to CSS for fancy
presentational effects --- gradients, canvas backgrounds, masks, and
so on. I think this is unwieldy and duplication of effort. Instead I'd
just like the SVG CSS properties 'filter', 'mask', 'clip-path', and
'fill' to Just Work on non-SVG content --- making the full power of
SVG paint servers and effects available to HTML content. And I'd like
a way to specify any element as an 'image' source for CSS 'background'
and other properties ... could be as simple as url(#element).
The biggest problem with this is making the necessary SVG fragments
available in an HTML document. Using HTML5's proposed parsing
extensions, or just XHTML, you could including the SVG fragments in
the underlying document, but that's clumsy if you're using the same
stylesheet in many documents.
A better approach would be to give the stylesheet an accompanying .svg
file and use external references to that SVG file. So foo.css would
contain "filter:url(foo.svg#bar)". That would work pretty well if we
can load the file once per base document and resolve all references to
foo.svg to that same loaded document. Unfortunately the spec
http://www.w3.org/TR/SVG/struct.html#URIReference doesn't say anything
about this but perhaps that just means we can interpret it the way we
want.
An additional issue is that we'd like to be able to manipulate the
contents of foo.svg using the DOM or declarative animation. So one
random idea is to expose a DOM API, analogous to the CSSOM stylesheet
API, that lets you get the contentDocument of all same-origin
referenced content documents.
Any thoughts?
Rob
I don't know what "fill" would mean for a non-SVG element, but it sounds
like a pretty reasonable approach in general. You just have to define for
each property what exactly it means when applied to a CSS box.
> And I'd like a way to specify any element as an 'image' source for CSS
> 'background' > and other properties ... could be as simple as url(#element).
>
> The biggest problem with this is making the necessary SVG fragments
> available in an HTML document. Using HTML5's proposed parsing
> extensions, or just XHTML, you could including the SVG fragments in
> the underlying document, but that's clumsy if you're using the same
> stylesheet in many documents.
>
> A better approach would be to give the stylesheet an accompanying .svg
> file and use external references to that SVG file. So foo.css would
> contain "filter:url(foo.svg#bar)". That would work pretty well if we
> can load the file once per base document and resolve all references to
> foo.svg to that same loaded document. Unfortunately the spec
> http://www.w3.org/TR/SVG/struct.html#URIReference doesn't say anything
> about this but perhaps that just means we can interpret it the way we
> want.
I think that makes a lot of sense, but you'd have to define what happens
if I reference e.g. an SVG <rect> element for my background-image. What
are the intrinsic dimensions here? What happens if I reference an SVG font
element? Or a <text> element? A gradient? A filter? Some of these make
sense and some of them don't. Whether they're defined to do something useful
or defined to be ignored, they all need to be defined explicitly one way
or another.
~fantasai
Right. For 'fill', 'mask', 'clip-path' and 'filter', which normally
apply to SVG geometry elements, you could just say that each CSS
border-box establishes a viewport whose size is the size of the border-
box, scaled so that 1 user unit is 1 CSS pixel. That would handle most
cases, although you might want something a bit more clever for
elements that have broken horizontally or vertically, offsetting the
viewport in the progression direction by the amount of progression.
> I think that makes a lot of sense, but you'd have to define what happens
> if I reference e.g. an SVG <rect> element for my background-image. What
> are the intrinsic dimensions here? What happens if I reference an SVG font
> element? Or a <text> element? A gradient? A filter? Some of these make
> sense and some of them don't. Whether they're defined to do something useful
> or defined to be ignored, they all need to be defined explicitly one way
> or another.
For background(#id), you would only be able to usefully reference
elements that actually render something. So referencing gradients,
fonts and filters would do nothing. For SVG geometry elements you'd
establish a viewport the same way as above.
Rob
On Apr 25, 6:05 pm, "rob...@ocallahan.org" <rocalla...@gmail.com>
wrote:
> I wasn't sure whether to blog about this but I thought I might as well
> start a little conversation here first...
>
> People are proposing all sorts of extensions to CSS for fancy
> presentational effects --- gradients, canvas backgrounds, masks, and
> so on. I think this is unwieldy and duplication of effort.
Do you mean unwieldy to authors or unwieldy to implementors?
For reference: I just checked and the patch to add CSS masking added
191 lines of code to WebKit, excluding the ChangeLog entry. To compare
to another somewhat duplicative piece of functionality, we have over
8000 lines of code specific to SVG text support (that's excluding
generic text layout and font code). So I don't think it is that big a
deal for implementors.
> Instead I'd just like the SVG CSS properties 'filter', 'mask', 'clip-path', and
> 'fill' to Just Work on non-SVG content --- making the full power of
> SVG paint servers and effects available to HTML content. And I'd like
> a way to specify any element as an 'image' source for CSS 'background'
> and other properties ... could be as simple as url(#element).
These would be neat features and I think Opera does this already.
> Any thoughts?
In general, I don't think the "SVG already does this" argument holds
much water. SVG does text, hyperlinking and inline inclusion of bitmap
images, features that were already in HTML, and this is not
unreasonable. These things are basic, and just as applicable to vector
graphics on the Web as to hypertext.
So, even with the ability to use SVG styling with HTML, I think a
native CSS way to do it is still desirable. Gradients and masks are,
much like shadows and rounded corners, pretty basic effects that are
well supported by underlying graphics libraries. It shouldn't be
mandatory to reference them from a separate SVG document (with its own
SVG DOM and presumably render tree) to use them in CSS.
While SVG is great as a markup language for scalable vector graphics,
I don't think it works so well as a styling language for other markup
languages. It was never designed for that.
Regards,
Maciej
mm, there are various ways you might want to handle that. See background-break.
http://www.w3.org/TR/css3-background/#the-background-break
>> I think that makes a lot of sense, but you'd have to define what happens
>> if I reference e.g. an SVG <rect> element for my background-image. What
>> are the intrinsic dimensions here? What happens if I reference an SVG font
>> element? Or a <text> element? A gradient? A filter? Some of these make
>> sense and some of them don't. Whether they're defined to do something useful
>> or defined to be ignored, they all need to be defined explicitly one way
>> or another.
>
> For background(#id), you would only be able to usefully reference
> elements that actually render something. So referencing gradients,
> fonts and filters would do nothing. For SVG geometry elements you'd
> establish a viewport the same way as above.
I don't think SVG elements have a 'border-box' exactly.. How would you
determine whether the SVG element has an intrinsic size or only an
intrinsic ratio?
Referencing filters and gradients directly for a background might be
useful. The size of the box they apply to would be the same as for an
image with no intrinsic size or ratio.
~fantasai
You're quite welcome :-).
> On Apr 25, 6:05 pm, "rob...@ocallahan.org" <rocalla...@gmail.com>
> wrote:
>
> > I wasn't sure whether to blog about this but I thought I might as well
> > start a little conversation here first...
>
> > People are proposing all sorts of extensions to CSS for fancy
> > presentational effects --- gradients, canvas backgrounds, masks, and
> > so on. I think this is unwieldy and duplication of effort.
>
> Do you mean unwieldy to authors or unwieldy to implementors?
>
> For reference: I just checked and the patch to add CSS masking added
> 191 lines of code to WebKit, excluding the ChangeLog entry. To compare
> to another somewhat duplicative piece of functionality, we have over
> 8000 lines of code specific to SVG text support (that's excluding
> generic text layout and font code). So I don't think it is that big a
> deal for implementors.
If I'd designed SVG I'd have tried to make it share more with HTML and
CSS. But that's water under the bridge, it's hard to fix now.
The cost is not just the cost of the implementation, but also the work
required to spec out the features, the extra testing required, the
extra syntax that authors and tools must know.
> > Instead I'd just like the SVG CSS properties 'filter', 'mask', 'clip-path', and
> > 'fill' to Just Work on non-SVG content --- making the full power of
> > SVG paint servers and effects available to HTML content. And I'd like
> > a way to specify any element as an 'image' source for CSS 'background'
> > and other properties ... could be as simple as url(#element).
>
> These would be neat features and I think Opera does this already.
Glad you think so.
> In general, I don't think the "SVG already does this" argument holds
> much water. SVG does text, hyperlinking and inline inclusion of bitmap
> images, features that were already in HTML, and this is not
> unreasonable. These things are basic, and just as applicable to vector
> graphics on the Web as to hypertext.
>
> So, even with the ability to use SVG styling with HTML, I think a
> native CSS way to do it is still desirable. Gradients and masks are,
> much like shadows and rounded corners, pretty basic effects that are
> well supported by underlying graphics libraries. It shouldn't be
> mandatory to reference them from a separate SVG document (with its own
> SVG DOM and presumably render tree) to use them in CSS.
>
> While SVG is great as a markup language for scalable vector graphics,
> I don't think it works so well as a styling language for other markup
> languages. It was never designed for that.
True, it was not designed for that, more's the pity. I want to see how
apt it is for that purpose, and what might need to be done to make it
more suitable.
Duplication isn't my only concern here. I'm concerned that as we
strive for increasingly complex effects, CSS syntax struggles to cope.
It's hard to work with complex property values; we have no standard
object model to script them with. Authors end up banging strings
together which is tedious, fragile and slow. Even your CSS transitions
and animations proposals have no way to modify their components. Being
able to use XML fragments and the DOM seems like a win.
You say that gradients and masks are pretty basic effects. Even if
that's true (I'm not convinced about masks, at least), it won't end
there. Authors will ask for small enhancements, and the path of least
resistance will be to add each one in turn as a new CSS property or
value. For my taste, CSS already tends too far towards a grab-bag of
complex features instead of a small set of composable primitives.
Rob
OK. I'll forward my comment about background-break to www-style.
> > For background(#id), you would only be able to usefully reference
> > elements that actually render something. So referencing gradients,
> > fonts and filters would do nothing. For SVG geometry elements you'd
> > establish a viewport the same way as above.
>
> I don't think SVG elements have a 'border-box' exactly.. How would you
> determine whether the SVG element has an intrinsic size or only an
> intrinsic ratio?
OK, let's render the SVG element in a viewport established by the
background clip area.
> Referencing filters and gradients directly for a background might be
> useful. The size of the box they apply to would be the same as for an
> image with no intrinsic size or ratio.
Not for filters. For gradients, maybe. That would be a separate
feature.
Rob
Note that SVG Tiny 1.2 does say that these URI references should result
in the document being loaded just the once:
http://www.w3.org/TR/SVGMobile12/linking.html#externalReferences
Since in SVG 1.1 external documents couldn't be manipulated (scripts
didn't run, there was no way to get access to the corresponding Document
object), this didn't matter too much. I think it would be safe for SVG
documents referenced by CSS properties in HTML to be shared.
--
Cameron McCormack, http://mcc.id.au/
xmpp:hey...@jabber.org ▪ ICQ 26955922 ▪ MSN c...@mcc.id.au
Ah, that's great to know! Thanks!
Rob
Thanks, it's a good comment. :)
>>> For background(#id), you would only be able to usefully reference
>>> elements that actually render something. So referencing gradients,
>>> fonts and filters would do nothing. For SVG geometry elements you'd
>>> establish a viewport the same way as above.
>>>
>> I don't think SVG elements have a 'border-box' exactly.. How would you
>> determine whether the SVG element has an intrinsic size or only an
>> intrinsic ratio?
>
> OK, let's render the SVG element in a viewport established by the
> background clip area.
I don't think that'll do anything useful. What are you expecting it
to do?
~fantasai
<svg viewBox="0 0 1000 1000" id="b">
<rect x="0" y="0" width="500" height="500" fill="magenta"/>
<rect x="500" y="500" width="500" height="500" fill="cyan"/>
</svg>
<p style="background: url(#b)">Hello Kitty</p>
Since the default value of preserveAspectRatio is "xMidYMid", this
should draw two small-ish squares in the centre of the <p>. Right?
Rob
Ok, the effect of that is very well defined in CSS if we take
the <svg> element as the root of the SVG image. It makes sense
to behave the same way if we reference the <svg> element with a
fragment identifier, I agree.
The question I had was, what if id="b" is on the <rect> element
instead?
~fantasai
We could just disallow that, just like a naked <rect> without an
enclosing <svg> is disallowed.
Or we could allow it and say it behaves as if it was wrapped in an
<svg> with no 'viewBox'. So an example would be
<rect x="0" y="0" width="100%" height="100%" fill="magenta" id="b"/>
<p style="background: url(#b)">Hello Kitty</p>
Rob
I agree that "SVG already does this" on its own isn't enough of an
argument. It's definitely useful to have some set of common operations
available directly through CSS, but I think more complex things are
better handled through the use of referencing an external resource, such
as an SVG file or an SVG element.
Another way to look at it would be that using SVG resources is the
default solution to the problem space, but let CSS provide some
convenience shortcuts to handle the most common cases.
This still leaves the question of what the common cases are of course...
One area where I think CSS could benefit from this is when doing page
headers and page footers, which currently have syntax that is both
complex and inadequate.
/ Jonas
Restricting internal image references to <svg> elements seems like
reasonable idea to me. Keeps things simple.
Any objections here or should we find an SVG person to pester about
writing a spec? :)
~fantasai
I want to have a prototype implementation to experiment with before
writing a spec. But I definitely want a spec since everyone seems to
agree this would be good to have.
Rob
Wrt <svg> elements without a viewbox, it might be reasonable to inherit
the viewbox of the nearest ancestor <svg> rather than to assume no
viewbox. I don't know; just something to consider.
~fantasai
<p style="fill: url(#MyGradient);">Foo</p>
Will the text be filled, or the background of the p element? Is it
possible to instead use something like:
<p style="color: url(file.svg#MyGradient); background-color:
url(file.svg#MyOtherGradient); background-image... etc.">Foo</p>
That seems... clearer to me, and more in line with what people are
used to. How hard would it be to allow these values on HTML CSS where
possible?
Turns out we don't want to use the 'fill' property, since 'fill'
inherits.
Creating a new color or image value, e.g. "paint(foo.svg#bar)", is
probably the way to go.
Rob
Turns out this is not a good way to go for filters. The slice-and-dice
approach will produce terrible results for filters that aren't just
per-pixel transformations, e.g. shadows. background-break:bounding-box
is the only value that makes sense there IMHO, so we should just make
that the only behaviour.
Rob
I can see shadows being quite strange for 'continuous', but I don't
see how they make a case for 'bounding-box' vs. 'each-box'.
(I'd also note that we implement background-break, for inlines only,
as -moz-background-inline-policy.)
It seems like use of gradients for backgrounds ought to obey
background-break, though.
-David
--
L. David Baron http://dbaron.org/
Mozilla Corporation http://www.mozilla.com/
You don't want each box to have independent overlapping shadows.
It should work like 'opacity', where the boxes for an element are
rendered as a group, then we do the filter effects.
> It seems like use of gradients for backgrounds ought to obey
> background-break, though.
Yeah. That's a different issue, SVG paint-servers for backgrounds need
to work like images.
Unfortunately this turns out to create a rather nasty reflow problem
(although it may be Gecko-specific).
Suppose we apply a filter to an inline element with two frames. The
filter could fill its filter region, which could be any size relative
to the objectBoundingBox or in userSpaceOnUse units. In particular, it
could be arbitrarily larger than the objectBoundingBox. Exactly how
those units are interpreted for inline frames is something that we
need to hammer out a spec for (I have stuff in my tree which I'll talk
about later), but it doesn't matter for this discussion. The problem
is, it's not clear how to allocate "excess" area drawn by a filter for
a group of frames to the overflow areas of individual frames.
I think the only reasonable solution is to assign the filter's area to
the overflow area of the *last* continuation, because that's the only
frame where we can be sure that all the prev-in-flows have been
reflowed. The problem is, when nsFrame::FinishAndStoreOverflow is
called, we haven't placed the frame yet so we can't compute the
bounding-box of all the continuations properly.
I think the only way to fix this is to do some fairly major changes to
overflow area management. Changes that we want to do anyway to handle
tricky stuff like multi-continuation, relatively-positioned frames
with abs-pos children that use "bottom", and so that we can adjust
overflow areas without reflow, and so that we can split the "overflow
area" concept up into "union of border-boxes of frame subtree modulo
clipping" from "area drawn to by a frame subtree".
For now, I think I'll just hack it so that overflow areas for each
filtered frame are computed as if that frame alone was the subject of
the filter. That will work for a lot of common cases, including all
cases where the filter does only per-pixel processing and when there
is only one frame for a filtered element.
Rob
Rob