2

In the below snippet is an example sub-menu layout. I want to evenly distribute the menu items across all three columns, but I want to arrange them vertically.

In the first instance, the items are evenly distributed, but they are arranged horizontally.

In the second instance, I tried switching grid-auto-flow to column to arrange them vertically, but this defaults to a single row no matter what auto-fill/auto-fit values I try to use for grid-template-rows.

In the third instance, I manually set the correct absolute value for grid-template-rows as a proof of concept; but in the real world the number of items (and thus the number of desired rows) will not always be known until render time.

Is there something I can do short of client-side JavaScript to achieve this layout?

.sub-menu {
  margin: 0;
  padding: 2px;
  border: 1px dashed red;
  list-style: none;
  
  /* the actual grid code */
  display: grid;
  grid-gap: 2px;
  grid-template-columns: repeat(3, 1fr);
}

.grid-auto-flow-row { grid-auto-flow: row; }
.grid-auto-flow-column { grid-auto-flow: column; }
.grid-template-rows-3 { grid-template-rows: repeat(3, 1fr); }

li {
  padding: 2px 4px;
  border: 1px dashed blue;
  display: flex;
  justify-content: center;
  align-items: center;
}
<h3>grid-auto-flow: row</h3>
<ul class="sub-menu grid-auto-flow-row">
  <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>
</ul>

<h3>grid-auto-flow: column</h3>
<ul class="sub-menu grid-auto-flow-column">
  <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>
</ul>

<h3>grid-auto-flow: column with grid-template-rows explicitly set</h3>
<ul class="sub-menu grid-auto-flow-column grid-template-rows-3">
  <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>
</ul>
focus.style
  • 6,612
  • 4
  • 26
  • 38
njbair
  • 1,982
  • 16
  • 14

1 Answers1

1

Here is a good answer why it is impossible to do it using display: grid;. So why should we? We have column-count for this task.

More about column-count and it's additional properties.

.sub-menu {
  margin: 0;
  padding: 2px;
  list-style: none;
  border-top: 1px solid;
  
  /* goodbye grid */
  column-count: 3;  
}
<ul class="sub-menu">
  <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>
</ul>

<ul class="sub-menu">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>
  <li>Item 5</li>
</ul>

<ul class="sub-menu">
  <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>
</ul>
focus.style
  • 6,612
  • 4
  • 26
  • 38
  • Thanks for this! I've know about the `columns` property for years but I never knew about all the sub-properties (`column-gap`, etc.), or thought to use it in the context of arranging block-level elements as opposed to text nodes (I know `

    ` is a block-level element but you know what I mean).

    – njbair Jul 06 '20 at 14:21