Reputation: 561
I have the following CSS definitions:
.detailsCollapsed
{
display:none;
height:0%;
width:100%;
-webkit-transition:height 40s ease-in-out;
}
.detailsExpanded
{
display:block;
visibility:visible;
height:100%;
width:100%;
-webkit-transition:height 40s ease-in-out;
}
These are applied to a div with some content inside of it.
I also have some javascript that when a div is clicked it changes the class name on the element. This works fine for expanding and collapsing but there is no animation on the iphone? (All other transitions I tried work fine with fluid animation) Any ideas?
Upvotes: 53
Views: 59564
Reputation: 11745
According to the W3C Spec on CSS3 Transitions, both length
and percentage
should be allowed for a transition on the property height
. So I guess it's just a matter of time until providing a percentage is supported in browsers.
Update 2022: Animating percent heights works just fine in latest Chrome/Firefox/Safari: https://codepen.io/fabb64/pen/BaYZXRM. Notes:
display: none
in the collapsed state because then the animation does not have a start value and directly jumps to the target value instead of animating it.overflow: hidden
on the contained text does not gradually reveal the text during animation, I'm not sure how to solve that.Upvotes: 19
Reputation: 29
There is no absolute solution to this issue.The desired result can be achieved through various workarounds. The browsers currently doesn’t support this since this involves transitioning an element into a height of auto, for which the browser would have to perform a reflow for every stage of that animation, which is not simple and expensive on performance side.
solution 1: max-height (ideal solution)
.slideup, .slidedown {
height: auto;
max-height: 0px;
overflow-y: hidden;
transition: max-height 300ms ease-in-out;
}
.slidedown {
max-height: 500px;
}
solution 2: transform : scaleY()
.slideup .slidedown {
overflow:hidden;
transition:transform 0.3s ease-out;
transform, not height!
height:auto;
transform:scaleY(1);
}
.slideup {
transform:scaleY(0); //collapse the view
}
Upvotes: -1
Reputation: 71
Here's my solution if the total height is not known
.container{
overflow:hidden;
max-height:20px;
transition-property: max-height;
-webkit-transition-property: max-height;
transition-delay: 1s; /*Set a delay for this css-propery so content also slides up*/
-webkit-transition-delay: 1s;
}
.container .content{
z-index:5;
background-color:LightGray;
margin-top:20px;
transform:translateY(-100%);
-webkit-transform:translateY(-100%);
transition:transform 1s;
-webkit-transition:transform 1s;
}
.container:hover{
max-height:9999px; /*apparently "none" doesnt work*/
transition-delay: 0s;
-webkit-transition-delay: 0s;
}
.container:hover .content{
transform:translateY(0);
-webkit-transform:translateY(0);
}
/*Less interesting stuff below*/
body{
background-color:navy;
}
div,label{
margin:0;
padding:0;
}
.container label{ /*Just a label to describe what you can do here*/
height:20px;
line-height:20px;
display:block;
z-index:10;
position:absolute;
background-color:maroon;
width:100%;
}
<body>
<div class="container">
<label>
Hover container
</label>
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras venenatis congue lectus pharetra interdum. Cras sit amet interdum ipsum, vel commodo ante. Maecenas quis libero eu tortor suscipit rutrum. Cras quam eros, malesuada ac semper sed, viverra condimentum nisl. Quisque lobortis porta purus non fringilla. Fusce erat eros, aliquam a diam quis, ullamcorper laoreet odio. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum pharetra scelerisque felis, vitae finibus dui lobortis non. Mauris iaculis rutrum vehicula. Nullam porta arcu et diam porta, in tristique nisl ornare. Mauris id ex maximus, lobortis erat a, laoreet justo.
Nullam tempus neque enim, nec consectetur enim fringilla ac. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Proin non rutrum nisl, sed vestibulum augue. Sed ac magna et metus tempus bibendum elementum id libero. Sed semper imperdiet risus et pellentesque. Aliquam commodo magna at rhoncus pellentesque. Vivamus tempus tellus lorem, a volutpat est pharetra nec. Vestibulum velit ligula, aliquet sit amet bibendum eget, viverra scelerisque tellus. Cras aliquam hendrerit bibendum. Etiam non faucibus nisi, sit amet cursus neque. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
Maecenas in eros ac elit pretium molestie. Mauris quis dolor erat. Suspendisse scelerisque gravida libero, rutrum consectetur metus ultrices in. Fusce eleifend, orci vitae sodales dictum, lectus nunc volutpat nulla, in efficitur dolor augue sed lorem. Nam ac lectus ultrices, ornare magna non, auctor neque. Mauris eros eros, bibendum commodo dolor non, posuere ultrices leo. Nullam ut laoreet ligula. Nulla posuere risus nec nibh fermentum, pretium consequat tellus eleifend. Vestibulum volutpat nisl quis euismod pulvinar. Donec hendrerit augue sed dui volutpat ultrices. Pellentesque mollis scelerisque metus, vulputate viverra risus pellentesque et. Duis nisi ante, faucibus in nunc et, semper varius turpis. Vivamus pharetra volutpat convallis.
Curabitur quis urna in orci tincidunt cursus vel ac dolor. Integer turpis augue, maximus eu lectus a, euismod consequat risus. Fusce leo lacus, dignissim vel sapien at, venenatis porttitor dui. Donec in metus non ex facilisis venenatis. In ac urna non tellus lobortis fringilla. Maecenas ornare dui nisl, gravida ornare purus aliquam in. Cras nec tortor eget neque volutpat pulvinar. In vestibulum, ante ut pharetra semper, nulla libero tincidunt nunc, a convallis orci dolor vel metus. Vivamus enim est, volutpat sit amet sagittis ut, efficitur at lacus. Morbi laoreet erat sit amet finibus finibus. Nulla sodales ut est non commodo. Aliquam sed purus a magna vehicula ullamcorper et id nunc. Curabitur aliquet tempor odio, euismod tempor ante consectetur ut. Proin neque sem, imperdiet sed est quis, ultricies tincidunt sem.
Donec nec sem id eros congue convallis eu in nibh. Etiam viverra sollicitudin maximus. In hac habitasse platea dictumst. Ut quis porta turpis. Duis egestas quam diam, id bibendum dolor imperdiet quis. Praesent ac odio in neque ultrices commodo. Nullam ac lacus sit amet dolor rhoncus tincidunt.
</div>
</div>
</body>
Upvotes: 0
Reputation: 13260
If you leave height:auto;
and use fixed values of max-height
you can simulate a transition:
.details-expanded {
max-height: 300px; /* try to guess a max-height for your content */
}
.details-collapsed {
height: auto;
max-height: 0;
transition: max-height 500ms linear; /* pick a proportional duration */
}
Pay attention to the transition duration and max-height
when the element is expanded. Play with the values until you get the wanted behavior.
This way you can get a transition between two defined values (in the above example, from 0 to 300) while the height
property will just "follow" the max-height
transition and grow until it gets the content's size.
DEMO 1 - a working example of this solution
DEMO 2 - just demonstration of what is going on in DEMO 1
For now transitions are implemented only between predefined values and I supposed it is because the engine cannot guess the initial or final value in some cases. What if you have a height transition which its final value is 50% but transition itself affects the parent's height somehow?! It would probably require several reflow calculations on each frame causing performance issues.
Like fabb said, the spec for CSS transitions determines that percentage values should be supported, so it might be just a matter of time until engines decides on which cases they're going to support transitions using dynamically valued points. Still, I'm not sure about what could be considered the correct behavior for auto
values thought.
Upvotes: 77
Reputation: 1092
Here is a solution for those who want to use percentages.
The trick is to contain it inside a div with a set height and width. If you are floating container div's this may not be ideal, but if you are absolutely positioning containers this should work pretty good and as long as elements are not overlapping each other.
here is the code
.container {
width: 500px;
height: 500px;
background: transparent;
}
.expand-content{
height: 0%;
color: #fff;
background: green;
}
.expand-content:hover {
height: 100%;
background: orange;
transition: all 2s ease;
}
.expand-content p {
font-size: 35px;
text-align: center;
}
<div class="container">
<div class="expand-content">
<p>Expanded Content</p>
</div>
</div>
on JSFiddle: http://jsfiddle.net/jtZ8j/7/
Upvotes: -1
Reputation: 129
I've used the following solution for elements where i need to toggle between display none and block, and keep the transition effect:
function slidedown(element) {
...
element.style.display = "block";
var timerId = setTimeout(function(){
element.style.webkitTransitionProperty = "height";
element.style.webkitTransitionTiming = "linear";
element.style.webkitTransitionDuration = "3.5s";
element.style.height = "500px";
}, 0);
...
}
the setTimeout function will force a short delay allowing the transition to occur after toggling the display property. Hope it helps.
Upvotes: 1
Reputation: 31
i had the same issue. Transition worked fine when "collapsing", but appeared with no transition (like being "switched on") on "expanding", when "display:none" was set before.
I accidentally came to a working solution while debugging: simply querying the "offsetHeight" seems to force an internal re-render of the element.
something like this:
showElement = function(){
...
oEl.style.display = "block";
var xDump = oEl.offsetHeight;
oEl.className = "show";
}
xDump is never used, but having it, made the differnce.
Upvotes: 3
Reputation: 169
Hopefully you've worked around this already, but I'm just writing to say I ran into the same problem: WebKit, at least on iOS 4.1, will not animate a transition if it was defined on an element styled with "display: none;", just like Nicholas mentioned above.
If your concern in not rendering this element is performance, like in my case, then I propose another solution than setting the height to 0. In your body's onLoad event callback, save the element in a variable and remove it from the DOM. Then re-insert it when it comes time to show it.
Upvotes: 0
Reputation: 846
It is the change from display:none to display:block that is stopping the transition. Try setting the collapsed style to display:block; height:0; overflow:hidden;
Note: a expanded height of auto will also stop the transition. If there is no height set on the containing block then a height of 100% is equal to a height of auto.
Upvotes: 1