Bug 68995

Summary: Height of SVG element is incorrectly calculated when svg when width of containing element is set as a percentage
Product: WebKit Reporter: brichard
Component: SVGAssignee: Nobody <webkit-unassigned>
Status: RESOLVED FIXED    
Severity: Normal CC: fmalita, krit, myles.borins, pdr, robertc, zimmermann
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: All   
OS: All   
URL: http://e-st.glam.ac.uk/simulationgames/svgheightbug/index.html
Attachments:
Description Flags
An http example of svg elements that render correctly in firefox, but incorrectly in webkit based browsers none

Description brichard 2011-09-28 05:04:39 PDT
When an SVG file is set to width = 100% and height = 100% (and viewport is set correctly) and its' containing element width is set in percentages, the height of the SVG image is incorrectly calculated. 
The SVG image displays at the correct size/ratio in browser window, but its' container picks up its' height from the SVG in code and this value is incorrect. It is larger than the SVG height as displayed in the browser window. If you inspect the SVG element and look at the metrics you will see the reported size is way bigger than the displayed size.

To demonstrate the bug I have posted code at http://e-st.glam.ac.uk/simulationgames/svgheightbug/index.html

The green areas are the background of the element containing the SVG. You should only be able to see a small amount of green, which I deliberately set in the css via padding and margins. For correct behaviour open the url in Firefox.
In Webkit you will notice that the green areas are far bigger and break the layout. I've attached a screenshot of the behaviour in Safari OS X.

The height of the containing element should match the height of the SVG as displayed in the browser window.



Other details:
HTML5
SVGs are rendered using Raphaƫl JS
Comment 1 Myles Borins 2012-07-05 21:32:11 PDT
Created attachment 151018 [details]
An http example of svg elements that render correctly in firefox, but incorrectly in webkit based browsers
Comment 2 Myles Borins 2012-07-05 21:32:54 PDT
I am having the same problem in regards to SVG and height.

Expected Behavior:

An SVG element with a viewBox attribute should responsively scale to fit the div element it is within, and the div element should accurately scale based on the aspect ratio of the viewBox.  In firefox this behavior is accurate and consistent.

Bug:

When an svg element is drawn the height of the div / viewBox defaults to the full height of the window if no style for height or width are present.  When multiple SVG elements are placed side by side, and on top of one another, the side by side elements scale as expect, but large gaps are present between the rows.

http://jsfiddle.net/Ede2v/

The above jsfiddle is a perfect example of the problem mentioned in this bug report. (It will also be attached as html).  

It would appear that the cause of this bug is a miscalculation of the height of the viewbox... I will attempt to dig in to the source and find the cause of the error.  Any guidance or suggestions would be greatly appreciated.
Comment 3 Myles Borins 2012-07-05 21:33:49 PDT
Comment on attachment 151018 [details]
An http example of svg elements that render correctly in firefox, but incorrectly in webkit based browsers

