GordonM
GordonM

Reputation: 31740

HTML fluid columns: 25% + 25% +25% +25% != 100% in webkit/opera

I'm trying to build a multi-column layout that is adaptive (fluid, elastic, whatever you want to cll it) and have built a test document to try the idea out.

I did some calculations to come up with the figures that would allow x number of columns to fit exactly side by side in a page. 2 was easy (50%), as was 4 (25%) and 10 (10%). If you take a margin into account to leave a gutter and subtract that then you get the column widths in percentage you need.

All seemed to be going well, I built the CSS and HTML (see below) and tried it out in Firefox and it all worked fine. However, when I tried it out in Opera, Chrome and Safari, I ran into a problem. The columns didn't seem to add up to 100% total when placed next to each other, they seemed to fall slightly short. The more columns there were, the worse the problem got. By 10 columns, the problem was extremely noticeable.

Why is this happening? Is the Firefox behaviour the correct one, or is what's happening in the other browsers what's meant to be happening? More importantly, how do I work around it to produce a consistent result in all browsers?

I've built a JSFiddle of the below code, which is available here. The full test page is also available here. (The JSfiddle is just the relevant code, whereas the full page had additional stuff as well)

The CSS for doing the columns is as follows:

.columnHolder {
    overflow: hidden;
    background: #EFE; /* For layout testing only! */
    margin: .5em 0;
    padding: 0;
}
.columnHolder h1 {
    background: #EFF; /* For layout testing only! */
}
.column {
    float: left;
    margin: .5%;
    background: #FFE; /* For layout testing only! */
    text-align: justify;
}
.column.half {
    width: 49%;
}
.column.third {
    width: 32.33333%
}
.column.quarter {
    width: 24%;
}
.column.fifth {
    width: 19%;
}
.column.sixth {
    width: 15.66666%;
}
.column.seventh {
    width: 13.28571%;
}
.column.eighth {
    width: 11.5%;
}
.column.ninth {
    width: 10.11111%;
}
.column.tenth {
    width: 9%;
}

The (cut down version of the) markup I'm testing with is as follows:

