Open keithjgrant opened 7 years ago
Adding here what I replied to @keithjgrant via Twitter:
In order to interpolate to/from an auto
or other keyword value, you need to have a way of describing the intermediary state. For lengths, intermediary states can usually be described via a calc()
function. 10% of the transition from 50px to 20em is calc(0.9*50px + 0.1*20em)
. So the most generic approach to supporting transitions with keywords would be to allow the keywords to be used in calc()
, with a real-time substitution of the current computed value that the keyword would create.
Sure, there are edge cases where the performance would inevitably be horrible (e.g., if you are transitioning to/from auto
at the same time you are also changing things that would cause the current computed value of auto
to change), but that shouldn't be reason to prevent its use in more sensible cases.
@keithjgrant yes, this is a real problem.
For the moment, we set up transitions on max-height value (using magic numbers for values, max-height = enough_and_pray_the_content_is_not_that_tall), and if you want to do it including accessibility pov, you have to transition on visibility (as display is not possible, cf this accordion https://a11y.nicolas-hoffmann.net/accordion/?animated=1 ) with a delay... really complicated for something that should be simple. :)
Looking around the web, you can easily see that this is a constant problem for developers. Velocity.js even notes this specific missing feature in its first paragraph of why it exists (https://fabric.io/blog/introducing-the-velocityreact-library). I can probably give a ton of references (on request) of developers rendering an element, measuring it, setting it's height to 0 then animating to that specific height. Even JQueryUI does a similar measurement technique just to get this to work and it's been around for almost a decade now.
What can we do as the larger software development community to petition this change and make sure it gets in on the next iteration?
Do we need to have more people come here and upvote this bug? Do we need to email a specific individual? Let us know so we can let you know what we need most.
I too am curious what we (the web programming community in general) can do to petition a change in the spec... I've got a few issues I know I could get quite a few people backing.
I caught up with @dbaron about this recently and it seems a likely way forward is to make 'auto' into a computed value. As well as enabling animation with auto
, that would also make it possible to write expressions like calc(auto + 10px)
. While that might not be trivial to implement, since there is interest from authors' and, I believe, browser vendors, it seems promising.
(One way to push this forward would be to submit a patch to one of the open-source browsers for this. Once you've proven the technical feasibility of this, it's easier to argue for it to be added to the spec.)
auto
is already a computed value; the thing that needs to happen is adding support for auto
to calc()
.
Awesome I'll start looking into it using Firefox since I think theirs would be the easiest source code to get a hold of. That said, it may take me a while due to lack of cpu resources (my computer is a 2 core 2.4ghz processor... it's going to take a while to build).
Thank you very much for bringing this up. We currently work around this by reading out an elements scrollHeight
and transitioning to that height, only to revert the element height to auto
on transitionend
. So making this a platform feature would be fantastic.
It has been suggested that we use max-height: max-content
.
But trying to get the browsers to implement either has been very difficult, as the CSS animations are typically done between 2 known values, which is why animation usually needs to be done with something like max-height: 500em
.
As an aside (and for some of the background on this), I've been trying to get browsers to support auto-height <iframes>
and <textarea>
s, which will work in pretty much the same way:
https://github.com/craigfrancis/iframe-height
https://discourse.wicg.io/t/feature-request-animating-max-height-height-based-on-content/1403
+1. Not being able to transition on height: auto
and display: <anything!>
(You can't even do a transition-delay
on display
) has always been a big pain.
Just FYI I'm currently out of the country and I'm also checking with my legal department to see if this is something I'm allowed to do due to where I work (non-compete and helping competitor issues). I'll be back in town on the 20th.
@nilssolanki That's the same trick we're using and it's just annoying.
@Jakobud I would say animating display is a bit out of the bounds of this request and may also have a few edge cases that would be interesting (animating inline to block?).
My legal department has come back to me informing me that I'm unable to currently work on this request due to non-compete legal stuff. That said, I'll have to (frustratingly) recuse myself of any code writing for this feature.
Just to note, I also asked a google groups question here if anyone is interested in taking this up. It should give a basic guide to how I was planning on tackling the problem.
Just want to make sure this is still happening.
This is actually rather important because, yes, we can precalculate a value for height and other properties using javascript and things like document.getElementById(elementID).scrollHeight+'px'
, but sometimes we need the property to have an auto value after the animation/transition so that we can make changes inside and around the element that the element will respond to appropriately.
For example, I have an element that transitions from a height of 0 to a height of 'auto'. After the transition is completed I want the height of the element to be able to adjust correctly to the changing elements inside of it without me having to recalculate it myself.
So if it really is just adding auto
compatibility to the calc()
function, as @dbaron has mentioned, is someone working on that, and if not, how would one do so?
To my knowledge no one has picked up this work and I'm still barred due to legal constraints. But if you download the source code and read the conversation here: https://groups.google.com/forum/#!searchin/mozilla.dev.tech.layout/auto%7Csort:relevance/mozilla.dev.tech.layout/fFuJqwXvu2I/6_mt7HmhDAAJ
It should give you a few locations to pinpoint where you would need to make the changes you need. Not sure if those are all of them but it should give you a starting point for learning the code base.
Good luck, I hope you do take this up because it would be an amazing addition!
I'd have to review to make sure that 'auto' doesn't have any special behaviors that make it incompatible with explicit lengths in some situations. That is, any place where the layout system does special things if the width/height is "auto", such that replacing the "auto" with its equivalent absolute length would give a different result.
I can't remember the source, but it was recommended we use height: max-content
rather than auto
... this might have started from you TJ.
Where it would be nice if we could use this keyword for iframe's and textarea's as well.
@k2snowman69 I would love to take this on and get it done. My question is what all would I need to change? I understand that there are the specification pages that explain how the transitions should be interpolated, and that those should be changed if this is added, but is there also some actual coded function or set of functions that would need to be modified? If so, where can I find them?
@tabatkins Do you know of any situations where that would be the case? (that auto acts differently than it's explicitly stated px size?)
Linked to this discussion in an answer at Stackoverflow where I point out that transition to nevermind, deleted the answer as I think I got confused somehow - doesn't seem to workheight: max-content
does seem to work in Chrome: https://stackoverflow.com/a/45203565/4200039
How can I transition height: 0; to height: auto; using CSS? is currently the top-voted question in the css-transitions
tag, with nearly 5 times as many votes as the third-highest.
Also, what's the story with bugzilla these days as far as CSS? There's this bug - pointed here.
While height is easy to get to the calculated auto through max-content, it would be best if this were to work for multiple properties such as width (there is no setting comparable to auto) and others. It is impossible to use javascript to get width to work properly without manually doing the math to remove the L&R margins, padding, and border from the 100% calculation, and other properties have similar setting problems.
Using the pre-calculated auto value as the target setting for each property that has an 'auto' option, while actually setting it to 'auto', would be the best method from what I can see.
PS: The data from Stackoverflow suggest that this is the most requested feature for the next CSS update. Using Stackoverflow's highly voted issues would probably be a good place to look for other features that might be good to include in the next version.
I used to really really want this feature, but over the years have found myself being content with transitioning a transform in many cases, while having a parent element set in inaccessible ways...
.parent {
pointer-events: none;
visibility: none;
overflow: hidden;
}
.element {
pointer-events: auto;
visibility: visible;
transition: transform ease .375s;
will-change: transform;
}
.transformed .element {
transform: translateY(-100%);
}
Here, the -100%
seamlessly takes care of the auto
height and transitions a texture over possibly invaliding layout during a height
transition. Not saying this is the silver bullet for the issue, but offering what I've found to be a more performant option for most cases. And furthermore, if we did get the ability to transition to/from auto
, I'd rarely use it over this approach. Though, this obviously doesn't handle the case where you'd want flow content to move along with the "height" transition, which again, is not as performant.
@jonjohnjohnson do you have a codepen/jsfiddle example of this anywhere and if not would you mind posting an example here? Many thanks
@cohsteve Quick -> https://jsfiddle.net/rwozw4bs/
Also, read up on FLIP animation methodology to see how you *could approach animating transforms while simulating the movement of flow content. https://aerotwist.com/blog/flip-your-animations/
@jonjohnjohnson A transform effect works for absolutely positioned elements. But if the element is statically positioned, it still takes up space in document flow when scaled down to height 0.
Transitioning max-height
was also mentioned above, but this too has a problem: the timing function is unreliable, since part of the transition will continue well after the max-height has reached the actual height of the element.
@keithjgrant correct. I find the gains from transforming a texture and not invalidating layout worthwhile, as opposed to the *few times I find myself wanting to animate within a flow.
Just making sure that this project hasn't been abandoned.
@dbaron, I see you are also the one assigned to the Mozilla ticket as well? (https://bugzilla.mozilla.org/show_bug.cgi?id=571344)
(I don't mean to be so pokey about this. I just keep running into designs where having this would immediately make the desired-but-impossible possible. So I hope that a fix for this bug will come soon.)
How is this, after so many years, still not solved?
Bump
I've written a polyfill which converts the max-height
+ overflow:hidden
hack-around for this issue into a more precise height
transition. https://github.com/eoghanmurray/height-transition-polyfill
The basic idea is to measure the height at the start of the transition and assign it via style attribute. For the reverse transition from 0px to auto, because of the overflow:hidden
, the scrollHeight
attribute gives a good approximation of a target height for transitioning. (all these extras are removed after transition completes).
Transitioning from/to auto
doesn't appear to cause any performance or other difficulties for the overflow:hidden
case, as the internal element layout doesn't need to be recalculated (so e.g. height can't affect width).
I believe this special case (transitioning width/height with overflow:hidden to/from auto) represents 95% of the usecases [citation needed!], and should be a lot simpler to implement/standardize vs. the more general to/from auto/max-content. Is there an argument to be made for focusing on this first? (i.e. wish this case was standardized 10 years ago!)
I'd like to add that transitions/animations on auto
valued properties should also be triggered when content changes:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Replaced content transition</title>
<style type="text/css">
div
{
border: 2px solid #caa;
background-color: antiquewhite;
padding: 1em;
margin: 2em auto;
width: 80%;
transition: height 1s;
}
</style>
</head>
<body onload="setTimeout(() => document.getElementById('replaceMe').src='b.png', 2000)">
<div><img id="replaceMe" alt="" src="a.png" /></div>
</body>
</html>
@SetTrend, the proposal sounds good, but I think it is too complicated. Think ... when having auto height, from what height expected to began the transition when loaded page of whapper containing only text? Form 0 or should transition be ignored in first paint? Then when screen width changed and text wrapps to more or less lines expanding or collapsing its wrapper size - would you expect transition to be applied for wrapper height? Maybe transition should apply when fixed height size changes to "auto", and when opposite then on initial paint to ignore the transition, otherwise would look weird like in my bottom link.
See this Chrome bug https://lab.laukstein.com/bug/input having since beginning of CSS3 transitions and imagine how wrong it can get if the spec proposal gets wrong, or browsers gets it wrong.
@SetTrend Interpolations work on the computed value. If you interpolate from auto
to auto
then it won't be smooth. This already happens if you have height: 100%; transition: height 1s
and you change the height of the containing block. Then the used value of height: 100%
changes, but it's a sudden change since both the 100%
starting point and the 100%
end point are updated.
@laukstein / @Loirooriol: Good thoughts.
First of all, I would suggest to have transitions and animations always be based on the computed* device pixels value, regardless of the CSS length currently being applicable to an element. Doing so, we get an abstraction layer between how a width
or height
is declared and what it really is on the device.
Then, in the event of (a) content changing, (b) styles getting dynamically applied or (c) transitions/animations being triggered, I would - figuratively speaking - draw the page having transitions/animations disabled. Then I'd get the computed device pixels values for all elements properties, and store those "target" device pixels values as shadow properties along with those elements. Next, I would re-enable transitions/animations and have them animate all elements whose current (probably in-transition) computed device pixels value deviate from the newly computed "target" device pixels value accordingly.
I once wrote a JavaScript function that works exactly like this (using hidden shadow elements, so running transitions on the target elements won't get interrupted) and, from my observation, it works like a charm so far.
I'm not sure, though, if it was necessary to re-evaluate descendant elements having width
/height
transitions applied while an anchestor element is being in transition, or to just have descendants strictly animate to their "target" size once it has been computed, regardless of its anchestor's in-transition dimensions.
@laukstein : Given my above explanation I would suggest to use the computed "target" device pixels value as an immediate starting point for any initial transition/animation.
* I wrote about "computed values" but I'm actually referring to "used values".
@SetTrend, let's say your transition wrapper contains a text and now is added an image into it expanding its height with transition. Because now the wrapper size and its content size differs till transition end, would you expect always to flicker it with scrollbar till transition end? - know that having scrollbar will mean less width and some text wrapped to more lines, while when transition ended you would expect no more scrollbar and text wrapped normally - no extra line wrapping due to scrollbar - that saying it will flicker delivering bad UX. The workaround would be to add overflow: hidden
for the transition wrapper but that sound already bad and as a limitation imagining to apply it to all places using this type of transition.
@laukstein : Yes, absolutely. That's the intrinsic nature of a transition: Intermediate state. It's up to the web page designer to circumvent and handle such condition in a sensitive manner.
Another year, another checkup.
I'm surprised that this bug still hasn't been fixed or even committed to. At this point pretty much everyone agrees that transitioning to auto is a necessary feature. Until this gets fixed, we're stuck with a bunch of ugly workarounds, each of which have a catch.
The question now is what will it take to get it implemented and who is in charge of taking those steps?
Heck, if it's something I can do, I'll do it. But I'm here because I don't know where to start and I'm assuming someone here does.
So, what's it gonna take?
Hi, what I'm about to mention isn't exactly a height: auto
solution but it doesn't rely on max-height
being set to a exceptionally high value which will allow an element to expand to any size, instead it relies on max-height: 100% through a flex element.
While I was working on a component library we had the need for an "Expander" component and I managed to build something that expands to "100% height" of the element but with max-height: 100%;
.
I'm wondering is this a bug that may be "fixed" in browsers in the future, or is it somewhat safe to assume that since this is working due to the flex
specifications it's safe to use?
I believe it works by the fact that display: flex;
elements are aware of their own size and as such can adjust to their "max height". Somehow it only works if it's not a direct element child of the flex container though.
@jchiem that looks like a great solution, and you should also post it here: https://stackoverflow.com/questions/3508605/how-can-i-transition-height-0-to-height-auto-using-css It's certainly the best CSS solution I've seen. Incidentally, the nested child is likely needed as the first child (.expandercontainer2 in the non-working example) is rendered as a flex-item, so it's dimensions are being controlled by the flexbox model, rather than preserving intrinsic dimensions like the .expandercontent element does. Of course we still need the spec updated!
I really wonder this issue opened in 2016 and still hasn't fixed.
It's still a big issue it seems. Even after all these years, there is still no good solution: https://stackoverflow.com/questions/3508605/how-can-i-transition-height-0-to-height-auto-using-css
Could you please give this problem some love? This is making CSS transitions useless in 90% of the cases where we want to use them.
This bug https://bugzilla.mozilla.org/show_bug.cgi?id=571344 is 11 years old! And this functionality is still required. Maybe a decade ago it was computationally hard task but nowadays even phones use GPU acceleration.
The workaround from @jchiem is pretty good, but the smooth appearance/disappearance of the content only works within the container of the component. Everything below is moved instantaneously (Example: https://rene78.github.io/faq-accordion/)
Almost 15 years ago, we were solving this with jQuery.slideUp() / jQuery.slideDown(). It's a bit sad that this solution seems to still be the state of the art :smile:
As a web dev, the expected result is that simply having height: 0
→ height: auto
be animatable using a CSS transition, and working the exact same way as if the CSS was height: 0
→ height: 400px
, if the calculated height of the element was 400px. The browser would only have to calculate this pixel value once, at start of transition?
Currently, I'm seeing awful max-height
hacks which have inconsistent animation timing or worse, chopped off content due to a too low value for max-height
.
Just out of curiosity ...
I assess that we all agree on this being useful, and I assess that we all agree that the browser implementation of this feature request is a snap ... Then what's keeping it from being approved?
This requires allowing calc()
to accept auto
(so you can represent intermediate values) which may not ending being trivial. e.g. see https://github.com/w3c/csswg-drafts/issues/626#issuecomment-311221589
If someone has the time to implement that in one of the engines, it would be a help.
It looks like we've got a stupid standoff between the browsers and the spec.
The browser people will wait for the spec to specify it first, but here in the suggestion for addition to the spec, the spec designers are saying to implement it in the browser first.
Somebody do something please, instead of waiting on the other person to do it.
Just add to the spec that "calc(auto)" should calculate the value of "auto" for the property.
Please. It's been so long.
Just add to the spec that "calc(auto)" should calculate the value of "auto" for the property.
It's not that easy. auto
has several special behaviors, for example, it enables justify/align-self: stretch
. What happens if you have height: calc(auto + 5px); align-self: stretch
? Should the box not be stretched, since height
is not exactly auto
? Should the box be stretched to fill the container, because it includes auto
? Should the box be first stretched to fill the container, and then grow 5 extra pixels?
And that's just one case, several specs should be revisited and every interaction with auto
should define how combinations with auto
behave.
Perhaps I'm missing the obvious, but do we really need to solve general case for calc(auto)
, if the goal is to just enable transitions from some value to auto
? Can't simply the computed pixel value be used in the animation engine? I understand that enabling calc(auto)
is an elegant solution, but it seems also full of tricky edge cases. Right now it's super confusing that height: 0
→ height: auto
does not animate.
Yes, calc(auto)
is needed because auto
computes to auto
(it's not resolved into a length until used-value time), and transitions interpolate computed values.
Can't simply the computed pixel value be used in the animation engine?
This, exactly.
Right now, the workaround we all have to do, is to use JS to measure the height that the element should have, then set that value explicitly using el.style.height
.
Why can't the browser engine do the same that we do, to make this work? If JS can do it, the browser engine can definitely do it.
I can see why calc(auto)
might be difficult, because calc()
can do arbitrary expressions, and additionally auto
might change during the animation. But that's not what we need. We just need auto
. The standard, default case is not working right now.
I understand it might be difficult to solve every little edge case. But we're talking about the 99% common case here. The most obvious common case does not work, making CSS animations pretty useless in half of the cases where we'd want to use them. Instead of trying to solve all egde cases, and then do nothing, why not solve the common case first, and leave the edge cases for later, rather than leaving us all in the cold?
Why force all of us to do the size calculation manually in JS? If we can do it in JS, the browser engine can definitely do the same in the engine. In this case, it is warranted, because this is such an important case - the default case.
(Edited: current resolved-on proposal is at https://github.com/w3c/csswg-drafts/issues/626#issuecomment-1800254442)
https://drafts.csswg.org/css-transitions/#animtype-rect
It would be incredibly useful to be able to transition to (or from)
height: auto
. As it stands now, you need to jump through a bunch of hoops in JavaScript to simulate it. This is used frequently for transitioning in alert boxes, opening accordions, etc, but it seems silly that JavaScript is required.I’m sure there must be discussion about this in the old mailing list, but I’d love to be privy to it here.