0

Say I have a parent div with width 500px. It has 13 child elements that should fill its width.

If I give each child element a width of 500 / 13 = 38.46... pixels, the browser will floor the pixel values, so I end up with 13 elements that take up a total of 38 * 13 = 494 pixels. There will be 6 pixels on the right side of the parent div that are not filled.

Is there an easy way to dither the child element widths so that the remainder (6 pixels) is distributed among some of the child elements, resulting in a total width of 500 pixels?

If I have to do the calculations manually and there's no way to get the browser to manage it, what dithering algorithm might I use in this case?

EDIT: A clarification -- I'm doing these calculations on the client side using JavaScript. Also, the size of the parent div and the number of child divs vary at runtime; the figures above are just an example.

kpozin
  • 25,691
  • 19
  • 57
  • 76
  • 1
    `"the browser will floor the pixel values"` - that's not true, as such. [Different browsers behave differently.](http://stackoverflow.com/questions/5581973/where-do-the-lost-pixels-go-in-a-percent-css-layout/5587820#5587820) – thirtydot Jun 29 '11 at 22:07
  • If you're doing the calculations yourself, I think you're restricted to JavaScript (for client-side modification); would solutions *using* JavaScript be acceptable (if so please tag '[tag:javascript]')? Or do you prefer a server-side solution (if so, please tag with the server-side language of your choice)? – David Thomas Jun 29 '11 at 22:10
  • Huh, even with percentages there is still a space left over: http://jsfiddle.net/apt2S/ – Dan Jun 30 '11 at 00:24
  • Thanks for that clarification, thirtydot. I've been working in WebKit-based browsers lately, so that's where my observation of flooring came from. – kpozin Jun 30 '11 at 02:31

1 Answers1

0

I'd suggest you just do everything with integer math yourself. You can then calculate what the uneven amount is and then decide how you want to distribute it across the elements. My supposition is that the least noticeable way to distribute the extra pixels would be to keep as many like width elements next to each other as possible.

One way of doing that would to calculate how many extra pixels N you have and then just give each N elements starting from the left one extra pixel. If you were worried about things not being centered, you could allocate the first extra pixel to the far left object, the second extra pixel to the far right, the third extra pixel to the 2nd from left, the fourth extra pixel from the 2nd from right, etc... This would have one more boundary between dissimilar width objects, but be more symmetric than the first algorithm.

Here's some code that shows how one could put the extra pixels on the end elements from outside in:

function distributeWidth(len, totalWidth) {
    var results = new Array(len);
    var coreWidth = Math.floor(totalWidth / len);
    var extraWidth = totalWidth - (coreWidth * len);
    var w,s;
    for (var i = 0; i < len; i++) {
        w = coreWidth;
        if (extraWidth > 0) {
            w++;
            extraWidth--;
        }
        if (i % 2 == 0) {
            s = i/2;               // even, index from front of array
        } else {
            s = len - ((i+1)/2);   // odd, index from end of array
        }
        results[s] = w;
    }
    return(results)
}

And here's a fiddle to see it in action: http://jsfiddle.net/jfriend00/qpFtT/2/

jfriend00
  • 683,504
  • 96
  • 985
  • 979