Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 290
Alexander Dreith Avatar asked Aug 03 '13 10:08

Alexander Dreith


1 Answers

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.

like image 104
Alohci Avatar answered Nov 07 '22 16:11

Alohci