<!DOCTYPE html>
<html>
    <head></head>
    <body>
        <div>
            <div style="float:left; width:50%; height:100%;">
                <svg viewBox="0 0 750 250" id="viewbox">
                    <g transform="translate(25,25)">
                        <rect style="stroke: #000000; fill: #ffff00; " x="0" y="0" width="50" height="200" id="60" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="50" y="0" width="50" height="200" id="62" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="100" y="0" width="50" height="200" id="64" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="150" y="0" width="50" height="200" id="65" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="200" y="0" width="50" height="200" id="67" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="250" y="0" width="50" height="200" id="69" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="300" y="0" width="50" height="200" id="71" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="350" y="0" width="50" height="200" id="72" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="400" y="0" width="50" height="200" id="74" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="450" y="0" width="50" height="200" id="76" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="500" y="0" width="50" height="200" id="77" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="550" y="0" width="50" height="200" id="79" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="600" y="0" width="50" height="200" id="81" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="650" y="0" width="50" height="200" id="83" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="35" y="0" width="30" height="125" id="61" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="85" y="0" width="30" height="125" id="63" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="185" y="0" width="30" height="125" id="66" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="235" y="0" width="30" height="125" id="68" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="285" y="0" width="30" height="125" id="70" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="385" y="0" width="30" height="125" id="73" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="435" y="0" width="30" height="125" id="75" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="535" y="0" width="30" height="125" id="78" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="585" y="0" width="30" height="125" id="80" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="635" y="0" width="30" height="125" id="82" class="note" noteType="orange"></rect>
                    </g>
                </svg>
            </div>
            <div style="float:left; width:50%; height:100%;">
                <svg viewBox="0 0 750 250" id="viewbox">
                    <g transform="translate(25,25)">
                        <rect style="stroke: #000000; fill: #ffff00; " x="0" y="0" width="50" height="200" id="60" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="50" y="0" width="50" height="200" id="62" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="100" y="0" width="50" height="200" id="64" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="150" y="0" width="50" height="200" id="65" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="200" y="0" width="50" height="200" id="67" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="250" y="0" width="50" height="200" id="69" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="300" y="0" width="50" height="200" id="71" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="350" y="0" width="50" height="200" id="72" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="400" y="0" width="50" height="200" id="74" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="450" y="0" width="50" height="200" id="76" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="500" y="0" width="50" height="200" id="77" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="550" y="0" width="50" height="200" id="79" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="600" y="0" width="50" height="200" id="81" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffff00; " x="650" y="0" width="50" height="200" id="83" class="note" noteType="yellow"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="35" y="0" width="30" height="125" id="61" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="85" y="0" width="30" height="125" id="63" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="185" y="0" width="30" height="125" id="66" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="235" y="0" width="30" height="125" id="68" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="285" y="0" width="30" height="125" id="70" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="385" y="0" width="30" height="125" id="73" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="435" y="0" width="30" height="125" id="75" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="535" y="0" width="30" height="125" id="78" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="585" y="0" width="30" height="125" id="80" class="note" noteType="orange"></rect>
                        <rect style="stroke: #000000; fill: #ffa500; " x="635" y="0" width="30" height="125" id="82" class="note" noteType="orange"></rect>
                    </g>
                </svg>
            </div>
        </div>
        <div>
            <div style="float:left; width:50%; height:150px;">
                <svg viewBox="0 0 300 30">
                    <rect width="300" height="30"></rect>
                </svg>
            </div>
            <div style="float:left; width:50%; height:150px;">
                <svg viewBox="0 0 300 30">
                    <rect width="300" height="30"></rect>
                </svg>
            </div>
        </div>
        
        <div>
            <div style="float:left; width:50%; height:100%;">
                <svg viewBox="0 0 300 300">
                    <rect x="0" y="0" width="150" height="300"></rect>
                    <rect x="150" y="0" width="150" height="300"></rect>
                </svg>
            </div>
            <div style="float:left; width:50%; height:100%;">
                <svg viewBox="0 0 300 300">
                    <rect width="300" height="300"></rect>
                </svg>
            </div>
        </div>
    </body>
</html>
Comment 4 Myles Borins 2012-07-05 21:45:05 PDT
Sorry about the spam... 

I have confirmed that this bug is present on OSX, Windows, and Linux

OSX - present in webkit browser, chrome, and Safari
Windows 7 - present in chrome
Ubuntu - Present in chrome
Comment 5 Philip Rogers 2012-07-09 20:46:48 PDT
Adding fmalita who was recently in this space.
Comment 6 Philip Rogers 2012-07-09 21:18:15 PDT
After some further discussion on IRC it looks like the issue boils down to calculating the height of an SVG element with viewBox set. WebKit appears to be using 100% of the viewport... is that correct?

Here's a smaller testcase:
http://jsfiddle.net/FTcSA/2/

