Floating with css percentages, full-width browsing

713 views Asked by At

Original question:

Okay, this is plain and simple css. But there's a bug on my site and i can't get it out !

I making a site with this design: http://cl.ly/image/1j231y2x3w07

The site i fully responsive and makes use of the css-aspect-ratio-technique:

HTML:

<div class="post small">Post that is small</div>
<div class="post big">Post that is big</div>
<div class="post tall">Post that is tall</div>
<div class="post wide">Post that is wide</div>

CSS/LESS:

.post {position: relative;}
.post:after {display: block; content: '';}

.post.small {width: calc(1/4 * 100%);}
.post.small:after {padding-top: 70%;}

.post.big {width: calc(1/2 * 100%);}
.post.big:after {padding-top: 70%;}

.post.tall {width: calc(1/4 * 100%);}
.post.tall:after {padding-top: 140%;}

.post.wide {width: calc(1/2 * 100%);}
.post.wide:after {padding-top: 35%;}

You get the gist of it.

I also make use of the excellent plugin Packery.js to keep track of floats and position. I mostly use is as a resize and animation helper.

But being fully responsive gives me a problem. For example when the browser window is 1304px wide, i get some odd height values(ex. 477.4px) due to the technique mentioned above. Because of the odd numbers i am not able to keep my grid, let alone my design.

And if the windows width is not divisible by 4 i get overlapping or 1 pixel white lines.

I've been working on this for quite some time now, and need some fresh eyes. So, if anybody got inputs to a solution i would be very happy. Thanks :-)

The solution:

A big thanks to @ScottS – great advice !

function frontpageResize() {
    // container ... duh.
    var container = $('#frontpage-wrapper');
    // body width.
    var bWidth = window.innerWidth;
    // get the pixels missing for making bWidth divisible by 20.
    var divisibleBy =  bWidth % 20; 
    // setting an alternative width.    
    var altWidth = Math.ceil(bWidth - divisibleBy + 20);
    // what's missing?
    var leftover = altWidth - bWidth;

    // if body width is divisible by 20 all is peaches?     
    if(divisibleBy === 0) {
        container.width(bWidth);
    } else {
        // else set the alternative width as body width and set margin-left.
        container.width(altWidth).css({ "margin-left" : -leftover / 2 + "px"}); 
    }
    // relayout Packery.js
    container.packery();    
}
1

There are 1 answers

2
ScottS On BEST ANSWER

The Only Way You Will Eliminate All Rounding Issues

To get the quartering division of width's without issues, as you noted, you need a total width that is divisible by 4. To get the height divisions with the percentages you are using you need a total width that is divisible by 20 (35% of 20 = 7, a prime number; there is no other values between 1-19 that can be multiplied by 35% without a fraction being generated).

So that means you need your widths to not shoot for 100% window width, but rather the width value that is the next smallest division by 20 (and then perhaps center your display, so that the 0 to 9.5px left over become side margins through an margin: 0 auto rule).

So your theoretical calculation you need for your width value needs to use a modulus function, something like this:

@width - mod(@width, 20) //in LESS

or

width - (width%20) //in javascript

As you can see, though, the point is you would need a dynamic action that CSS does not have available natively to make it pixel perfect.