Search code examples
javascripthtmlmobilemobile-safari

How to center 'Getting Data' on mobile screen


While developing a site for many browsers, mobile and desktop, I've noticed that the following CSS works nicely to center a loading div.

img.loading1 {
    position:absolute;
    left:50%;
    margin-left:-16px;
    top:50%;
    margin-top:-16px;
    z-index:10
}
.loading2 {
    color:#006BB2;
    position:absolute;
    left:50%;
    margin-left:0px;
    top:40%;
    z-index:5
}
.loading3 {
    position:absolute;
    width:100%;
    height:100%;
    left:0;
    top:0;
    background-color:lightgrey;
    opacity:0.85
}
<div id="container" style="position:relative">
    ...content ommitted...
    <div id="loading" style="display:none">
        <div class="loading3"></div>
        <img class="loading1" src="images/loader-ajax.gif" width="32" height="32">
        <span class="loading2" id="getting">Getting your request...</span>
    </div>
    ...content ommitted...

The div's display gets set to 'block' and the 3 items center great.

However, on a mobile screen, while the horizontal is right on, the vertical position could be off-screen depending on the height of the 'containing' div.

Is it possible to find the center of the screen and position the image and span there with Javascript?

Edit 1: Must the height of the loading div be set to be the height of the screen for this to work?


Solution

  • Related info:

    Every absolutely-positioned element is positioned relative to a container. The default container is the body tag.

    If no dimensions are specified, an element with absolute position is shrink-wrapped to the size of its content. When calculating the size in JavaScript, the value returned is whatever the current size happens to be, based on the content it contains. The element will not have the same size as its parent unless the width or height is explicitly set to 100%.

    Without using jQuery:

    Get the x and y location of the container element (relative to the viewport), the width and height of the viewport, and the width and height of the element.

    Set the top to half the viewport height, minus the container y position, minus half the element height. Set the left to half the viewport width, minus the container x position, minus half the element width.

    // Center an absolutely-positioned element in the viewport.
    function centerElementInViewport(el, container) {
    
        // Default parameters
        if ((typeof container == 'undefined') || (container === null))
            // By default, use the body tag as the relative container.
            container = document.body;
    
        // Get the container position relative to the viewport.
        var pos = container.getBoundingClientRect();
    
        // Center the element
        var left = ((window.innerWidth >> 1) - pos.left) - (el.offsetWidth >> 1);
        var top = ((window.innerHeight >> 1) - pos.top) - (el.offsetHeight >> 1);
        el.style.left = left + 'px';
        el.style.top = top + 'px';
    }
    

    Here's a jsfiddle demo. If there are problems running it in jsfiddle, try this standalone demo.

    Tested it in IE7/8/9, Firefox, Chrome, Safari, and Safari Mobile (iOS). The only thing found to cause a problem so far is if the absolutely-positioned element has a margin (which this function does not support at present).

    Haven't tested in a responsive design yet.

    Note: Be careful not to call this function when the page first loads. If the browser was scrolled or zoomed and then reloaded, the page may not have been rescrolled or zoomed back to where it was yet, and the resulting position would be incorrect. Setting a timer of 100 msec before calling the function seemed to work (allowing the browser time to rescroll and rezoom the page).