<!DOCTYPE HTML>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Gordian Solutions</title>
        <link rel="stylesheet" href="./css/core.css" media="all" />
    </head>
    <body>
        <article style="margin: 1em 10% 1em 10%;">
            <section class="columnHolder">
                <h1>2 Column Test</h1>
                <div class="column half">
                    <p> Nulla hendrerit; <a href="#">nunc quis mollis</a> cursus; lectus libero viverra turpis, ut ornare arcu mauris eu ipsum. Curabitur et dolor dui, nec sagittis felis. Nam elit purus, eleifend nec pulvinar et, commodo id nisl. Curabitur pharetra, quam porttitor aliquam volutpat, nunc ipsum semper quam, non imperdiet libero risus non diam. Praesent et dui arcu. Praesent lorem lorem, malesuada sit amet egestas eget, lacinia sed velit. In congue sagittis ipsum, sed venenatis ligula vulputate vel? </p>
                </div>
                <div class="column half">
                    <p> Proin ornare, nisl et vestibulum dignissim, purus odio scelerisque massa, in mollis dolor neque nec massa. Vestibulum neque ipsum, sodales sit amet dapibus a, viverra sit amet est. Mauris odio mi, semper vel ultricies ac, hendrerit eget tortor. Quisque eu mi tellus, nec iaculis lectus. Duis pellentesque, ipsum nec molestie aliquet, lorem urna scelerisque risus, quis venenatis nibh dolor ac elit. Duis vitae nisi ante. <a href="#">Morbi dictum ornare</a> justo in fermentum. </p>
                </div>
            </section>
            <section class="columnHolder">
                <h1>4 Column Test</h1>
                <div class="column quarter">
                    <p> Nulla hendrerit; <a href="#">nunc quis mollis</a> cursus; lectus libero viverra turpis, ut ornare arcu mauris eu ipsum. Curabitur et dolor dui, nec sagittis felis. Nam elit purus, eleifend nec pulvinar et, commodo id nisl. Curabitur pharetra, quam porttitor aliquam volutpat, nunc ipsum semper quam, non imperdiet libero risus non diam. Praesent et dui arcu. Praesent lorem lorem, malesuada sit amet egestas eget, lacinia sed velit. In congue sagittis ipsum, sed venenatis ligula vulputate vel? </p>
                </div>
                <div class="column quarter">
                    <p> Proin ornare, nisl et vestibulum dignissim, purus odio scelerisque massa, in mollis dolor neque nec massa. Vestibulum neque ipsum, sodales sit amet dapibus a, viverra sit amet est. Mauris odio mi, semper vel ultricies ac, hendrerit eget tortor. Quisque eu mi tellus, nec iaculis lectus. Duis pellentesque, ipsum nec molestie aliquet, lorem urna scelerisque risus, quis venenatis nibh dolor ac elit. Duis vitae nisi ante. <a href="#">Morbi dictum ornare</a> justo in fermentum. </p>
                </div>
                <div class="column quarter">
                    <p> Donec magna justo, semper nec pulvinar eu, faucibus eget neque. Nunc egestas porttitor orci, eget congue nisl rutrum in. Donec ut dignissim nunc. Sed a suscipit ante. Fusce in nunc id risus elementum molestie eget eget eros. Nunc eget dolor sit amet eros accumsan porta. Phasellus nibh ligula, ullamcorper sed adipiscing at, luctus ut justo. Mauris eleifend posuere laoreet. Integer odio leo, dapibus a pretium sit amet, ultricies id augue. Aliquam mollis ipsum id urna varius iaculis. Class aptent taciti sociosqu ad <a href="#">litora torquent per conubia</a> nostra, per inceptos himenaeos. Pellentesque leo arcu, rhoncus ut suscipit ut, posuere a sapien. Nullam a nisi nec nibh facilisis egestas dignissim quis magna. Nulla nec egestas elit. Nunc nibh est, porttitor at hendrerit a, iaculis vel est. Cras pulvinar dignissim neque, et ultrices massa tristique nec. </p>
                </div>
                <div class="column quarter">
                    <p> Nulla hendrerit; <a href="#">nunc quis mollis</a> cursus; lectus libero viverra turpis, ut ornare arcu mauris eu ipsum. Curabitur et dolor dui, nec sagittis felis. Nam elit purus, eleifend nec pulvinar et, commodo id nisl. Curabitur pharetra, quam porttitor aliquam volutpat, nunc ipsum semper quam, non imperdiet libero risus non diam. Praesent et dui arcu. Praesent lorem lorem, malesuada sit amet egestas eget, lacinia sed velit. In congue sagittis ipsum, sed venenatis ligula vulputate vel? </p>
                </div>
            </section>
            <section class="columnHolder">
                <h1>10 Column Test</h1>
                <div class="column tenth">
                    <p> Nulla hendrerit; <a href="#">nunc quis mollis</a> cursus; lectus libero viverra turpis, ut ornare arcu mauris eu ipsum. Curabitur et dolor dui, nec sagittis felis. Nam elit purus, eleifend nec pulvinar et, commodo id nisl. Curabitur pharetra, quam porttitor aliquam volutpat, nunc ipsum semper quam, non imperdiet libero risus non diam. Praesent et dui arcu. Praesent lorem lorem, malesuada sit amet egestas eget, lacinia sed velit. In congue sagittis ipsum, sed venenatis ligula vulputate vel? </p>
                </div>
                <div class="column tenth">
                    <p> Proin ornare, nisl et vestibulum dignissim, purus odio scelerisque massa, in mollis dolor neque nec massa. Vestibulum neque ipsum, sodales sit amet dapibus a, viverra sit amet est. Mauris odio mi, semper vel ultricies ac, hendrerit eget tortor. Quisque eu mi tellus, nec iaculis lectus. Duis pellentesque, ipsum nec molestie aliquet, lorem urna scelerisque risus, quis venenatis nibh dolor ac elit. Duis vitae nisi ante. <a href="#">Morbi dictum ornare</a> justo in fermentum. </p>
                </div>
                <div class="column tenth">
                    <p> Donec magna justo, semper nec pulvinar eu, faucibus eget neque. Nunc egestas porttitor orci, eget congue nisl rutrum in. Donec ut dignissim nunc. Sed a suscipit ante. Fusce in nunc id risus elementum molestie eget eget eros. Nunc eget dolor sit amet eros accumsan porta. Phasellus nibh ligula, ullamcorper sed adipiscing at, luctus ut justo. Mauris eleifend posuere laoreet. Integer odio leo, dapibus a pretium sit amet, ultricies id augue. Aliquam mollis ipsum id urna varius iaculis. Class aptent taciti sociosqu ad <a href="#">litora torquent per conubia</a> nostra, per inceptos himenaeos. Pellentesque leo arcu, rhoncus ut suscipit ut, posuere a sapien. Nullam a nisi nec nibh facilisis egestas dignissim quis magna. Nulla nec egestas elit. Nunc nibh est, porttitor at hendrerit a, iaculis vel est. Cras pulvinar dignissim neque, et ultrices massa tristique nec. </p>
                </div>
                <div class="column tenth">
                    <p> Nulla hendrerit; <a href="#">nunc quis mollis</a> cursus; lectus libero viverra turpis, ut ornare arcu mauris eu ipsum. Curabitur et dolor dui, nec sagittis felis. Nam elit purus, eleifend nec pulvinar et, commodo id nisl. Curabitur pharetra, quam porttitor aliquam volutpat, nunc ipsum semper quam, non imperdiet libero risus non diam. Praesent et dui arcu. Praesent lorem lorem, malesuada sit amet egestas eget, lacinia sed velit. In congue sagittis ipsum, sed venenatis ligula vulputate vel? </p>
                </div>
                <div class="column tenth">
                    <p> Proin ornare, nisl et vestibulum dignissim, purus odio scelerisque massa, in mollis dolor neque nec massa. Vestibulum neque ipsum, sodales sit amet dapibus a, viverra sit amet est. Mauris odio mi, semper vel ultricies ac, hendrerit eget tortor. Quisque eu mi tellus, nec iaculis lectus. Duis pellentesque, ipsum nec molestie aliquet, lorem urna scelerisque risus, quis venenatis nibh dolor ac elit. Duis vitae nisi ante. <a href="#">Morbi dictum ornare</a> justo in fermentum. </p>
                </div>
                <div class="column tenth">
                    <p> Donec magna justo, semper nec pulvinar eu, faucibus eget neque. Nunc egestas porttitor orci, eget congue nisl rutrum in. Donec ut dignissim nunc. Sed a suscipit ante. Fusce in nunc id risus elementum molestie eget eget eros. Nunc eget dolor sit amet eros accumsan porta. Phasellus nibh ligula, ullamcorper sed adipiscing at, luctus ut justo. Mauris eleifend posuere laoreet. Integer odio leo, dapibus a pretium sit amet, ultricies id augue. Aliquam mollis ipsum id urna varius iaculis. Class aptent taciti sociosqu ad <a href="#">litora torquent per conubia</a> nostra, per inceptos himenaeos. Pellentesque leo arcu, rhoncus ut suscipit ut, posuere a sapien. Nullam a nisi nec nibh facilisis egestas dignissim quis magna. Nulla nec egestas elit. Nunc nibh est, porttitor at hendrerit a, iaculis vel est. Cras pulvinar dignissim neque, et ultrices massa tristique nec. </p>
                </div>
                <div class="column tenth">
                    <p> Nulla hendrerit; <a href="#">nunc quis mollis</a> cursus; lectus libero viverra turpis, ut ornare arcu mauris eu ipsum. Curabitur et dolor dui, nec sagittis felis. Nam elit purus, eleifend nec pulvinar et, commodo id nisl. Curabitur pharetra, quam porttitor aliquam volutpat, nunc ipsum semper quam, non imperdiet libero risus non diam. Praesent et dui arcu. Praesent lorem lorem, malesuada sit amet egestas eget, lacinia sed velit. In congue sagittis ipsum, sed venenatis ligula vulputate vel? </p>
                </div>
                <div class="column tenth">
                    <p> Proin ornare, nisl et vestibulum dignissim, purus odio scelerisque massa, in mollis dolor neque nec massa. Vestibulum neque ipsum, sodales sit amet dapibus a, viverra sit amet est. Mauris odio mi, semper vel ultricies ac, hendrerit eget tortor. Quisque eu mi tellus, nec iaculis lectus. Duis pellentesque, ipsum nec molestie aliquet, lorem urna scelerisque risus, quis venenatis nibh dolor ac elit. Duis vitae nisi ante. <a href="#">Morbi dictum ornare</a> justo in fermentum. </p>
                </div>
                <div class="column tenth">
                    <p> Donec magna justo, semper nec pulvinar eu, faucibus eget neque. Nunc egestas porttitor orci, eget congue nisl rutrum in. Donec ut dignissim nunc. Sed a suscipit ante. Fusce in nunc id risus elementum molestie eget eget eros. Nunc eget dolor sit amet eros accumsan porta. Phasellus nibh ligula, ullamcorper sed adipiscing at, luctus ut justo. Mauris eleifend posuere laoreet. Integer odio leo, dapibus a pretium sit amet, ultricies id augue. Aliquam mollis ipsum id urna varius iaculis. Class aptent taciti sociosqu ad <a href="#">litora torquent per conubia</a> nostra, per inceptos himenaeos. Pellentesque leo arcu, rhoncus ut suscipit ut, posuere a sapien. Nullam a nisi nec nibh facilisis egestas dignissim quis magna. Nulla nec egestas elit. Nunc nibh est, porttitor at hendrerit a, iaculis vel est. Cras pulvinar dignissim neque, et ultrices massa tristique nec. </p>
                </div>
                <div class="column tenth">
                    <p> Nulla hendrerit; <a href="#">nunc quis mollis</a> cursus; lectus libero viverra turpis, ut ornare arcu mauris eu ipsum. Curabitur et dolor dui, nec sagittis felis. Nam elit purus, eleifend nec pulvinar et, commodo id nisl. Curabitur pharetra, quam porttitor aliquam volutpat, nunc ipsum semper quam, non imperdiet libero risus non diam. Praesent et dui arcu. Praesent lorem lorem, malesuada sit amet egestas eget, lacinia sed velit. In congue sagittis ipsum, sed venenatis ligula vulputate vel? </p>
                </div>
            </section>
        </article>
    </body>
