[svg][filter-effects][css-masking] objectBoundingBox/userSpaceOnUse in HTML


TL;DR: See examples in section “Current browser behavior” for current behavior of browsers on objectBoundingBox/userSpaceOnUse in HTML and proposed defintions in section “Possibilities”. Implementations are interoperable but not necessarily following the specs. The behavior on HTML and userSpaceOnUse is unclear. This post differs between objectBoundingBox and userSpaceOnUse and describes both.

## Introduction ##

SVG defines the concept of objectBoundingBox and userSpaceOnUse that is used across different SVG resources like SVG Gradients, SVG Patterns, Filter Effects, SVG Masks or SVG clipping path.

* objectBoundingBox — takes the boundaries of the current element as reference box. Percentage and length values are resolved according to this box.[1]

* userSpaceOnUse — takes the nearest viewport of the element in the current local coordinate space of the element as reference box. Percentage and length values are resolved according to this box.[1]

Note: While <length> values are resolved normally on userSpaceOnUse, they have a distance of 1 unit (pixel) from one edge to the other for objectBoundingBox.

Note 2: The viewport is not effected (trimmed) by the window size for SVG. SVG does not have the concept of scroll bars either (yet).

## objectBoundingBox for HTML elements? ##

For SVG elements, the bounding box of the element is taken as reference box for position and dimension of the resource.[2]

The term bounding box was not defined for HTML/CSS. CSS Masking and Filter Effects currently define and use the term "bounding client rect" which is the smallest rectangle that contains the border box of the current element and the border boxes of all descendant elements.[3]

## userSpaceOnUse for HTML elements? ##

SVG elements are positioned on the canvas (the area defined by the nearest viewport). The coordinate origin is positioned on the top left of the viewport, independent of the position of the element.

<rect x=“100” y=“200” width=“100” height=“100”/>, position of the element is at (100;200) position of the origin (0;0).

HTML elements set the top left coordinate origin to their top left corner — not the top left of the nearest viewport.

<div>box 1</div><div>box 2</div> The 2nd box is positioned after the first box. Lets assume the position of the 2nd box is (0;40). The point of origin would be the top left corner of the element. Even though the element is positioned at (0;40), the point of origin is reset to (0;0) for transforms and sizing but still at the position (0;40).

How does that effect the behavior of userSpaceOnUse on HTML elements?

## Current browser behavior ##

I wrote some small example with <clipPath> and userSpaceOnUse as well as <clipPath> and objectBoundingBox:

userSpaceOnUse: http://jsfiddle.net/hhLHz/
objectBoundingBox: http://jsfiddle.net/ZzGD6/ http://jsfiddle.net/XAd5U/

The examples just work on Gecko, WebKit and Blink which have initial implementations of <clipPath> on HTML content. <clipPath> is representative for all SVG resources (SVG Gradients, SVG Patterns, Filter Effects or SVG Masks).

All SVG resources need to be defined in an SVG context. Meaning that the element (i.e. <clipPath>) must be the descendant of an <svg> element (which creates a viewport).

* behavior for objectBoundingBox (http://jsfiddle.net/ZzGD6/ http://jsfiddle.net/XAd5U/)

Gecko, WebKit and Blink take the bounding client rect as reference box for positioning and sizing of the clipping path. See examples.

* behavior for userSpaceOnUse (http://jsfiddle.net/hhLHz/ http://jsfiddle.net/M8K3V/)

Gecko, WebKit and Blink use the nearest viewport of the <mask> element as reference box (presumably an <svg> element). The origin of the reference box is set to the top left of the border-box of the clipped element. (As a proof that it is really the border-box: http://jsfiddle.net/XAd5U/ the content of the <div> has a negative margin that does not influence the position of the clipping path.)

Note: The definition of userSpaceOnUse is the nearest viewport of the *masked element* according to the SVG spec. The current behavior of browsers does not match the specification text.

## Possibilities ##

* objectBoundingBox
We have interoperable behavior that is consistent with the specs. Take the bounding client rect as reference box. No need to change anything.

* userSpaceOnUse
1) Use definition of SVG: take the nearest viewport of the effected element as reference box for positioning and sizing.
2) Use one of the boxes of background and borders (content-box, padding-box, border-box), margin-box or the bounding client rect as reference box. Properties like mask-origin or background-origin could override a default box.
3) Change definition of userSpaceOnUse and follow the behavior of Gecko and WebKit/Blink. The reference box would be the nearest viewport of the resource (i.e. <clipPath>) and not of the element using the SVG resource (the <div> box in the example above). (See SVG only example demonstrating the same behavior in SVG context: http://jsfiddle.net/CxnwQ/). The origin would be determined by the border-box for HTML elements.

As a note, for many elements the userSpaceOnUse behavior is the default. Attributes like maskContentUnits or clipPathUnits must actively set to objectBoundingBox to change behavior to objectBoundingBox.


[1] http://www.w3.org/TR/SVG11/types.html#DataTypeLength (2nd list item)
[2] http://dev.w3.org/fxtf/masking/#ClipPathElementClipPathUnitsAttribute
[3] http://dev.w3.org/fxtf/masking/#bounding-client-rect

Received on Monday, 30 December 2013 13:16:49 UTC