jQuery UI blind effect - reveal from bottom

jquery, jquery-ui

Solution

The effect you're looking for is a little tricky to achieve, but it can be done, even without a wrapper element.

The main issue here is that elements naturally render top-down, not bottom-up. Animating both the `top` and `height` CSS properties of a relatively-positioned element allows us to implement a slide-up effect, but the element will still render top-down:

+-------------------------------------------+
|                                           |  ^
|                                           |  |  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 bottom-up rendering, we have to modify the scrollTop property of the element during the animation, in order for its lower part to always remain 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 doing so in conjunction with `top` and `height` did not work correctly in my tests (I suspect `scrollTop` is reset when `top` or `height` are modified in the first animation step, so it ends up stuck to `0`).

To work around this, we can handle `scrollTop` ourselves through the optional step function we can pass to `animate()`. This function is called with two arguments, `now` and `fx`, `now` being the current value of the animated property and `fx` being a wrapper object around useful information, like the element and property being animated.

Since we always want `scrollTop` to be the same as `top`, we only have to test if `top` is being animated in our `step` function. If it is, we set `scrollTop` to `now`. This solution gives acceptable results, although it flickers a little too much for my taste (that might be an artifact of my browser, though).

So, in summary, to implement that effect, we have to:

- Fetch the element's original height,

- Make the element `position: relative;` so we can animate its `top` property,

- Collapse the element by setting `top` to the original height and `height` to `0`,

- Show the element (necessary in your fiddle since `display: none;` is applied),

- Animate `top` to `0` and `height` to the original height,

- Give `scrollTop` the value of `top` on each animation step.

Resulting 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 test it in this fiddle.

Problem

This could be really obvious and I'm completely missing it. I've searched for hours and can't seem to find a way to, using jQuery, reveal a hidden div from the bottom up. What I am trying to achieve is exactly as in the following link, but in reverse: http://jqueryui.com/demos/show/ I can slide a div from the bottom to the top, but this reveals itself as it moves, rather than being 'masked' in. Like I said, this could (should?) be really obvious and I'm not seeing it, but I've been looking for ages and can't find a solution to this relatively simple problem. Thanks, Ronnie

Original source