I have a table with two columns. One of the columns has more content than the other. I would like to replicate the behaviour of an old fashioned table, where free space is allocated roughly in proportion to the amount of content in a cell, except using grid instead of table. I would prefer to use grid so that I can make the cells stack vertically on a narrow screen.
Using “grid-template-columns: auto auto” is close, but remaining space is split evenly, and I want remaining space to be split at a 2:1 (or other) ratio. “2fr 1fr” isn’t right, and there’s no such thing as “2auto 1auto”.
I can’t find any combination of CSS Grid styles that replicate the spacing of a classic table. But just using a table that overrides the “display” property at a certain screen size seems inelegant. Is there a way to do this using only CSS Grid?
Here’s what I’ve tried so far: https://jsfiddle.net/mnegdk0o/
<p>
My starter grid without using any extra space:
</p>
<div class="grid grid0">
<div>
This cell has more, more, more, more, more, more, more content
</div>
<div>
Less content here
</div>
</div>
<p>
For reference, here is a classic table. Note how by default, the first column gets more free space due to having more content.
</p>
<table cellspacing="5" cellpadding="5" width="100%">
<tr>
<td>
This cell has more, more, more, more, more, more, more content
</td>
<td>
Less content here
</td>
</tr>
</table>
<p>
Attempt 1: Try using "grid-template-columns: auto auto;".
</p>
<div class="grid grid1">
<div>
This cell has more, more, more, more, more, more, more content
</div>
<div>
Less content here
</div>
</div>
<p>
Attempt 2: Try using "grid-template-columns: 2fr 1fr;".
</p>
<div class="grid grid3">
<div>
This cell has more, more, more, more, more, more, more content
</div>
<div>
Less content here
</div>
</div>
<p>
Attempt 3: Try using "grid-template-columns: minmax(auto, 2fr) minmax(auto, 1fr);".
</p>
<div class="grid grid3">
<div>
This cell has more, more, more, more, more, more, more content
</div>
<div>
Less content here
</div>
</div>
<p>
Attempt 4: Just use classic table, and change "display" below a certain breakpoint.
</p>
<table class="hacky" cellspacing="5" cellpadding="5" width="100%">
<tr>
<td>
This cell has more, more, more, more, more, more, more content
</td>
<td>
Less content here
</td>
</tr>
</table>
table {
border: 1px solid red;
}
td {
border: 1px solid red;
}
.grid {
display: grid;
gap: 5px;
border: 1px solid blue;
padding: 5px;
margin-bottom: 5px;
}
.grid>* {
border: 1px solid blue;
padding: 5px;
grid-template-columns: 100%;
}
.grid0 {
grid-template-columns: fit-content(100%) fit-content(100%);
}
.grid1 {
grid-template-columns: auto auto;
}
.grid2 {
grid-template-columns: 2fr 1fr;
}
.grid3 {
grid-template-columns: minmax(auto, 2fr) minmax(auto, 1fr);
}
@media (max-width: 400px) {
table.hacky,
table.hacky tr,
table.hacky tr td {
display: block;
}
}