SVG:Sizing

From MozillaWiki
Jump to: navigation, search

Introduction

This page is an in-progress attempt of mine to make sense of viewport sizing for SVG content (the sizing of the rectangular area the SVG is given to draw into). You'd think it would be simple, what with one 'width' and one 'height' attribute. Unfortunately, there are a lot of other things to consider too, such as different unit types, omitted attribute(s), the CSS 'width', 'height', 'min-width', 'min-height', 'max-width', 'max-height' and 'background-image' properties, the 'viewBox' attribute, intrinsic width, height and aspect ratio, and whether the SVG is rendering standalone, embedded inline or embedded by reference. All add to the fun. In this document I'm only going to focus on a few important issues that I consider to be unresolved/troublesome and in need of further thought before implementation begins.

SVG width/height vs. CSS width/height

The effect of the CSS properties is reasonably well defined. An important question to answer is, what part do the SVG 'width', 'height' and 'viewBox' attributes play, and how do they interact with the CSS properties? It has become clear that SVG is to be treated as a replaced element in CSS contexts. It has also become clear that the intrinsic dimensions that the SVG must pass to the CSS replaced element algorithms are to come from the SVG 'width', 'height' and 'viewBox' attributes. However, current implementations (e.g. Opera 9.23) appear to treat the 'width' and 'height' attributes as presentation attributes and map them into style (i.e. translate them directly to CSS 'width' and 'height' properties). As it turns out, there are problems with both these approaches, and unfortunately the new text specifying SVG as a replaced element creates some horrible authoring gotchas (as currently worded).

goes against the letter of the specification, but actually honors the intent behind the letter.

The way SVG requires the 'width' and 'height' attributes to be overridden by xxx does not fit well with mapping into style where uses values are expected to be close/related to the specified values.

The former approach would have the advantage of being the most intuitive for authors. The latter approach solves the problem of the 'display' property (i.e. what you do with |display:inline;| on SVG), and unless the user sets only one of the CSS properties 'width' and 'height' on the SVG while also having 'width' and 'height' attributes, they won't notice a difference to the former approach (well, as long as percentage attribute values are intrinsic).

Common ground

It's worth stating a few of my assumptions that everyone now seems to have agreed on:

1) The 'width' and 'height' attributes are the only source of intrinsic width and height values.

2) The 'viewBox' attribute specifies an intrinsic aspect ratio if it has a valid width/height component (we don't need to concern ourselves with the case where the aspect ratio defined by the 'width' and 'height' attributes is different from that defined by the 'viewBox' attribute since CSS only cares about aspect ratio in cases where an aspect ratio can't be determined from intrinsic width/height). XXX true?

Percentage intrinsic width and height

One of the key questions to answer is whether percentage values for the 'width' and 'height' attributes specify intrinsic dimensions or not. Clearly the understanding/intention of the author of the current wording in the relevant section of the SVG Tiny 1.2 CR is that the answer is yes. Just as clear is that the understanding/intention of the SVG WG chair is that the answer is no and the part of the spec on 'width' says no.

Problems with "no":

  • If SVG is treated as a replaced element when embedded inline or embedded by reference the 'width' and 'height' attributes will not have any effect if they have percentage values. The SVG will either render at the width of the containing block minus margin/padding/border if it has an intrinsic aspect ratio (so the height can be calculated), or it will render at 300x150 px. For example, confusingly, this snippet of SVG embedded inline in an XHTML document will render in a 300x150 px rectangle:
    <div ...fixed size>
      <svg width="50% height="50%" viewBox="none">
        ...
      </svg>
    </div>
    

    On the other hand, if the width and height are moved into a 'style' attribute:

    <div ...fixed size>
      <svg style="width:50%; height:50%;" viewBox="none">
        ...
      </svg>
    </div>
    

    the SVG will render in a rectangle that's 50% the width and height of its containing block, which would no doubt be what the authors would expect of either snippet. How's that for confusing?

Problems with "yes":

  • The CSS spec says intrinsic width/height are resolved as a percentage of the containing block's width/height. As a result, once again with CSS, you have the problem that none-zero values for border/padding/margin will cause the SVG to burst out of its containing block. (For inline SVG this may be what's expected since it's how things would behave if the attributes were mapped into style.)
  • There is no way for some SVG content to say it wants to take up whatever space is available after borders, padding and margins have taken their share (there is no way to create SVG that does NOT have an intrinsic width/height since the 'width' and 'height' attributes default to 100%).

Does it actually make sense to have percentage intrinsic dimensions? In the general case, probably not. It does make sense to be able to say "take up all the room available", i.e. 100% width/height, but why would you want to take up some arbitrary percentage of some unknown area? The SVG knows nothing about what's outside it. It makes no sense.

Sizing of standalone SVG

SVG Tiny 1.2, The initial viewport, says "If there is no [containing] document, the SVG user agent must use the 'width' and 'height' attributes on the 'svg' element as the width and height for the viewport." For this scenario we could map the 'width' and 'height' attributes into style (width/height defaulting to 100% if not specified) which would make implementation much simpler in Mozilla (this is also what Opera does). Percentage values would then set the viewport of the SVG to a percentage of the client area as the user would expect.

Treating SVG as a replaced element in this context

In this scenario we don't care about intrinsic size/ratio (and hence, for the purposes of viewport sizing, the 'viewBox' attribute).

One note: we would want to make sure to force |display:block;| for such SVG and prevent content from changing this.

Sizing of SVG embedded inline

SVG Tiny 1.2, The initial viewport, says "If the [containing] document is styled with CSS, then the negotiation process must follow the CSS rules for replaced elements." To allow this, SVG Tiny 1.2 specifies how the intrinsic width, intrinsic height and intrinsic aspect ratio are found for SVG content. This information is used as specified in CSS 2.1, Visual formatting model details to determine the width and height occupied by the SVG content.

Sizing of SVG embedded by reference