w3c / fxtf-drafts

Mirror of https://hg.fxtf.org/drafts
https://drafts.fxtf.org/
Other
69 stars 48 forks source link

Proposal: Promote SVG Viewbox to a CSS property, extend to all transformable elements #7

Open tabatkins opened 8 years ago

tabatkins commented 8 years ago

From @vidhill on May 19, 2016 14:0

First, original proposition, https://lists.w3.org/Archives/Public/www-svg/2013Dec/0080.html

Yes, I'm trying to bring this to the table again as it did not seem to get much attention/discussion the last time around. -maybe being on Github will be more conducive to discussion..

I really agree with this proposal, being able to modify the viewbox on a SVG element using CSS would allow for very useful applications of SVG in a responsive layout, (See Sara Soueidan's examples below)

Sara Soueidan has a very good article demonstrating a perfect need and use cases for this here: https://sarasoueidan.com/blog/svg-art-direction-using-viewbox/

There were some enthusiastic responses from some SVG heads..

@sdras Sarah Drasner Mail List Reply

@AmeliaBR Amelia Bellamy-Royds Mail List Reply

@jakearchibald Jake Archibald Mail List Proposal

Copied from original issue: w3c/csswg-drafts#128

tabatkins commented 8 years ago

Yup, sorry about the request getting buried. I got swamped for a while and am trying to catch up on proposals.

Yes, viewbox should totes be a property; nearly everything in SVG should be. A simplified version that solely exposes none | <length>{4} would be utterly uncontroversial. I like, however, the bounds value, and having it be defined simply as the stroke bounding box is good. This is essentially just CSS shrinkwrapping (in theory, of course; it's different in practice).

tabatkins commented 8 years ago

From @AmeliaBR on May 24, 2016 21:11

@tabatkins Are you able to move this issue to the FX repo? I'd like to keep any view-box spec under the (shared) responsibility of the SVG WG.

And if you do start drafting something, Tab, I'd be happy to review it. If you don't get to it, it's still on my eventual To-do list. Just buried under far too many other to-do's!

tabatkins commented 8 years ago

From @bradkemper on May 25, 2016 13:46

Would this affect non-SVG stuff too? I'm no expert on this attribute, but it sounds kind of like a clip-path:inset() effect which also affects the element's instrinsic dimensions, causing it to be scaled so that the new dimensions are contained by the original dimensions. Is that something we want for plain old HTML too?

tabatkins commented 8 years ago

@bradkemper I don't think so. This doesn't clip, either; viewBox just (a) from the POV of stuff inside the SVG, sets up the coordinate space they position themselves in (and in particular, what "100%" maps to), and (b) from the POV of stuff outside the SVG, defines the intrinsic aspect ratio of the element.

(a) doesn't mean anything for non-SVG elements. (b) could theoretically, but it's a very roundabout way to handle aspect ratio, and misses some features we'd like for a real aspect-ratio property, so I don't think we should try to smuggle aspect-ratio into general CSS via viewbox.

BigBadaboom commented 8 years ago

Animatable: as simple list of length

Is this flexible enough? Or should viewBox perhaps be considered a shortcut for

viewbox-x viewbox-y viewbox-width viewbox-height
tabatkins commented 8 years ago

You can't specify those independently in SVG, and to the best of my knowledge people haven't asked for it (despite the handful of examples I've seen of viewBox animating), so I'm inclined to not do that unless there are good use-cases for it.

AmeliaBR commented 8 years ago

@BigBadaboom

I suggested making the min-x and min-y parts optional (default to 0), but I don't see any need for breaking it into shorthand & longhand properties.

And yes, it should be animatable as a list of 4 independent numbers. Being able to animate a viewBox with CSS animations/transitions is one of the main benefits for SVG of upgrading it to a property. (The other main benefits being media queries and assigning a single viewBox to a class of inline SVG icons.)

AmeliaBR commented 8 years ago

@bradkemper

For non-SVG content, the viewBox would:

I'm not sure how this relates to clip-path.

sdras commented 8 years ago

+1 on animatable, I think part of the reason it has only been done a handful of times is undereducation. It has a lot of nice implications for the web and informative graphics. 4 independent numbers makes a lot of sense. Thank you for all of your work, Tab!

BigBadaboom commented 8 years ago

My thought was that if animators wanted to use viewBox like a camera, they may want to animate position differently from size.

If it is an array of lengths, they could achieve that to some extent with @keyframes. But I was thinking they may want to do something like:

.crash-zoom {
  viewbox-x: 100;
  viewbox-y: 100;
  viewbox-width: 16;
  viewbox-height: 9;
  transition: viewbox-x: 0.5s easeInQuad, viewbox-y: 0.5s easeInQuad,
              viewbox-width: 0.5s easeOutElastic, viewbox-height: 0.5s easeOutElastic;
}
AmeliaBR commented 8 years ago

@BigBadaboom I can see the use-case. But it's something that could be easily added in after the fact, so we don't have to worry about it now. Once we get authors are really using the property as is, then they can tell us if it isn't flexible enough without shorthand/longhands.

vidhill commented 8 years ago

+1 on animatable as well,

Great creative potential on animated viewbox.

Great to see this being discussed.

jezmck commented 8 years ago

+1

bodymovin commented 8 years ago

+1

jakearchibald commented 8 years ago

FWIW my sketchy proposal was to allow this on html elements too. Is it a no-go? https://lists.w3.org/Archives/Public/www-style/2016Feb/0328.html

AmeliaBR commented 8 years ago

@jakearchibald Definitely a go.

Changed the issue title to reflect the beyond-SVG scope of the proposal. Apologies for ruining email threading of notifications.

ubik23 commented 8 years ago

+1

jakearchibald commented 8 years ago

Y'all are great. Really excited about this.

roblevintennis commented 8 years ago

👍

andrewpomeroy commented 8 years ago

👌

jesperstarkar commented 8 years ago

👍

shepazu commented 8 years ago

I wanted to use this 2 days ago to make a map zoomable onto different countries. Please, please, please let this happen. Let me know if I can help.

tabatkins commented 8 years ago

Hmmmm, if it's usable on all transformable elements, what does that mean? It is a scale/pan based on the ratio of the viewBox width/height and the element's actual width/height? If we want to do that (make it a new transform shorthand), we need to define where in the list it goes, and then probably define a transform function for it.

AmeliaBR commented 8 years ago

@tabatkins Yep, the net effect can be described as a scale + translate, but only on the element's children, not on the element itself. Not sure whether it's practical to define it as a transform function, but it would affect the cumulative transformation matrix for child content. (I still want to get all the SVG transformation-related DOM APIs generalized to all transformable elements, too!)

Since there's lots of interest here, I'm copying my email from April which lays out a lot of the complications that will need to be addressed, as well as summing up possible use cases:


Support viewBox in CSS

I am also strongly supportive of converting the SVG viewBox attribute into a property controllable by CSS. I also like Jake's proposal to extend it to the CSS box model as a way of creating aspect ratio control and scale-to-fit behavior for HTML content.

It's taken me this long to reply because I wanted to carefully outline some of the issues that need to be considered. This is also effectively an explanation of why we haven't done this yet in SVG.

It's getting a little late to spec this in time for SVG 2. However, if there is support from the CSS WG to also adopt this feature for CSS box layout, then it probably makes sense to have it as its own module, anyway.

(Aside: I agree that the CSS-ified term should be view-box. I'm using viewBox here out of habit. I'd assume it would continue to be the standard spelling for the presentation attribute.)

First, a summary of what the SVG viewBox and preserveAspectRatio attributes do, translated into CSS terms:

The scale transformation is not defined as an explicitly magnification factor, like in transform: scale(s). Instead, it's always a scale-to-fit, with the preserveAspectRatio attribute defining what "fit" means when the <svg> layout box is constrained to a different aspect ratio than that declared by the viewBox. preserveAspectRatio therefore has much the same function as CSS object-fit and object-position combined (albeit with more limited options).

The translate transformation is a combination of an implicit transformation from the preserveAspectRatio (the corner of the viewBox won't always fit up against the corner of the layout box) and an explicit transformation defined by the xMin and yMin parameters of the viewBox. These are often left as 0 (no explicit translation), but they are very useful in some cases, such as creating a centered coordinate system.

So, if I was going to write up a proper spec for viewBox in CSS (as I keep telling people I intend to do), I would make the x- and y-offset parameters optional, and I would replace preserveAspectRatio with object-fit and object-position. (The mapping of attribute values to those properties could be defined via user stylesheets.) Currently, these object-* properties are not well defined for <svg> elements anyway, and interact poorly with preserveAspectRatio. It makes sense to create a single cohesive definition, with all the extra options that object-* properties provide. Jake's proposal introduces a new property, but I don't think it's necessary.

Benefits for SVG:

Complications for SVG:

Benefits for CSS box model:

The main benefit as noted in Jake's proposal would be aspect ratio control, for videos, for images that haven't been downloaded yet, and for complex graphical layouts.

There have been a number of different proposals on www-style lately for aspect ratio control. Currently, the "padding hack" is the only way to create a scalable container with a fixed aspect ratio (and it can only be used to scale height to match width and not the reverse).

The scale-to-fit effect of viewBox would be also useful for big text headers and for embedded <iframe> (e.g., the little scaled-down preview iframes used on CodePen).

Complications for CSS box model:

The view-box approach would not be quite as flexible as other proposals for aspect ratio control, since it can't separate the aspect ratio from the scale effect. Most of the use cases (video, image, and big-text headers) are all scale-to-fit. But there could be other cases, such as text-in-a-shape layouts, where you would want the box to maintain a certain aspect ratio but not scale the text.

The xMin and yMin offset parameters are less useful for CSS (at least, until polar coordinate layout gets adopted). If we make them optional that isn't a big problem, but would need to define the behavior if they are used (e.g., the impact on the interpretation of left/top/etc in absolute positioning, on transform-origin, and so on).

All in all, I do think it's a useful proposal, but there are a lot of details to sort out. I would be happy to help spec it, but I probably won't have much time to work on it in the next few months as we try to get SVG 2 and the SVG accessibility specs finalized.

Martin-Pitt commented 8 years ago

One more reason for css-ified naming to view-box is that it exists as a keyword in clip-path

nucliweb commented 8 years ago

👍

birtles commented 8 years ago

Can someone fill me in on where the view-box naming proposal came from? The original proposal was for viewbox (as linked in the first post) since otherwise we'll have viewBox for the presentation attribute in SVG, viewBox or viewbox when using SVG in HTML, and view-box when using CSS. It seems better to me to harmonize the between presentation attributes / property than with keywords in the clip-path property? (which could possibly still be changed if we really needed to) But maybe this has been discussed elsewhere?

Martin-Pitt commented 8 years ago

It's not been discussed anywhere else as far as I know.

I'm just chiming in a vote for view-box. Not to break apparent convention with CSS (no combined words, fooBar ‹-› foo-bar) and also being able to condense neatly back to element.style.viewBox, which matches original SVG spec more nicely than the lowercased HTML version.

jarek-foksa commented 8 years ago

I would suggest using simplified model where the only purpose of the the view box is to define a rectangular area of element's local coordinate system for the purpose of rendering. How that area should be transformed so that it fits into the viewport would be controlled by object-fit and object-position properties.

In this model every renderable element has a view box, either explicit (defined with view-box property) or implicit (computed from the bounding or viewport box).

The spec should stop telling people that the view box "transforms the local coordinate system" as it makes the whole concept much harder to grasp. The view box does not transform but rather is transformed by the matrix determined from the value of preserveAspectRatio (or proposed object-fit and object-position).

AmeliaBR commented 8 years ago

@jarek-foksa

That's a very good point. The object-fit property already has the scale-down and none options that limit the scaling effect, so that plus viewBox would automatically allow authors to choose whether & when they wanted a scale effect.

That doesn't require simplifying the model: it actually is exactly the same model proposed above, I just hadn't extrapolated out all the extra options that object-fit would introduce, compared to preserveAspectRatio.

I also recognize your concern about terminology. We need to clearly distinguish between a transformation on an element and the transformation on its child content created by the interaction of viewBox & p.A.R.

jarek-foksa commented 8 years ago

@AmeliaBR I just meant changing the mental model that is used in the spec to explain the concept of the view box, not altering the API. The current reasoning is that the primary purpose of the view box is to provide intermidate transformation. If I were to explain what viewBox on the outermost <svg> element does, I would rather do it this way:

  1. The children of the outermost <svg> element live in an abstract infinite 2D space called the world space. Coordinates, distances and dimensions in this space are expressed with abstract (made-up) units called the world units (more generally known as user units).
  2. Since the world is infinite, it can't be rendered anywhere on the screen. What actually gets rendered is a finite rectangular area of the world called the view box, defined by the viewBox attribute on the outermost <svg> element.
  3. The screen area into which the view box is rendered is called the viewport, defined by the width and height attributes on the outermost <svg> element and/or by other CSS properties.
  4. The algorithm used to transform the view box so that it fits into the viewport is specified by the preserveAspectRatio attribute.

I realize this is a very limited explanaition that covers only one specific use case of viewBox and ignores all the edge cases (viewport with overflow: visible, relative units, etc.), but I hope you get the point.

AmeliaBR commented 8 years ago

Another issue that this spec should address: interaction of viewBox with box-sizing. Currently if you add box-model properties (margins, paddings & borders) to the root <svg>, auto-sizing gets thrown off when you embed that SVG as an <object>, <img>, etc.

OliverJAsh commented 8 years ago

I have one use case in mind that I'm not sure this will fix: a <picture> element with multiple <source>s, wherein each source image has a different aspect ratio. You want to reserve space for the current selected image, so there needs to be a way of defining aspect ratio for each <source>. I think this is a pretty significant use case—otherwise there's literally no way you can use art direction without causing the page to jump around as images load (as I found out the hard way).

The way I was imagining this (before hearing of this proposal) was:

<picture>
  <source media="(min-width: 500px)" srcset="landscape.jpg" aspectratio="4:3" />
  <source srcset="square.jpg" aspectratio="1:1" />
  <img>
</picture>

Is there any way we could utilise the proposal here to solve this use case? I can't think of one, because the browser re-uses the <img> element, so one can't simply apply a viewBox to each <source>.

AmeliaBR commented 8 years ago

@OliverJAsh That is an interesting & important use-case that hasn't been discussed yet.

Setting values on <source> to affect the associated <img> only when the source is used wouldn't fit with standard CSS property inheritance model, regardless of whether we used viewBox or a new property. However, it is actually somewhat similar to the case of SVG <view> elements: when the view is the target element of the URL, the viewBox on the view element replaces the corresponding property on the <svg>.

That doesn't mean it's an easy problem to solve (it's one of the main reasons SVG 2 hasn't turned viewBox into a CSS property yet), but if we solve it for one case we could solve it for both.

frivoal commented 8 years ago

I'm thinking of using this for scaling down large tables that otherwise don't fit when scrolling is not an option. Think of printing a w3c spec with a large propdef table at the bottom, on a piece of paper too narrow for it to fit. I think it would work, except that I'm just missing one thing: I'd need to set the view-box width to the intrinsic width of the table, rather than an arbitrary size.

table.propdef {
  view-box-width: max-content; /*I need the extra keyword*/
  max-width: 100%;
  object-fit: scale-down; /*If we make that an independent choice*/
  view-box-height: auto; /*Can I do that? If not, why not?*/
  height: auto;
}

Thougths?

AmeliaBR commented 8 years ago

@frivoal

That's an interesting use case. For auto-sizing view-boxes, I'd only been thinking about the SVG case (fill-box or stroke-box), where the size can be determined explicitly from the contents independent of the container size.

However, applying a viewBox to a CSS box would effectively remove all external constraints on its internal layout. (You want it to lay out its contents, then you'll scale them to fit.) So you need to be able to specify how it should constrain that layout intrinsically (min-content or max-content).

I think that makes perfect sense to allow those keywords in the width/height portion of the view-box. What the view-box is defining is the width and height values that will be used for laying out child content, before scaling (or not) to fit in the actual width and height assigned to this box.

We'd have to think through the interaction of width, max-width, and view-box-width, but it's definitely do-able.

sdras commented 8 years ago

That is incredibly interesting and I could see a lot of uses for it. I think this could be a really giant leap for responsive dev.

In terms of the view-box-height, if I remember correctly, the current SVG spec doesn't support height: auto. Most browsers will interpret it correctly regardless but I've seen issues on IE or mobile safari. I defer to Amelia on that one though.

AmeliaBR commented 8 years ago

@sdras
The latest specs should be clear on auto height/width for <svg> now, for controlling the layout box dimensions based on the viewBox proportions. We don't have any way to specify auto values inside the viewBox itself yet, to determine the necessary dimensions based on the bounding box of the actual graphics.

sdras commented 8 years ago

Ah, excellent. Thank you for the clarification.

pkra commented 8 years ago

@frivoal 's use case also comes up for mathematical content; in fact, the MathML spec allows overflow="scale" though afaik there are no MathML implementation supporting it (for the web anyway). Having this in CSS would be great for all math rendering on the web.

frivoal commented 8 years ago

@pkra Yes, thanks for reminding me of the math use case. I'm running into it as well, and I agree that the same approach should be helpful there as well.

frivoal commented 8 years ago

@AmeliaBR Glad you like it. I was hoping you would, but kind of worried you'd show me how I completely misunderstood the whole thing:)

The interation between view-box width and max-width don't worry me too much. They have to be defined, but I don't think it's that bad.

I think we'll also need to be a bit careful about how that interacts with fragmentation, especially when the height / view-box height is auto. But that too seems just a matter of writing things properly, not a fundamentally hard issue.

freakk101 commented 4 years ago

Greeting for the day, Wonderful people. I have gone through the thread and did a bit of research as well, but I am unsuccessful to change viewBox properties using CSS. Proposal for adding viewBox CSS property is still valid? if it's not what is the available option to change the viewbox property using CSS?

AmeliaBR commented 4 years ago

@freakk101 The proposal (suggestion) is still open for consideration, but it has not been adopted or implemented. Currently, to animate the SVG viewBox you must either use JavaScript or animation elements. Alternatively, you may be able to create the effect you want by animating a CSS transform on a child group (<g>) element.

ShaggyDude commented 4 years ago

Plus one on the concept in general. I have not had time to digest all the pros and cons but, if nothing else we need to be able to not put the same view box markup over and over. Ex. <svg viewBox="0 0 24 24"..

This is totally in the realm of the visual and thus css.

denis-bosiy commented 3 years ago

+1