I would like my table to fulfill these properties:
- The width of the table is 100% of the parent container.
- All columns width are fit to the maximum column width.
- The column
flex-column
takes the remaining space.
In the figure, the middle column takes, the remaining horizontal space while the other columns width are fitted to their content.
I played with Flexbox and CSS Grid, but I couldn’t get any result yet. What is the proper method?
table {
width: 100%;
table-layout: fixed;
border-collapse: collapse;
}
th,
td {
padding: 8px;
border: 1px solid black;
}
th.flex-column,
td.flex-column {
width: auto;
}
th:not(.flex-column),
td:not(.flex-column) {
white-space: nowrap;
}
<table>
<thead>
<tr>
<th>A</th>
<th class="flex-column">B</th>
<th>C</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="3">foo</td>
<td class="flex-column">2</td>
<td>3</td>
</tr>
<tr>
<td class="flex-column">4</td>
<td>5</td>
</tr>
<tr>
<td class="flex-column">6</td>
<td>7</td>
</tr>
</tbody>
</table>
9
Making the flex column width 100% will work.
This snippet wraps the table in a div to demonstrate that the table can pick up the width of the parent.
.container {
width: 50vw;
}
table {
table-layout: fixed;
border-collapse: collapse;
}
th,
td {
padding: 8px;
border: 1px solid black;
width: auto;
}
th.flex-column,
td.flex-column {
width: 100%;
}
th:not(.flex-column),
td:not(.flex-column) {
white-space: nowrap;
}
</div>
<div class="container">
<table>
<thead>
<tr>
<th>A</th>
<th class="flex-column">B</th>
<th>C</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="3">foo</td>
<td class="flex-column">2</td>
<td>3</td>
</tr>
<tr>
<td class="flex-column">4</td>
<td>5</td>
</tr>
<tr>
<td class="flex-column">6</td>
<td>7</td>
</tr>
</tbody>
</table>
Remove the table-layout: fixed
, use a very small fixed value for the side colums, and possibly also use white-space: nowrap;
on them if you want their content not to be wrapped. The width will not remain at that fixed value, but adapt if needed.
table {
width: 100%;
border-collapse: collapse;
}
th,
td {
padding: 8px;
border: 1px solid black;
}
th.flex-column,
td.flex-column {
text-align: left;
}
th:not(.flex-column),
td:not(.flex-column) {
white-space: nowrap;
width: 6px;
}
<table>
<thead>
<tr>
<th>A</th>
<th class="flex-column">B</th>
<th>C</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="3">foo</td>
<td class="flex-column">2</td>
<td>3</td>
</tr>
<tr>
<td class="flex-column">4</td>
<td>5</td>
</tr>
<tr>
<td class="flex-column">6</td>
<td>7</td>
</tr>
</tbody>
</table>
2
body {
width: 100vw;
margin: 0;
padding: 0;
}
table {
width: 100%;
border-collapse: collapse;
}
th,
td {
padding: 8px;
border: 1px solid black;
width: auto;
align-self: flex-start;
text-align: start;
}
th.flex-column,
td.flex-column {
width: 100%;
}
th:not(.flex-column),
td:not(.flex-column) {
white-space: nowrap;
}
<table>
<thead>
<tr>
<th>A</th>
<th class="flex-column">B</th>
<th>C</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="3">foo</td>
<td class="flex-column">2</td>
<td>3</td>
</tr>
<tr>
<td class="flex-column">4</td>
<td>5</td>
</tr>
<tr>
<td class="flex-column">6</td>
<td>7</td>
</tr>
</tbody>
</table>
You mentioned grid so here is an example of that.
I added a wrapper just for convenience in the CSS but it could be a class on the table as well. Note how I used the grid rows on the foo
and put it at the top of the block also.
body {
width: 100vw;
margin: 0;
padding: 0;
font-size: 16px;
}
.wrapper {
width: 100vw;
}
/* make these rows all apear to be direct children of table element */
.wrapper thead,
.wrapper thead>tr,
.wrapper tbody,
.wrapper tbody>tr,
.wrapper tfoot,
.wrapper tfoot>tr {
display: contents;
}
table {
border: solid #d000d0 1px;
border-collapse: collapse;
display: grid;
grid-template-columns: auto 1fr auto;
justify-content: start;
text-align: left;
}
.rowspan3 {
grid-row: 2 / 5;
}
.wrapper th,
.wrapper td {
padding: 0.5em;
border: 1px solid black;
width: minmax( min-content, 1fr);
}
.wrapper .flex-column,
.wrapper .flex-column {
grid-column: 2;
}
.wrapper th:not(.flex-column),
.wrapper td:not(.flex-column) {
white-space: nowrap;
}
<div class="wrapper">
<table>
<thead>
<tr>
<th>A</th>
<th class="flex-column">B</th>
<th>C</th>
</tr>
</thead>
<tbody>
<tr>
<td class="rowspan3">foo</td>
<td class="flex-column">2</td>
<td>3</td>
</tr>
<tr>
<td class="flex-column">4</td>
<td>5</td>
</tr>
<tr>
<td class="flex-column">6</td>
<td>7</td>
</tr>
</tbody>
</table>
</div>
1