How is a CSS "display: table-column" supposed to work?
Asked Answered
O

2

93

Given the following HTML and CSS, I see absolutely nothing in my browser (Chrome and IE latest at time of writing). Everything collapses down to 0x0 px. Why?

<!DOCTYPE html>
<html>
<head>
    <style type="text/css">
        section { display: table; height: 100%; background-color: grey; }

        #colLeft { display: table-column; height: 100%; background-color: green; }
        #colRight { display: table-column; height: 100%; background-color: red; }

        #row1 { display: table-row; height: 100%; }
        #row2 { display: table-row; height: 100%; }
        #row3 { display: table-row; height: 100%; }

        #cell1 { display: table-cell; height: 100%; }
        #cell2 { display: table-cell; height: 100%; }
        #cell3 { display: table-cell; height: 100%; }
    </style>
</head>
<body>
    <section>
        <div id="colLeft">
            <div id="row1">
                <div id="cell1">
                    AAA
                </div>
            </div>
            <div id="row2">
                <div id="cell2">
                    BBB
                </div>
            </div>
        </div>
        <div id="colRight">
            <div id="row3">
                <div id="cell3">
                    CCC
                </div>
            </div>
        </div>
    </section>
</body>
</html>
Oversexed answered 1/10, 2011 at 0:53 Comment(0)
S
125

The CSS table model is based on the HTML table model http://www.w3.org/TR/CSS21/tables.html

A table is divided into ROWS, and each row contains one or more cells. Cells are children of ROWS, they are NEVER children of columns.

"display: table-column" does NOT provide a mechanism for making columnar layouts (e.g. newspaper pages with multiple columns, where content can flow from one column to the next).

Rather, "table-column" ONLY sets attributes that apply to corresponding cells within the rows of a table. E.g. "The background color of the first cell in each row is green" can be described.

The table itself is always structured the same way it is in HTML.

In HTML (observe that "td"s are inside "tr"s, NOT inside "col"s):

<table ..>
  <col .. />
  <col .. />
  <tr ..>
    <td ..></td>
    <td ..></td>
  </tr>
  <tr ..>
    <td ..></td>
    <td ..></td>
  </tr>
</table>

Corresponding HTML using CSS table properties (Note that the "column" divs do not contain any contents -- the standard does not allow for contents directly in columns):

.mytable {
  display: table;
}
.myrow {
  display: table-row;
}
.mycell {
  display: table-cell;
}
.column1 {
  display: table-column;
  background-color: green;
}
.column2 {
  display: table-column;
}
<div class="mytable">
  <div class="column1"></div>
  <div class="column2"></div>
  <div class="myrow">
    <div class="mycell">contents of first cell in row 1</div>
    <div class="mycell">contents of second cell in row 1</div>
  </div>
  <div class="myrow">
    <div class="mycell">contents of first cell in row 2</div>
    <div class="mycell">contents of second cell in row 2</div>
  </div>
</div>


OPTIONAL: both "rows" and "columns" can be styled by assigning multiple classes to each row and cell as follows. This approach gives maximum flexibility in specifying various sets of cells, or individual cells, to be styled:

//Useful css declarations, depending on what you want to affect, include:

/* all cells (that have "class=mycell") */
.mycell {
}

/* class row1, wherever it is used */
.row1 {
}

/* all the cells of row1 (if you've put "class=mycell" on each cell) */
.row1 .mycell {
}

/* cell1 of row1 */
.row1 .cell1 {
}

/* cell1 of all rows */
.cell1 {
}

/* row1 inside class mytable (so can have different tables with different styles) */
.mytable .row1 {
}

/* all the cells of row1 of a mytable */
.mytable .row1 .mycell {
}

/* cell1 of row1 of a mytable */
.mytable .row1 .cell1 {
}

/* cell1 of all rows of a mytable */
.mytable .cell1 {
}
<div class="mytable">
  <div class="column1"></div>
  <div class="column2"></div>
  <div class="myrow row1">
    <div class="mycell cell1">contents of first cell in row 1</div>
    <div class="mycell cell2">contents of second cell in row 1</div>
  </div>
  <div class="myrow row2">
    <div class="mycell cell1">contents of first cell in row 2</div>
    <div class="mycell cell2">contents of second cell in row 2</div>
  </div>
</div>

In today's flexible designs, which use <div> for multiple purposes, it is wise to put some class on each div, to help refer to it. Here, what used to be <tr> in HTML became class myrow, and <td> became class mycell. This convention is what makes the above CSS selectors useful.

PERFORMANCE NOTE: putting class names on each cell, and using the above multi-class selectors, is better performance than using selectors ending with *, such as .row1 * or even .row1 > *. The reason is that selectors are matched last first, so when matching elements are being sought, .row1 * first does *, which matches all elements, and then checks all the ancestors of each element, to find if any ancestor has class row1. This might be slow in a complex document on a slow device. .row1 > * is better, because only the immediate parent is examined. But it is much better still to immediately eliminate most elements, via .row1 .cell1. (.row1 > .cell1 is an even tighter spec, but it is the first step of the search that makes the biggest difference, so it usually isn't worth the clutter, and the extra thought process as to whether it will always be a direct child, of adding the child selector >.)

The key point to take away re performance is that the last item in a selector should be as specific as possible, and should never be *.

Summation answered 21/12, 2012 at 2:27 Comment(4)
I haven't tried this myself, but I have seen recommendations for tanalin.com/en/projects/display-table-htc which is a javascript solution for IE6 and IE7. When the javascript runs, it converts the page into the older HTML table tags.Summation
Solution works on IE8+, Firefox, Chrome, iPad, Android. It is a good way to avoid table layouts if you need flexible structure of a table and you are supporting more modern browsers listed above.Elemental
the <col style="color: red;" > isn't work , but the <col style="background-color: red;" > is ok! what's wrong with this ?Proleg
@xgqfrms: Some other css rule must be overriding the color. Probably a rule applied to an element inside your cells. For example, if your text is inside <p>, then somewhere you have a more specific rule setting <p> color. Try <col style="color: red !important;">. If this works, then that is the problem. However, don't get in the habit of overusing !important. After seeing that work, best to remove it, and figure out a more specific selector to take precedence. google "css more specific selector", or see smashingmagazine.com/2007/07/…Summation
U
24

The "table-column" display type means it acts like the <col> tag in HTML - i.e. an invisible element whose width* governs the width of the corresponding physical column of the enclosing table.

See the W3C standard for more information about the CSS table model.

* And a few other properties like borders, backgrounds.

Umpteen answered 1/10, 2011 at 0:57 Comment(3)
If the col element has a logical structure, which it does, then how does one justify using the CSS rule display: table-column;, which only has presentational structure? According to the specs on display (w3.org/wiki/CSS/Properties/display), it's supposed to "behave" like a col element. But I can't see how that's useful...Contrecoup
@TestSubject528491 Because then you can set the column background, column width, etc, of a [presentational] table. But really it's mostly useful in terms of specifying the default style rule for the <col> tag itself, or an equivalent tag in a different XML-based markup language.Umpteen
@chharvey: HTML's col is a logical element that contains only presentational styling. You can't put a column of info in it - this is a common misunderstanding. Table data is always in rows. display: table-column; converts a logical element (typically a div) into a col. It causes other style fields assigned to that element to apply to the presentation concept "a column". The result is a logical element that is not displayed and whose contents, if any, are ignored; its only effect is to apply style to "columns" of the associated presentation. See my answer for a template.Summation

© 2022 - 2024 — McMap. All rights reserved.