Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-transforms] view-box interacts poorly with transform-origin percentages #2443

Closed
eevee opened this issue Mar 15, 2018 · 6 comments
Closed
Labels

Comments

@eevee
Copy link

eevee commented Mar 15, 2018

Per spec:

If a viewBox attribute is specified for the SVG viewport creating element:

  • The reference box is positioned at the origin of the coordinate system established by the viewBox attribute.

  • The dimension of the reference box is set to the width and height values of the viewBox attribute.

This seems to say that the box is the size of the viewport, but is shifted so that its upper-left corner is always at (0, 0). Percentages for transform-origin are relative to the edges of the box, so 0% 0% or top left will always mean the point (0, 0), which may be anywhere within the viewport or outside it entirely.

Firefox and Chrome both behave this way. I would expect this to scale the square down around the center of the viewport, but instead it scales down around the point (100, 100), which is ¾ of the way across:

<svg viewBox="-50 -50 200 200" xmlns="http://www.w3.org/2000/svg">
<rect x="-50" y="-50" width="200" height="200" fill="#f4f4f4"/>
<rect x="-25" y="-25" width="150" height="150" fill="none" stroke="pink"/>
<rect x="-25" y="-25" width="150" height="150" fill="none" stroke="lightblue"
    style="transform: scale(0.5); transform-origin: center; transform-box: view-box;"/>
</svg>

demo

Is this a mistake, or is there a rationale for it that I'm missing? It seems to make view-box nearly useless if your viewBox isn't anchored at the origin.

@eevee
Copy link
Author

eevee commented Mar 15, 2018

It occurs to me that this might be so absolute values for transform-origin are relative to the SVG coordinate system, but that's an odd behavior to tack onto view-box.

@AmeliaBR
Copy link
Contributor

This isn't a mistake, it's just how SVG works. All positions in SVG are relative to the viewBox origin. If you want to draw a <rect> that fills the viewBox, setting width="100%" height="100%" isn't enough, you also need to adjust the x and y values to match the viewBox offsets.

SVG didn't have a transform-origin, but it did have the ability to move your viewBox origin into the middle of the graphic. It does mean that you need to be aware of your viewBox origin whenever you are using transform-origin with transform-box: view-box.

I agree that, in hindsight, this interaction means that the keyword versions of transform-origin are confusing. center, left, right, and so on aren't the center, left, right, etc. of the actual viewbox, but of a constructed box positioned at the origin.

This is because the keywords map directly to percentage values: center is equivalent to 50% 50%, and percentages are measured relative to the origin, the same as absolute values. If the entire system had been designed starting with SVG, we might have created "smarter" keywords, that adjusted to the current viewBox, but there is probably too much web content relying on the keywords computing directly to percentages.

For setting transform-origin when using view-box as your reference frame, I'd recommend sticking with percentage or pixel values, or calc() combinations of the two.

If you're dynamically setting the percentages and viewBox offsets, you could use custom properties, and then a calc funtion to keep them logically separate:

<svg viewBox="-40 -30 80 60" style="--vbx: -40; --vby: -30">
<circle r="20"/>
</svg>
<style>
circle {
--tox: 50%;
--toy: 100%;
transform-origin: calc(var(--vbx) + var(--tox)) calc(var(--vby) + var(--toy));
}
</circle>

@eevee
Copy link
Author

eevee commented Mar 15, 2018

All positions in SVG are relative to the viewBox origin.

Er... but transform-box: fill-box; makes my example render as expected.

demo

The whole point of transform-box is to change what transform-origin is relative to, so I don't understand why view-box couldn't simply be positioned to match the actual view box. (Aside from breaking anything relying on the current behavior, of course.)

@AmeliaBR
Copy link
Contributor

(Aside from breaking anything relying on the current behavior, of course.)

But that's just it. transform-box: view-box is designed to match the existing SVG behavior. transform-box: fill-box is a new behavior, changing the rules on how coordinates and percentages work.

All positions in SVG are relative to the viewBox origin.

Sorry, over-simplified, there. Should have been "until transform-box: fill-box, all positions in SVG..."

@eevee
Copy link
Author

eevee commented Mar 15, 2018

Ah, I didn't realize it was just codifying the original behavior. Hmm.

I'd love a positioned-view-box, then. :)

@AmeliaBR
Copy link
Contributor

I'd love a positioned-view-box, then. :)

Hmmm, interesting idea. Maybe in the same spec that eventually creates a CSS representation of the viewBox attribute (w3c/fxtf-drafts#7) (whenever that happens).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants