Search code examples
cssvertical-alignment

How to vertically center *injected* div in HTML smoothly?


I have a div which is perfectly centered courtesy flex. Now I inject some content dynamically into the centered div. It remains centered of course, but it jerks into that centered position, which looks downright ugly.

Is there anyway to make the centering smooth? I tried setting transition: all but it has no effect.

Here is a fiddle for reference and quick testing: http://jsfiddle.net/qv8fLu4n/


Solution

  • I would suggest that on page load you grab the height of the element you want to shrink, set that as the max-height of the element, and then toggle the max-height property between 0px and initial height of element. For example:

    var i = document.querySelector(".injected-block");
    var maxHeight = i.clientHeight + 'px';
    i.style.maxHeight = maxHeight;
    
    document.getElementById("injection-button").onclick = (function () {
        if (i.style.maxHeight === '0px') {
            i.style.maxHeight = maxHeight;
        } else {
            i.style.maxHeight = 0;
        }
    });
    

    The animation can then be handled with a transition: max-height on the disappearing element, e.g.

    .injected-block {
        overflow: hidden;
        transition: max-height 0.2s;
    }
    

    Here's a JSFiddle

    EDIT

    Since the goal is to start with the element being invisible, you'll have to resort to some hacky stuff. Here's a function that will take the invisible element, stick it in an off-screen div, and return the height of it.

    var getHeight = function(el) {
        var hiddenDiv = document.getElementById('hidden');
        var clone = el.cloneNode(true);
        clone.className = '';
        clone.style.width = el.clientWidth + 'px';
    
        hiddenDiv.appendChild(clone);
        var height = clone.clientHeight + 'px';
        hiddenDiv.removeChild(clone);
    
        return height;
    };
    

    So you'd use it like:

    var i = document.querySelector(".injected-block");
    var maxHeight = getHeight(i);
    i.style.maxHeight = 0;
    

    This uses a div #invisible. Example CSS (would need to be adapted for your situation) for this is:

    #hidden {
        position: fixed;
        top: -1000px;
        left: -1000px;
    }
    

    And here's another JSFiddle. Cheers!