Re: [css-backgrounds] border-image with an SVG resource that has no intrinsic size

> On Aug 12, 2015, at 4:56 PM, Said Abou-Hallawa <sabouhallawa@apple.com> wrote:
> 
> Regarding the last point which is why the SVG image (with no intrinsic size) by itself can be rendered correctly while the image-border in WebKit renders all the pieces from the top-left corner, here is my explanation for why this approach was chosen. Let's  consider this simple test case:
> 
> svg-no-intrinsic-size.svg:
> 
> <svg xmlns="http://www.w3.org/2000/svg <http://www.w3.org/2000/svg>" version="1.1">
>  <rect width="100" height="100" fill="lime"/>
>  <rect x="10" y="10" width="80" height="80" fill="none" stroke="black" stroke-width="4px"/>
> </svg>
> 
> test-case.html:
> <!DOCTYPE HTML>
> <head>
>  <style>
>    .box {
>      height: 100px;
>      width: 100px;
>      margin: 10px;
>      display: inline-block;
>      background-color: red;
>      border: 20px solid;
>    }
>    .border-image-no-intrinsic {
>       border-image: url('svg-no-intrinsic-size.svg') 0 fill;
>    }
>    .border-image-no-intrinsic-slice {
>       border-image: url('svg-no-intrinsic-size.svg') 20 fill;
>    }
>  </style>
> </head>
> <body>
>  <div class="box border-image-no-intrinsic"></div>
>  <div class="box border-image-no-intrinsic-slice"></div>
> </body>
> 
> When loading this test case In Chrome, the first div: <div class=“box border-image-no-intrinsic”> draws only the fill part of the border-image.

Right, because there is a zero width border-image-slice. So the image is essentially sliced into one big middle sections and 8 outer sections of zero width and/or height.

> But the drawing of the border-image is scaled down by some ratio which is hard to be understood.

I think that might be a Chrome bug.

> But from tracing the code here is why this scaling is happening.
> This div size is (100x100) with border of 20, so the border box is (140x140)
> According to the specs: the intrinsic size of the SVG border image should be (140x140)
> Since the border-image has fill set on but its slice is 0, the whole SVG which is (140x140) has to be displayed in the content box of the div which is (100x100)
> So the SVG drawing will be scaled down by 100/140.
Well, the outer “svg” element (which acts as a viewport for the drawing of the contents) should be. The contents, being a definite size inside a container that is not a definite size, should not. Whether the viewport is the size of a window (as when the SVG is loaded directly into a browser window), or the size of the border box, makes no difference to fixed (non-percentage-based) dimensions of elements in it.

I did suggest in an earlier email that if the svg element has no other intrinsic dimensions then it should use the dimensions of the contents as its intrinsic dimensions, which would then allow those contents to be stretched, but I was told (by David Vest) that there is no such provision. So, unless the rect was measured in percentage, the rects shouldn’t be stretched in this situation. This has more to do with the way SVGs work than with the way border-image specifically works. The rects also don’t scale in a background image, even though the background-size is 100%x100% when it is ‘auto’ on an image with no intrinsic dimensions.

> In Chrome also, the second div: <div class="box border-image-no-intrinsic-slice”> draws all the nine parts of the border-image. But it does not fill the whole rectangle of the <div>; it only fills 100x100 out of the 140x140 pixels. Here is why this happening:
> This div size is (100x100) with border of 20, so the border box is (140x140)
> According to the specs: the intrinsic size of the SVG border image should be (140x140)
> Since the border-image has its slice set to 20, the drawing size is also 140x140, which means no scaling is applied when drawing the image.
I think that is what is happening in Chrome. But the fixed-dimension contents shouldn’t scale anyway, just as they wouldn’t in a background image when you have 'background-size:auto’.
> Since the SVG itself draws only 100x100 pixels and since no scaling or stretching will happen,  only 100x100 of the element area will be covered by the SVG image.
Right.

> From these two cases, it was obvious to me that this problem is unsolvable. The nine-piece-slicing algorithm needs to know the bonding box of the drawing to draw the border-image correctly. There is no reliable way to know this bounding box (at least for now).

No, you are being mislead by the Chrome bug, not the specs. The bounding box of the SVG with no intrinsic outer dimension is the border box. Changing that bounding box affects the viewport for the SVG but does not affect fixed dimension contents.

> So the only way to know it is to require an “intrinsic size” set by the user.

The user? Anyway, this sentence means you are going off-spec, and are non-conforming.

> Now if the following SVG is used, the border-image will be drawn exactly as expected:
> 
> <svg xmlns="http://www.w3.org/2000/svg <http://www.w3.org/2000/svg>" version=“1.1” width=“100” height=“100">
>  <rect width="100" height="100" fill="lime"/>
>  <rect x="10" y="10" width="80" height="80" fill="none" stroke="black" stroke-width="4px"/>
> </svg>

Right, it has a viewport of a fixed size, and all the contents maintain their same spatial/sizing relationship to that size. So if you scale the fixed size of the image, you are scaling the all contents too. It is just like scaling a JPEG or something, except it is vectors instead of rasters.

> The specs says that the border box of the containing element should be used as a replacement of the image intrinsic size, if it is not provided. But this does not even give predictable results for simple cases.

It would if the browsers didn’t have bugs related to SVG border-images, and treated them more similarly to SVG background images. But the solution is not to standardize the bug and then pile more bugs on top of it because the first bug causes problems. The solution is to follow the spec, where this has been worked out already.

> I disagree that this was horrible change in WebKit. I understand it is not the ultimate solution and might not be the expected behavior. But my goal in choosing this approach was two things: (1) Solve this problem using the most straightforward solution so we get predictable and easy to explain results.

But you are explaining an incorrect result in Chrome, instead of understanding how SVG can have fixed sized elements when the SVG bounding box is scale-to-fit. It is a Chrome bug that they are being scaled down instead.

> (2) Make strong emphasis to the users that border-image has to have intrinsic size since we can’t guess its bounding drawing box. 

This means you are creating your own version of border-image, instead of basing it on the specs. The specs say that the bounding box is the border-box when the intrinsic size isn’t known. It doesn’t say the result can be random when the border-image doesn’t have intrinsic size. The fact that SVG can be misleading about when its bounding box is being stretched or not, is just due to the way SVG works. Chrome gets some of that wrong, but you have an opportunity to get it right, instead of more wrong.

Received on Thursday, 20 August 2015 06:19:41 UTC