The effect you are looking for is a little more complicated, but it can be done even without a shell element.
The main problem here is that elements naturally render from top to bottom, and not from bottom to top. Animating the CSS properties of the top
and height
element with relatively positioning allows us to implement a slide effect, but the element will still be displayed from top to bottom:
+-------------------------------------------+ | | ^ | | | Hidden area collapses upwards. | | | +-------------------------------------------+ <-- 'top' | | ^ | | Upper part of element (visible). | | | | | | Animation goes bottom-up. | | Element still renders top-down. | | | | | | +--|----------------------------------------+ <-- 'top + height' | | | | | | Lower part of element (hidden). | | | V | | +-------------------------------------------+
If we want to simulate the rendering from bottom to top, we must change the scrollTop property of the element during the animation, so that its lower part always remains in view:
+-------------------------------------------+ | | ^ | | Upper part of element (hidden). | | Hidden area collapses upwards. | | | | +--|----------------------------------------+ <-- 'top' and 'scrollTop' | | | ^ | | Element still renders top-down. | | | | | | Animation goes bottom-up. | | Lower part of element (visible). | | | V | | +-------------------------------------------+ <-- 'top + height'
We can use animate () with scrollTop
, but this in combination with top
and height
didn’t work correctly in my tests (I suspect scrollTop
is reset when top
or height
changed in the first stage of the animation, so it ends with 0
).
To get around this, we can handle scrollTop
ourselves through an optional step function, which we can pass to animate()
. This function is called with two arguments, now
and fx
, now
is the current value of the animated property and fx
is a wrapper around useful information, such as an animated element and property.
Since we always want scrollTop
to be the same as top
, we only need to check if top
animated in our step
function. If so, set scrollTop
to now
. This solution gives acceptable results, although it flickers slightly to my liking (this may be an artifact of my browser).
So, in the end, to realize this effect, we must:
- Get the original height of the element,
- Make the element
position: relative;
so that we can animate its top
property, - Minimize an element by setting
top
to its original height and height
to 0
, - Show an element (necessary in your violin from the moment
display: none;
), - Animate
top
to 0
and height
to the original height, - Give
scrollTop
the top
value at each step of the animation.
The result is in the following code:
$("#click").click(function() { var $revealMe = $("#revealMe"); var originalHeight = $revealMe.height(); $revealMe.css({ position: "relative", top: originalHeight, height: 0 }).show().animate({ top: 0, height: originalHeight }, { duration: 1000, step: function(now, fx) { if (fx.prop == "top") { $(fx.elem).scrollTop(now); } } }); });
You can check it in this script .