Bug when using absolute position and percentages to vertically center child div

12,494

Height and top percentages are relative to the height of their containing block - i.e. the div with class "container". The containing block's height is determined by the height of the div with class "pretendImage".

Width, left and margin-left percentages are relative to the width of their containing block - i.e. the div with class "container". The containing block's width is determined as a percentage of its containing block, which in the jsfiddle case is the initial containing block, which is itself the same as the width of the viewport. This is not how you are calculating the percentages you think you need. You can handle this by shrink wrapping the element which is position:relative (use display:inline-block; or float:left;) and create another wrapper div outside that to space out the elements in the viewport.

The weird one is the margin-top (and margin-bottom) percentages. These are relative to the width of the container block. This is not helpful, and there's little that can be done about this unless the containing block has a known and fixed aspect ratio, in which case you could calculate the percentage value of the height needed from the width and the aspect ratio.

No idea what Safari is doing, but it sounds seriously buggy.

Share:
12,494
Admin
Author by

Admin

Updated on June 14, 2022

Comments

  • Admin
    Admin almost 2 years

    I have a div that is my "popup" that I'm animating to show up in the direct center of its parent div. So I'm using absolute positioning, negative margins, and left+top to position it so that I can simply animate it with -webkit-transform: translateY(-100%) on hover. Works great on Safari and Mobile Safari.

    If you use pixels in Chrome or Firefox it works fine, even if you use all percentages but set the parent div width using pixels it will work. BUT, if you use all percentages FF+Chrome seems to go completely bunk and render the percentages based off something I can't figure out.

    Fiddle Example: View this in Safari and FF/Chrome to see that Safari renders #pixels just the same as #percents is and should be rendered in both. Is it Safari that's rendering this wrong then?

    <div class="container">
        <div class="pretendImage"></div>
        <div id="percents"></div>
    </div>
    

    and my CSS:

    #percents {
        width:100%;
        height:100%;
        position:absolute;
        top:50%;
        left:50%;
        margin:-50% 0 0 -50%;
    }
    .container {
        position:relative;
        width:50%;
        height:auto;
    }
    .pretendImage {
        width:200px;
        height:200px;
    }
    

    Well I found a workaround by adding an additional wrapper. I'd still like to know what causes this though.

    My workaround: Fiddle Uses a wrapper to avoid having to compute the top+margins the inner div that uses 80% width/height.

  • Admin
    Admin over 10 years
    Wow, okay so the margin-top in Safari is using the height of the parent div to determine what margin-top:-40% is? While normally it should be using the width of the parent div for reference? I had no idea that it would reference the width of the parent, in my opinion Safari's method makes more sense since the top/bottom margins deal with height they should be affected by height when using percent. Cross-browser issues like this will be the death of me.