W3C home > Mailing lists > Public > www-style@w3.org > August 2015

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

From: Tab Atkins Jr. <jackalmage@gmail.com>
Date: Thu, 13 Aug 2015 12:02:54 -0700
Message-ID: <CAAWBYDC5xZG5DbtY-z6rZq26xOgGxtHJUDWV87kZ4D8cbZrpKA@mail.gmail.com>
To: Said Abou-Hallawa <sabouhallawa@apple.com>
Cc: www-style list <www-style@w3.org>, Brad Kemper <brad.kemper@gmail.com>, davve@opera.com, Dean Jackson <dino@apple.com>, Simon Fraser <simon.fraser@apple.com>
On Tue, Aug 11, 2015 at 10:35 AM, 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" 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.
> But the drawing of the border-image is scaled down by some ratio which is
> hard to be understood. 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.
>
> 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.
> 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.
>
> 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). So the only way to know is to require
> an “intrinsic size” set by the user.
>
> No if the following SVG is used, the border-image will be drawn exactly as
> expected:
>
> <svg xmlns="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>
>
> The specs does cover this case clearly. Using the border box of the
> continuing element as a replacement of the image intrinsic size, if it is
> not provided, does not even give predictable results for simple cases.
>
> 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 aim in
> choosing this approach was two things: (1) Solve this problem with the most
> straightforward solution so we get predictable and easy to explain results.
> (2) Make strong emphasis to the users that border-image has to have
> intrinsic size since we can’t guess its bounding drawing box.

No, this is absolutely a terrible behavior currently.  What WK is
currently doing cannot be interpreted as anything other than "this is
an error, doing minimal recovery to figure out something renderable".
There's no possible way to defend it as actually desirable.

The specs aren't super-clear on this, but the behavior in practice is
clear - in the absence of any other information, the SVG's viewport is
set so that its px is the same as the page's px.  You then render
appropriately given that information - in the example given, the lime
square is 100px wide in the page's coordinate system.  You can see
this if you use it in, say, a background - regardless of what
background-origin is given (which alters the background positioning
area), the square is always rendered the same size.

The same *should* be true of border-image, using the border box as its
positioning area, as the spec dictates.  If you don't provide a size
or a viewBox, this'll often result in a slightly weird result, *but
that's okay*.  The Backgrounds spec is then quite clear that
border-image-slice <number> values refer to the vector-space units
(for SVG, that's user-space units, or px values within the SVG's
coordinate space).  Applying that then gets you the correct result.

~TJ
Received on Thursday, 13 August 2015 19:03:41 UTC

This archive was generated by hypermail 2.3.1 : Thursday, 13 August 2015 19:03:42 UTC