How to shift element upwards to it's variable height using css


Tags: html,css,stylesheet,markup

Problem :

Main question

I have two divs, one nested inside the other and i wish to shift inner div outside (upwards) of outer div and slide-in it on a hover.

Markup is looking like so:

<div class="body">
    <div class="inner">Green is variable-height text which slides in on viewport hover</div>
    Blue is a viewport (&lt;body&gt;, visible part of a page), which content should be compressed upon green slide-in
</div>

And (a little pseudo) css:

.body {
    background: #aaf;
    height: 300px;
    width: 300px;
    overflow: hidden;
}

.inner, .body:hover .inner {
    -webkit-transition:all linear 0.2s;
    transition:all linear 0.2s;
}

.inner {
    background: #afa;
    width: 300px;
    margin-top:-some-magic-to-get-this-div-height;
}

.body:hover .inner {
    margin-top: 0;
}

And a final result animation i'd like to get, without using fixed height of green div:

example.gif

Also, this example (with a guessed and hard-coded height value of 2.5em) on jsfiddle to experiment with:

http://jsfiddle.net/n7vyLoh4/20/

Possible partial work-around (not satisfactory)

It is possible to partially implement what i want, using transitioning max-height instead of transitioning margin-top, the transition of max-height: 0; -> max-height: 100%; with overflow: hidden; set at all times works, but has two draw-backs:

  1. it doesn't slide in, it's more like drops the curtain
  2. it doesn't stop transition at the end of green div, it transits till the end of outer blue div, which especially noticeable at reverse transition, when it first travels all the way from bottom of blue div to bottom of green div before any effect is visible. Also, this means that despite transition time set to 0.2s, it will spend only fraction of this time on transiting trough green div, because this 100% are 100% of parent div, not inner one (and my question could be answered if there is a way to calculate the 100% of inner div height).

Here is an illustration:

example2.gif

And fiddle for that:

http://jsfiddle.net/bsd7vnwu/1/



Solution :

I think this is the effect you want. CSS doesn't allow you to get the height of an element to use in calc() for positioning and margins, so a little JS is needed.

CSS:

.body {
    background: #aaf;
    height: 300px;
    width: 300px;
    overflow: hidden;
}

.inner, .body:hover .inner {
    -webkit-transition:all linear 0.2s;
    transition:all linear 0.2s;
}

.inner {
    background: #afa;
    width: 300px;
    overflow: hidden;
}

.body:hover .inner {
    margin-top : 0 !important;
}

JS:

Array.prototype.forEach.call(document.getElementsByClassName('inner'), function (item) {
    item.style.marginTop = (item.clientHeight * -1) + 'px';
});

Demo:

http://jsfiddle.net/09tyLr9b/


    CSS Howto..

    How to get list of custom CSS properties

    How to check if Html element has a background-image css property in WebBrowser control C#

    How to change placeholder color in css

    How to get the root directory of wordpress in css

    How to align pictures on a menu bar?

    How to make a jQuery step animation?

    How to add css box-shadow using .style javascript property

    How can I make one