Have you ever had a Zen moment? Like one where you finally know the sound of one hand clapping? I just had one. I now understand how SVG is suppose to be fitted into part of a web page (well almost, as you will see). This was not an easy task, and in fact I found it more difficult than understanding QCD. It took piecing together parts from nine sections in five different chapters and two versions of the SVG specification plus developing a
test page. If you are a long time web developer (or standards writer) you probably already know how SVG is fitted into HTML, or could make a good guess; the problem is, I am not. The fact that the various browsers have rendering differences with SVG in HTML means that I am probably not alone.
Why is this important? I have over 500 SVGs in my Inkscape book. I want the SVGs to scale to the same size as the PNG fallback images. It would be very time consuming to go through and size each one individually and DocBook doesn’t provide a way to scale them by a set factor automatically.
The first step in placing SVG into HTML is determining the “viewport” (
SVG1.1, 7.2). This is the region on the web page where the SVG is to be placed. The position of the viewport is determined by the HTML. The size can be specified by the HTML through “positioning properties” (
SVG1.1, 7.2). For example, if a wrapping <object> tag has width and height attributes defined, they determine the viewport size. If, however, the wrapping tag does not specify a size, the width and height attributes in the SVG root are used (
SVG1.1, 7.2). The SVG width and height can be in absolute units (e.g. px) in which case, that is the size of the viewport, or they can be defined in percentages, in which case things are more complicated. If width and height are both 100% (or not given), then the viewport will fill the space allocated by the wrapper. If width and height are less than 100% one would think that the viewport would be scaled down by that amount which seems consistent with
SVG1.1, 6.16. However,
SVG1.2Tiny, 7.14 states that if percentages are used, they correspond to the percentage of the viewport that is actually rendered and not the relative size of the viewport to the available area! This can explain why in some cases Firefox and Opera both show only a quarter of the SVG when width and height are both 50%. Firefox and Opera don’t agree when which rule should be applied. And in one case, Opera applies both rules, reducing the viewport and clipping the SVG content.
The viewport has another role that may not be obvious at once. By default, the SVG is clipped by the viewport and not by the SVG width/height or viewBox (SVG1.1,
14.3.3 and
6.16). This means that if you leave an object outside the nominal area of your drawing it may show up when the SVG is embedded in HTML!
Now that we have the viewport, the next step is transform the SVG to fit it. If there is no viewBox attribute, the SVG is rendered so that the origin (upper left corner) of the SVG is at the upper left corner of the viewport (
SVG1.1, 7.3). One user unit in SVG space corresponds to one screen pixel (SVG1.1, 7.2). If the viewport is bigger than the allotted area, Firefox adds scroll bars, Opera does not. There is an attribute that might control the display of scrollbars, zoomAndPan (
SVG1.1, 16.7), but it doesn’t appear used. If there is a viewBox, the viewBox is mapped to the viewport (
SVG1.1, 7.7). How the mapping is done is determined by the preserveAspectRatio attribute. The default value is “xMidYMid meet” (
SVG1.1, 5.1.2) which means that the center of the viewBox is at the center of the viewport and that the SVG is scaled uniformly so that one pair of sides (top/bottom or left/right) of the viewBox coincide with the viewport while the other pair of sides is inside the viewport (
SVG1.1, 7.8). Now recall that if the SVG attributes width and height have percentage values less than 100% there may be some clipping involved.
The most important thing to take away is that the SVG attributes width and height are not what a naive person might think. They are rather suggestions to the HTML layout engine about the area that should be allocated for the SVG and in which the SVG will be scaled to fit (using the viewPort and scaleAspectRatio attributes).