Why does flex-box work with a div but not a table?

The following simple snippet leads to the creation of a single web page that occupies the available screen space with a header at the top, the footer at the bottom, and the main content takes up as much space as possible (with a dotted border to make viewing easier):

html, body { width: 100%; height: 100%; margin: 0; padding: 0; } body { display: flex; flex-flow: column; } h1, small { flex: 0 1 auto; } div { flex: 1 1 auto; border: 1px dotted; } 
 <!doctype html> <html> <body> <h1>Some Header</h1> <div>Some Text</div> <small>Some Footer</small> </body> </html> 

If I change CSS and HTML instead of instead of table instead of div , it does not expand the table to consume available space:

 html, body { width: 100%; height: 100%; margin: 0; padding: 0; } body { display: flex; flex-flow: column; } h1, small { flex: 0 1 auto; } table { flex: 1 1 auto; border: 1px dotted; } 
 <!doctype html> <html> <body> <h1>Some Header</h1> <table><tr><td>Some Content</td></tr></table> <small>Some Footer</small> </body> </html> 

Why does the first version (with div ) work, and the second version (with table ) does not? And is there a way to fix the second example so that the table expands and consumes all available space (without entering scrollbars)?

Some notes: my table will have a number of headers (all with equal width) and several rows (all with equal width / height). I know that you can recreate the table using a bunch of div and more CSS, but going down this route, he feels that he is throwing a child with bath water (and, besides, I would not ask this question and find out if I just hacked it). Also, JavaScript is not available to me here (and it seems like it's superfluous).

I know enough CSS / HTML to get myself in trouble, but not enough to get rid of it ...

Edit: aavrug's suggestion to use display: flex for table makes the table expand properly to fill the area, but when I add a few rows / columns to the table, they are not longer than evenly distributed. I would like to keep the equidistance of the table cell.

+7
html css flexbox css3 css-tables
source share
4 answers

The html table element saves its display property in the flex container:

 display: table 

Therefore, it does not accept flexible properties.

However, just override this rule with display: block display: flex and the layout should work.

 html, body { width: 100%; height: 100%; margin: 0; padding: 0; } body { display: flex; flex-flow: column; } h1, small { flex: 0 1 auto; } table { display: flex; flex: 1 1 auto; } tbody { display: flex; width: 100%; } tr { display: flex; width: 100%; } td { flex: 1; border: 1px solid red; } 
 <h1>Some Header</h1> <table> <tr> <td>Some Content</td> <td>Some Content</td> <td>Some Content</td> <td>Some Content</td> <td>Some Content</td> </tr> </table> <small>Some Footer</small> 
+3
source share

I think the problem is that the table field is placed inside the table cover window :

the table generates a main block block called the table cover field, which contains the table table itself and any header fields

enter image description here

Thus, the table field is no longer a child of the flex container and therefore is not a flexible element. The flex element is a table wrapper field, but you set the flex property to the table element and

values โ€‹โ€‹of non-inherited properties are used in the table field, not the table wrapper window

So, your flex used in a field that is not a flexible element and therefore ignored.

Perhaps this worked if this property was used in the table wrapper window, but it cannot be selected. Even if you could, it would be unclear whether it should be installed in accordance with the table layout that it creates, and not with the Flexbox layout in which it participates.

The solution is simple:

  • Place the table in a wrapper that will be an element of flexibility.
  • Flexible element size optionally using flexible layout
  • Remove the table from the stream and give it specific lengths relative to the flexibility element.

 html, body { width: 100%; height: 100%; margin: 0; padding: 0; } body { display: flex; flex-flow: column; } h1, small { flex: 0 1 auto; } div { position: relative; flex: 1 1 0; /* Chrome needs non-auto flex-basis */ overflow: auto; } table { position: absolute; height: 100%; width: 100%; left: 0; top: 0; table-layout: fixed; border-collapse: collapse; } td { border: 1px dotted; text-align: center; } 
 <h1>Some Header</h1> <div> <table><tr> <td>This</td> <td>is</td> <td>equidistributed.</td> </tr><tr> <td>This</td> <td>is also</td> <td>equidistributed.</td> </tr></table> </div> <small>Some Footer</small> 

Just for fun, a hacker way of avoiding adding a wrapper would be to style the table as a block and automatically insert the body as a table.

 html, body { width: 100%; height: 100%; margin: 0; padding: 0; } body { display: flex; flex-flow: column; } h1, small { flex: 0 1 auto; } table { display: block; position: relative; flex: 1 1 0; } tbody { display: table; position: absolute; height: 100%; width: 100%; left: 0; top: 0; table-layout: fixed; border-collapse: collapse; box-sizing: border-box; } td { border: 1px dotted; text-align: center; } 
 <h1>Some Header</h1> <table><tr> <td>This</td> <td>is</td> <td>equidistributed.</td> </tr><tr> <td>This</td> <td>is also</td> <td>equidistributed.</td> </tr></table> <small>Some Footer</small> 
+1
source share

Well then, you should use vw and vh units in height and width, they are not supported in most browsers, but they are really good at what they can do. Also, with a table problem, you have never indicated its width, so you only get a cell that matches the text.

Adding something like "width: 75vw;" to style of the table will help (you can use% s for width)

0
source share

From where I see it, the style of the table should not go beyond shades, stripes, have decent pads, borders and line height. But if you want to have flex-table , you have to do this to the end:

 html, body { width: 100%; height: 100%; margin: 0; padding: 0; } body { display: -webkit-box; display: -webkit-flex; display: -moz-box; display: -ms-flexbox; display: flex; -webkit-flex-flow: column; -ms-flex-flow: column; flex-flow: column; } h1, small { -webkit-box-flex: 0; -webkit-flex: 0 1 auto; -moz-box-flex: 0; -ms-flex: 0 1 auto; flex: 0 1 auto; } table { -webkit-box-flex: 1; -webkit-flex: 1 0 auto; -moz-box-flex: 1; -ms-flex: 1 0 auto; flex: 1 0 auto; border: 1px dotted; display: -webkit-box; display: -webkit-flex; display: -moz-box; display: -ms-flexbox; display: flex; -webkit-box-align: stretch; -webkit-align-items: stretch; -moz-box-align: stretch; -ms-flex-align: stretch; align-items: stretch; } table tbody { display: -webkit-box; display: -webkit-flex; display: -moz-box; display: -ms-flexbox; display: flex; -webkit-flex-wrap: wrap; -ms-flex-wrap: wrap; flex-wrap: wrap; -webkit-box-flex: 1; -webkit-flex-grow: 1; -moz-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; } table tbody tr { display: -webkit-box; display: -webkit-flex; display: -moz-box; display: -ms-flexbox; display: flex; -webkit-box-align: stretch; -webkit-align-items: stretch; -moz-box-align: stretch; -ms-flex-align: stretch; align-items: stretch; -webkit-box-flex: 1; -webkit-flex: 1 0 100%; -moz-box-flex: 1; -ms-flex: 1 0 100%; flex: 1 0 100%; } table tbody tr td { -webkit-box-flex: 1; -webkit-flex-grow: 1; -moz-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; border-style: dotted; border-width: 0 1px 1px 0; padding: 3px 10px; } table tbody tr td:last-child { border-right-width: 0; } table tbody tr:last-child td { border-bottom-width: 0; } 
 <body> <h1>Some Header</h1> <table> <tr><td>This</td><td>is</td><td>equidistributed</td></tr> <tr><td>This</td><td>is</td><td>equidistributed</td></tr> <tr><td>This</td><td>is</td><td>equidistributed</td></tr> </table> <small>Some Footer</small> </body> 

Clear SCSS:

 table { flex: 1 0 auto; border: 1px dotted; display: flex; align-items: stretch; tbody { display: flex; flex-wrap: wrap; flex-grow: 1; tr { display: flex; align-items: stretch; flex: 1 0 100%; td { flex-grow: 1; border-style: dotted; border-width: 0 1px 1px 0; padding: 3px 7px; &:last-child { border-right-width: 0; } } &:last-child { td { border-bottom-width: 0;} } } } } 
0
source share

All Articles