Open tabatkins opened 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).
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!
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?
@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.
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
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.
@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.)
@bradkemper
For non-SVG content, the viewBox would:
I'm not sure how this relates to clip-path
.
+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!
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;
}
@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.
+1 on animatable as well,
Great creative potential on animated viewbox.
Great to see this being discussed.
+1
+1
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
@jakearchibald Definitely a go.
Changed the issue title to reflect the beyond-SVG scope of the proposal. Apologies for ruining email threading of notifications.
+1
Y'all are great. Really excited about this.
👍
👌
👍
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.
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.
@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:
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.)
auto
height or width width proportional to a fixed value in the other dimension.<svg>
itself.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.
<svg>
elements within a document (e.g., for SVG icons in an HTML file), reducing markup and repetition.<img>
or <object>
), the viewBox is often used to determine how much space in the main document it should consume (by defining the intrinsic aspect ratio & size). This in turn affects the "media" for all media queries defined within the SVG file. If those media queries can alter the viewBox, you could generate infinite loops & there would need to be clear rules on how to resolve them.Only certain elements currently accept the viewBox attribute (svg, symbol, pattern, marker). Only some of these (svg, symbol) are "viewport elements" that re-define the px-to-percent ratio.
If viewBox became a generic property that you could specify on any element (by setting it to a value other than auto
), it would need to create a consistent behavior as a layout container for child content.
I personally think it's one of the biggest mistakes in SVG that patterns & markers don't reset the meaning of percentage lengths (it makes percentage lengths pretty much useless within pattern and marker content). There has been some talk of changing this in the SVG 2 spec, but it would be a breaking change & we haven't made that resolution. I would also like to see viewBox available on <clipPath>
and <mask>
. I don't mind allowing it on generic SVG container elements (<g>
and <a>
), effectively giving them the same layout model as a nested <svg>
. The other parts of the layout model, x
, y
, width
, and height
, have all been made geometry properties in SVG 2, although they currently would not have any effect if declared on a <g>
element.
A nested <svg>
element, even without a viewBox
attribute, redefines the coordinate system for child elements. In other words, it resets the percentage-to-px ratio and creates a translation based on the value of x
and y
. Therefore, there would need to be both a view-box: auto
value (default for SVG elements that normally take a viewBox
attribute) and a view-box: none
value (initial value for the property and default for all other SVG container elements).
These changes would require coordinating changes to SVG DOM properties that allow you to access the nearest ancestor viewport element for any SVG element. They need to either (a) be redefined to retrieve the nearest ancestor <svg>
or <symbol>
element, independent of any notion of viewBox or the basis of 100% or (b) be redefined to find the nearest ancestor whose computed value for view-box
is not none
(more useful, but more work for the implementation). Implementations would also need to update how they resolve percentage lengths.
<use>
element has special rules for how width & height values on that element interact with width, height, and viewBox on a re-used <svg>
or <symbol>
element. These rules would need to be updated & generalized to any element with a non-none computed value of view-box
, and implementations updated correspondingly.<svg>
element, the <view>
element and the #svgView()
fragment, which are not easy to represent in CSS. When a view is in effect, the effective viewBox
and preserveAspectRatio
values for the <svg>
element are over-ridden by those specified in the view. This shouldn't be a deal-breaker, though, since you can also specify transform
via those means, so any implementation is already going to have to propagate transform styles from the view to the SVG. It's just an extra headache & confusion to be aware of.auto
value I've described previously (the current behavior of an SVG if you don't specify viewBox
attribute), which creates a view-box based on the width and height in pixels, and therefore does not apply a scaling effect.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).
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.
One more reason for css-ified naming to view-box
is that it exists as a keyword in clip-path
👍
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?
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.
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
).
@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.
@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:
<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).viewBox
attribute on the outermost <svg>
element.width
and height
attributes on the outermost <svg>
element and/or by other CSS properties.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.
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.
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>
.
@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.
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?
@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.
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.
@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.
Ah, excellent. Thank you for the clarification.
@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.
@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.
@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.
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?
@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.
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.
+1
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