With SVG being integrated more and more into HTML5, both included via <object>
and <img>
elements, and inline in the same document, some natural questions about SVG and CSS are receiving more focus. This includes box model questions like background and border, and pointer events.
I’m interested in comments from the community on what direction SVG should take.
It’s pretty clear that the intent of the SVG 1.1 spec was that the box-model CSS properties must not apply to any SVG elements. In addition to what the spec states on the subject, my conversations with people who participated in the SVG WG at the time leave me with no doubt on the matter.
The question is, is that the behavior we want? How hard or easy is it to change that in modern SVG+HTML+CSS implementations? What is most useful and intuitive for content authors?
In my opinion, we could specify that some aspects of the box model apply without screwing with SVG’s coordinate-based positioning system. Here are my initial thoughts on some specific properties:
Borders
A borders is different than a stroke. An SVG element, including any graphical (<rect>
, <circle>
, <path>
, etc.) or container element (<svg>
, <g>
) can have both a stroke (which conforms to the geometry) and a border (which conforms to the element’s bounding box). A common use case is setting the graphics apart from other content, or doing mouseover highlights of an SVG element; for example, when I mouse over or focus a circle, it would be much nicer, and just as semantic, to simply have a CSS property draw a rectangle around that element as a highlight than for me to generate a rectangle based on the bbox and insert that into the DOM, keep a pointer to it, then remove it when I mouse out.
Paint servers and similar resources (gradients, filters, etc.) should not have any border. Note: <defs>
is a non-rendering element, akin to <head>
, so no border would be visible for that either, but if the content of a <defs>
is <use>
d, any border properties would apply in the same manner as for other properties.
The border should not have any effect on the layout or rendering; it would be strictly visual.
Margin
No effect on SVG content, but may affect HTML content around that SVG content. So, an <svg>
element with 'margin: 20px;'
has a 20-pixel gap around the SVG content, just as if it were <img style="margin: 20px;"/>
Alternately, maybe margin only has an effect for <svg>
elements; that might be simpler to specify, implement, and understand for content authors.
Padding
Again, this has no effect on SVG content, but it does affect how the border is drawn. This would be a nice way to compensate for thick stroke widths.
Background
A background is different than a fill. Background is much the same as border; it is a rectangle (modulo the border-radius effects) around the shape, based on its geometric bounding box, taking into account padding.
By default, there should be no background color, including for the <svg>
element. Right now, there is a WebKit bug in Chrome and Safari which renders a white, non-transparent background for SVG fragments or documents; this is a major pain for any content creators trying to use SVG, much like the old Internet Explorer bug on transparency in PNGs. I hope it receives some attention from the WebKit developers soon.
SVG Tiny 1.2 defines a 'viewport-fill'
and 'viewport-fill-opacity'
. I think those should be deprecated in favor of 'background'
properties; I have no opinion on which should have precedence… maybe they should be seen as aliases of 'background'
, if that makes it simpler.
A background on SVG content raises the question of pointer events, which is also relevant to borders.
Pointer Events
Should pointer events on the border or background fire on the element itself? I think that the default should be “no”, just to be safe and consistent with older SVG content, but I could easily be persuaded to reverse that. Either way, there should be a new property or set of properties that can modify this, in a manner consistent with how CSS is defining 'pointer-events'
.
This touches on the question, asked in a related thread, on whether the <svg>
element, by default, should be a proximal event target for pointer events. My answer on that is a pretty firm “no”; if you want to have it as an event target, give it a background, or change the 'pointer-events'
value.
Questions
A few high level questions:
- Is this a change from SVG 1.1 and SVG Tiny 1.2? Yes.
- Is this backwards compatible? Kind of. It introduces new behavior that is not consistent with past behavior, but doesn’t explicitly change very much.
- Does this break existing content? Very doubtful.
- Is this intuitive for content authors? My intuition says yes.
- Does this match existing implementations? Some, at least.
- Does this provide value for content authors? Yes.
- Does this make it harder to implement? I don’t know; I suspect it makes it easier for at least some implementations.
- Would defining this improve interoperability? Yes.
Conclusion
I propose we change SVG 2 to explicitly define this behavior. As the editor of the HTML5 spec, Hixie seems to imply that this is not for HTML5 to define, and I tend to agree with that, though maybe some informative mention in the HTML5 or CSS specs for how SVG treats margins and padding might be appropriate. We recently formally closed the Compound Document Formats Working Group, which was formed to look at exactly these sorts of questions, and published its specifications as Working Group Notes for posterity; we wanted to be clear about its status. The CDF WG succumbed to the politics around the reformation of the HTML WG, and probably to good effect overall; but in its absence, we still need to resolve these questions by cooperation between the various groups involved.
I don’t think this should be any different in standalone SVG files than in SVG files referenced or inlined in HTML. That would be very unintuitive, in my opinion.
If this is not controversial, I would be happy to put any or all of this in the SVG Integration spec, which is one of the foundations of SVG 2. If someone disagrees with this, we’ll have to talk about it before I start editing the spec. In either case, it would need to be fleshed out some… I’m probably glossing over some possible stumbling blocks in the box model, which I’d appreciate feedback on.
Please leave a comment if you like my suggestions, if you see a flaw, or have a better suggestion.
Update:
Just to show what I’m talking about, I created a sample. Here is a good example of a bad example; below are 3 instance of the same SVG with the same CSS background and border values, with a border width of 2px. The first 2 are external files referenced as objects, the third is inline in the HTML (you won’t see this one unless you are using preview releases of Firefox 4, WebKit, or IE9); the second image also has a padding and margin of 10px.
I tested this in several browsers, and in the referenced cases, the border width increases the image size, spawning scrollbars; I don’t think that’s a good outcome… it should clip the border, just as it does for any graphical overflow… borders should not contribute to the geometry of SVG images.
In the second case, where I added padding, the argument is less clear, but I still believe that for referenced content, the border and background should not displace the rendered graphics, and should be clipped. For inline content, it would make sense for the padding and margin to be visible in the rendered document, but it should still not change the geometry of the SVG.
We’d need to specify this in order for it to behave the same across browsers (and authoring tools). So, do people agree or disagree with my conlcusions?
Is there really a need to support box model stuff on anything other than the root <svg> (which is already special in all sorts of ways)?
Boris, unless it’s difficult to implement, I don’t see a reason not to. One of our goals is to make SVG easier to use for developers and designers already skilled in HTML and CSS, and it seems unintuitive to me that borders and backgrounds aren’t allowed on SVG elements; special-casing the root element seems equally confusing and frustrating. Is there some reason not to allow these box model properties to apply to general content?
I am with you on adding the border property which makes sense since a user can interact with an SVG element. It’s a good UI feedback.
The background property I am not so sure. Are you thinking about multiple backgrounds like CSS3 or just a single background?
Thinking out loud, one way is to keep the SVG spec. slim (no CSS, backgrounds etc.) and then wrap it in another container (div?) which will get styled/referenced. That seems a bit counter-intuitive since as a web developer I can’t see myself putting a SVG element on a page and not wanting some control over where and how it renders and I can’t see a designer not doing weird things with it either.
I think I side with the IE9 team on their interpretation of how this will work in the wild.
I agree with Boris. On the outside of the rootmost svg element (for inline svg) or on the object/img/iframe (for referenced content), the css box model applies. On the inside, and for any child svg elements, the box model does not apply and therefore, borders and padding etc do not and should not apply.
Hi, Chris, as we discussed face-to-face, I should clarify that I didn’t mean we should inherit all the various aspects of the box model (like stacking context, etc.), just to think about the specific properties I mentioned: border, background, and some treatment of margin and padding.
From the group discussions, we determined that what I really want is not border, though, because that participates in the box model and “adds geometry”, as it were… what I really want is the ‘outline’ properties.
I think that the best case scenario would be to have our cake and eat it too. Â By default, I would argue that we do not want any CSS rules applying to SVG elements unless the rules are specific to those elements. Â SVG should be free flowing. Â If I handwrite a paper document and want to go back over it with a set of markers, I can add pictures and decor where-ever I please. Â SVG should be no different for web documents. Â I think that enforcing CSS rules on the SVG elements by default could hamper creativity.
I propose we go the optional route and let this be a property that can be set if it is preferred. Â CSS inherit: yes || no.
This also brings up another question. Â If I could have what I want and use SVG freely and as my heart desires within a document, what should the rendering order be? Â Should the page just render everything left to right top to bottom regardless of it being HTML or SVG or should all HTML elements be rendered first to ensure the fastest delivery of text content?