Let's go through your two sticking points.
grid-auto-flow: column
is required to make the column wrapping work, but also forces me to add grid-template-rows: repeat(5, 1em)
to specify a row count, which breaks the responsiveness. Is there a way to calculate the row count automatically based on content and column count?
grid-auto-flow: column
does not make column wrapping work. In fact, it does the exact opposite. The rule creates new columns to accommodate additional grid items.
Here's how it works (from the spec):
7.7. Automatic Placement: the grid-auto-flow
property
Grid items that aren’t explicitly placed are automatically placed into
an unoccupied space in the grid container by the auto-placement
algorithm.
grid-auto-flow
controls how the auto-placement algorithm works,
specifying exactly how auto-placed items get flowed into the grid.
column
The auto-placement algorithm places items by filling each column in
turn, adding new columns as necessary.
row
The auto-placement algorithm places items by filling each row in turn, adding new rows as necessary. If neither row
nor column
is provided, row
is assumed.
With regard to your question:
Is there a way to calculate the row count automatically based on content and column count?
With CSS Grid alone, I don't believe so. As it says in the spec, grid-auto-flow
is designed to add new tracks in the specified direction (column
/ row
).
If it can be done with Grid, then it wouldn't be fully automatic. You would need at least some defined placement and, I would guess, media queries.
Lastly, with regard to column wrapping, that comes from the auto-fit
or auto-fill
values in the grid-template-columns
and grid-template-rows
properties.
Why are the column widths not evenly distributed and why don't they adapt to the screen size? Isn't this what minmax
is for?
This goes back to the spec section highlighted above.
This is your column-sizing code:
grid-template-columns: repeat(auto-fill, minmax(33.333%, 50%));
This translates to: The width of each explicit column must be a minimum of 33.333% and a maximum of 50%.
The problem is that the third column is not explicit. It is implicit, as it is being added to the grid by the auto-placement algorithm, under the guidance of grid-auto-flow: column
. So this column is not subject to grid-template-columns
, which deals solely with explicit track sizing.
The properties for implicit track sizing are grid-auto-columns
and grid-auto-rows
. Their default value is auto
, which is what you're seeing in your layout: The third column is the width of its content.
ol {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(33.333%, 50%));
grid-auto-flow: column;
grid-template-rows: repeat(5, 1em);
margin: 0;
padding: 0;
list-style: none;
background-color: grey;
}
li {
outline: 1px solid orange;
}
<ol>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
<li>Item 11</li>
<li>Item 12</li>
<li>Item 13</li>
<li>Item 14</li>
<li>Item 15</li>
</ol>
Once you set the value of grid-auto-columns
, the third column can be properly sized.
ol {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(33.333%, 50%));
grid-auto-flow: column;
grid-template-rows: repeat(5, 1em);
grid-auto-columns: 33.333%; /* NEW */
margin: 0;
padding: 0;
list-style: none;
background-color: grey;
}
li {
outline: 1px solid orange;
}
<ol>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
<li>Item 11</li>
<li>Item 12</li>
<li>Item 13</li>
<li>Item 14</li>
<li>Item 15</li>
</ol>
Of course, the information above is intended to be an explanation, not a solution to the main problem, as I don't believe CSS Grid provides one.