Notice that in WebKit the box is centered, whereas Firefox leaves it at the top.
Comment 7 Dirk Schulze 2012-07-09 22:07:00 PDT
(In reply to comment #6)
> After some further discussion on IRC it looks like the issue boils down to calculating the height of an SVG element with viewBox set. WebKit appears to be using 100% of the viewport... is that correct?
> 
> Here's a smaller testcase:
> http://jsfiddle.net/FTcSA/2/
> 
> Notice that in WebKit the box is centered, whereas Firefox leaves it at the top.

I can just say that the behavior is looks incorrect. The actual size of the SVG is dependent on the CSS box of the SVG. This must be specified directly:

<svg style="width: 100px; height:100px">

The with and height attribute are independent of the properties. If the properties were not specified, the default size (calculated value) for an inline SVG is 500px to 250px.

That is what Firefox and Opera are doing if you do NOT specify a viewBox. Strangely this behavior changes if a viewBox was specified. I don't see a reason for that. IE10 on the other side, is doing what I would expect.

To the centralization: This depends on the default values of preserveAspectRatio. However, if we assume that the 500px to 250px are not used in combination with viewBox (which does not make sense), the size should be dependent on the viewport (which also makes not much sense in HTML), and the behavior of WebKit would be correct. Just like it would be for a standalone SVG.

But like I said, the SVG size should not be scaled, and the rect should fit in the size of 500px to 250px IMO. Since this is just a resolution of the SVG WG and not specified, it might be a good idea to bring it up on the www-svg mailing list, or open bugs for other browsers :).
Comment 8 Dirk Schulze 2012-07-09 22:26:25 PDT
(In reply to comment #2)
> I am having the same problem in regards to SVG and height.
> 
> Expected Behavior:
> 
> An SVG element with a viewBox attribute should responsively scale to fit the div element it is within, and the div element should accurately scale based on the aspect ratio of the viewBox.  In firefox this behavior is accurate and consistent.

It is consistent, but definitely not accurate since it does not take the default value for preserveAspectRatio into account.

Just open your black SVG example snippets as standalone in any browser, then resize the window. You'll see that the black rect won't fit into the whole window, what it should following your assumptions on the pasted test.

It doesn't because of the default value of preserveAspectRatio. Therefore WebKit is correct and Firefox and Opera are wrong on this particular part of the test.
Comment 9 Myles Borins 2012-07-09 23:42:19 PDT
 > It doesn't because of the default value of preserveAspectRatio. Therefore WebKit is correct and Firefox and Opera are wrong on this particular part of the test.

It does take the default value of preserveAspectRation into account... the problem is that the Height is being incorrectly calculated... creating an excess buffer on the top and bottom of the svg element.  

This prevents developers from "Stacking" svg elements on top of each other in the DOM in a responsive way using div elements.

If one were to place multiple svg elements in a single div... they would not be able to have multiple viewports placed side by side in the window. The below example places 4 svg elements in a single div.  It renders as expected in all major browsers (untested in IE)

http://jsfiddle.net/teYA2/

Now if I were to place the elements into seperate divs I can use a bit of css to place four of them. Having not specified any dimension this result should "in theory" be responsive to the size of the window.

http://jsfiddle.net/KS69Z/

This above example renders as expected in firefox, but with web-kit the default calculated height for the element is based on the size of the window rather than the aspect ratio of the viewbox.

Funny enough there is a hack to fix this that works in the chrome dev past v21.x and also seems to work in the nightly build of web-kit.  Adding style="height: 100%;" seems to render the expected output (although this will not work in the public release of either browser).

http://jsfiddle.net/TmVVe/

It would seem to me like the default behavior is currently off, is it not strange that we need to specify a height of 100% with css?  Should that not be the default?
Comment 10 Dirk Schulze 2014-05-12 06:43:45 PDT
This works the same in Firefox, WebKit trunk and Chromium now. Closing the bug.