</html>

Upvotes: 2

Views: 173

Answers (2)

OmegaJunior
OmegaJunior

Reputation: 46

What usually helps is to omit the width setting from one or two columns. This allows the browser to calculate their widths by itself.

For instance, the search results overview of my website currently sports a 3-column layout, of which only the left and right columns have a width specified. The middle column's width (the article#main) is calculated by the browser:
http://www.omegajunior.net/found.html

Upvotes: 1

anotherdave
anotherdave

Reputation: 6754

The issue is to do with rounding differences when you start to use percentage widths — e.g. if the original container is 205 pixels & you have 4 x 25% columns, you are setting each column to have a width of 51.25px. You can't have quarter of a pixel, but how this gets handled can vary from browser to browser — some might drop the quarter pixel in each case; others might tag the 1px onto the last column.

Edit: Read a good article on this ages ago by John Resig, which is worth a read. He has a quote though from David Baron, a Mozilla Dev, which sums up the issues nicely:

  1. 4 adjacent objects of width/height 25% (for example) starting at one edge of a container should end exactly at the other edge; there should never be an extra pixel in the container and they should never be wrapped due to being a pixel to wide
  2. objects that are logically adjacent should always touch visually; there should never be a pixel gap or a pixel of overlap due to rounding error
  3. objects given the same width should occupy the same number of pixels
  4. object boundaries should always (visually) be aliased to a specific pixel boundary in the display (they should never be blurred)

There is no real standardisation in the CSS spec for how this should the above 4 requirements should be achieved, which is why browsers compromise on these in different ways.

Edit: Just to say also, as you asked how you can best avoid the issue — where possible, keep container elements to a width that is evenly divisible across its columns. (Though this isn't always possible with fluid layouts).

Upvotes: 7

Related Questions