Create a CSS Grid that flows by column, with dynamic columns and rows based on content

眉间皱痕 提交于 2020-06-14 08:51:54

问题


I have a dynamic number of elements (all of equal dimensions). I want to position them in a grid, such that they are ordered in columns, with a dynamic number of columns based on the available container width, and with a dynamic number of rows based on the number of elements.

For example, assuming there are 9 elements:

1 4 7
2 5 8
3 6 9

But if the container width expands:

1 3 5 7 9
2 4 6 8

Or shrinks:

1 6
2 7
3 8
4 9
5

This works fine when the items are positioned by row, but not by column. Also, if I explicitly set the number of rows, it works fine, but if I use auto-fill for both rows and columns, it just displays everything in a single row.

Here's a simple example I would expect to be rendered as a 3x3 grid: https://codepen.io/anon/pen/ZxPQNd

#grid {
  width: 320px;
  border: 1px solid red;
  display: grid;
  grid-gap: 10px;
  grid-auto-flow: column;
  grid-template-rows: repeat(auto-fill, 100px);
  grid-template-columns: repeat(auto-fill, 100px);
  grid-auto-columns: 100px;
  grid-auto-rows: 100px;
}

#grid>div {
  background: lime;
}
<div id="grid">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
</div>

回答1:


Your desired layout is achievable using CSS multi-column layout using column-width property. Demo:

#grid {
  border: 1px solid red;
  column-width: 100px;
  column-gap: 10px;
}

#grid > div {
  break-inside: avoid-column; /* Prevent element from breaking */
  page-break-inside: avoid; /* Prevent element from breaking in Firefox */
  background: lime;
  width: 100px;
  height: 100px;
  margin-bottom: 10px;
}
<div id="grid">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
</div>



回答2:


This works fine when the items are positioned by row, but not by column.

This is because block elements consume the full width of their parent, by default.

But this behavior does not extend to height. Most elements are, by default, the height of their content (i.e., no extra space).

Essentially, your container is set to width: 100% and height: auto. For the row behavior in the vertical axis add height: 100vh.

More info: How to make a div 100% height of the browser window?

#grid {
  width: 320px;
  border: 1px solid red;
  display: grid;
  grid-gap: 10px;
  grid-auto-flow: column;
  grid-template-rows: repeat(auto-fill, 100px);
  grid-template-columns: repeat(auto-fill, 100px);
  grid-auto-columns: 100px;
  grid-auto-rows:  100px;
  height: 100vh; /* NEW */
}

#grid > div {
  background: lime;
}
<div id="grid">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
</div>

In terms of the re-ordering of grid items based on screen size, with grid-auto-flow: row the items will respond to container width. With grid-auto-flow: column, the items will respond to container height. To make the column-flowing items respond to width re-sizing will require some trickery.

More info: Make grid items fill columns not rows



来源:https://stackoverflow.com/questions/49764092/create-a-css-grid-that-flows-by-column-with-dynamic-columns-and-rows-based-on-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!