12

In working on a layout, I decided to try combining a float-based layout for the major columns with a table-based layout for the sub-elements. Thus, my html/css markup was along these lines:

HTML:

<div class="column">
    <div class="sub-element"></div>
    <div class="sub-element"></div>
</div>
<div class="column">
    <div class="sub-element"></div>
    <div class="sub-element"></div>
</div>
...

CSS:

.column {
    float: left;
    display: table;
    width: 15%;
    margin: 2%;
    /*  ...  */
}
.sub-element {
    display: table-cell;
    /*  ...  */
}

The specific widths and margins aren't critical. See this jsFiddle for a reference example.

What I saw happening was that each column block, going left to right across the page, had slightly smaller margins than the last. Since no additional markup or CSS was present to make this happen, I was confused. After playing around with different values, I discovered that commenting out display: table caused the normal behavior I was expecting, e.g. constant column widths.

Now, I can use alternative methods to get the layout I want, that's not a problem; but I am really curious why this is happening. Any thoughts?

EDIT

It looks like this is a webkit bug. display: table with float and margins works fine in Firefox. Any suggestions on a fix for webkit for posterity?

Further EDIT

I just tested in Safari and it seems to work there as well. WTF Chrome??

Final EDIT

After testing in Firefox 18, Safari, and Chrome Canary (in addition to standard Chrome), it appears that this is in fact a Chrome-specific bug.

The easiest fix is to add a simple additional wrapper div inside each of the ones being floated to contain the content and set the wrappers' CSS to width: 100%; height:100%; display: table;, then remove the display: table from the outer elements being floated. Works like a charm.

http://jsfiddle.net/XMXuc/8/

HTML:

<div class="column">
    <div class="sub-element-wrapper">
        <div class="sub-element"></div>
        <div class="sub-element"></div>
    </div>
</div>
<div class="column">
    <div class="sub-element-wrapper">
        <div class="sub-element"></div>
        <div class="sub-element"></div>
    </div>
</div>
...

CSS:

.column {
    float: left;
    width: 15%;
    margin: 2%;
    /*  ...  */
}
.sub-element-wrapper {
    width: 100%;
    height: 100%;
    display: table;
}
.sub-element {
    display: table-cell;
    /*  ...  */
}
Ken Bellows
  • 6,711
  • 13
  • 50
  • 78
  • This is not supposed to happen. Looks like another WebKit bug if you ask me. – BoltClock Feb 18 '13 at 18:29
  • Yep, looks like WebKit - works as expected in FireFox. – Joe Feb 18 '13 at 18:34
  • Huh, I think you're right. I just tried it out in FF 18 and it works fine, normal spacing with `display: table`. is there a way to verify this? – Ken Bellows Feb 18 '13 at 18:37
  • Actually, it works fine in Safari too. So it isn't Webkit. Just Chrome, maybe? – Ken Bellows Feb 18 '13 at 18:48
  • 1
    lol at your further edit - I can't find anything in the [Chromium issue tracker](https://code.google.com/p/chromium/issues/list) for this particular behavior, but Chrome is a buggy browser, 'nuff said. – BoltClock Feb 18 '13 at 18:48
  • 1
    opened issue https://code.google.com/p/chromium/issues/detail?id=363954 – HEX Apr 16 '14 at 08:34
  • 1
    fixed in beta 35.0.1916.114 and canary 37.0.1992.1 – HEX May 18 '14 at 11:30

1 Answers1

8

This should not happen. Horizontal margins on block-level tables should be calculated in the same way as with any other block-level non-replaced elements, as described in section 10.3.3 of the CSS2.1 spec, regardless of which table layout algorithm is used. In particular, percentages values for margins should be calculated based on the width of the containing block of the element that you're displaying as a table; since all your elements are siblings that share the same parent and the same margin percentage value, they should be equidistant as long as they are floating block boxes.

In all browsers except Google Chrome, the elements are equidistant, as expected. So my best guess is that this is another Chrome bug.

If you comment out the display: table declaration — which as you say causes the behavior to return to normal — browsers will still generate anonymous block table boxes within your floats to contain the table cells. This should not adversely affect the layout, but if it does, I can't comment further as I'm not intimately familiar with how table layout works in terms of CSS.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • As a quick comment, using `display: table-cell` on child elements does not seem to generate the table structure above it. For one, alignment works properly. For another, using normal table-cell properties, such as `vertical-algin: middle`, does not work with just `display: table-cell`, but *does* work when `display: table` is added to the parent (though alignment goes haywire again). – Ken Bellows Feb 18 '13 at 19:11
  • @KenB: Hmm, what if you use `display: table-row` instead? I'm not intimately familiar with the internals of CSS table layout so at this point I'm just tossing out ideas. – BoltClock Feb 18 '13 at 19:13