Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Child position differs from assigned if container has non-integer (%) position

I have centered (position: absolute; left: 50%; margin: -50px;) 100px width div (container).

It has absolutely positioned child div with overflow: hidden, its size is 100x2000 px (such height is for test purposes, as described below).

There is an image in child div, it is absolutely positioned. The image is 3100x100 px, it contains frames of animation.

I am animating this image by changing its style.left from 0 to -1100px, step is 100px. Everything is fine, but I encounter weird issue when body width is not even.

It can happen if there is scrollbar and the scrollbar has odd width (it happens for me on Chrome/Win32 for example). In this case image visually shifts by 1 pixel horizontally as soon as animated image goes through screen edge (for 1920x1080 it happens roughly at 9-10 frame of animation). I can't find workaround for this behavior.

Working example reproducing the problem can be found here

Child div height is set to 2000px to make sure scrollbar is visible. If your scrollbar has even width, you can reproduce the problem by resizing your browser window to odd width.

like image 612
mephisto123 Avatar asked Nov 22 '12 01:11

mephisto123


2 Answers

That happens because of the browsers rounding engines. Webkit apparently has some problems with 50% on even and odd widths.

One way to overcome the issue - re-position the .outer element based on window width

document.getElementById( 'outer' ).style.left = Math.floor( window.innerWidth / 2 ) + 'px';

DEMO

like image 97
Zoltan Toth Avatar answered Nov 20 '22 10:11

Zoltan Toth


You need to change .inner img position to relative and update your javascript. I made changes for you, so here is your solved code:

<!DOCTYPE html>
<html>
    <head>
        <title>test</title>
        <style>
            body {
                background-color: #000000;
            }
            .outer {
                position: absolute;
                left: 50%;
                margin-left: -50px;
            }
            .inner {
                position: absolute;
                width: 100px;
                height: 2000px;
                overflow: hidden;
            }
            .inner img {
                position: relative;
                top: 0;
                left: 0;
            }
        </style>
    </head>
    <body>
        <div class="outer">
            <div class="inner">
                <img src="http://lorgame.ru/test.png" id="img">
            </div>
        </div>
        <script language="JavaScript">
            var framesCount = 30;
            var framesCurrent = 0;
            var framesMoveLeft = true;
            var img = document.getElementById('img');
            var interval = setInterval(function() {
                if(framesMoveLeft == true){
                  framesCurrent++;
                  img.style.left = (img.offsetLeft - 100) + 'px';
                  if(framesCurrent == framesCount) framesMoveLeft = false;
                } else { // Move right
                  framesCurrent--;
                  img.style.left = (img.offsetLeft + 100) + 'px';
                  if(framesCurrent == 0) framesMoveLeft = true;
                }
            }, 100);
        </script>
    </body>
</html>
like image 31
Epsil0neR Avatar answered Nov 20 '22 10:11

Epsil0neR