CSS "grid" 现代布局 CSS(无 JS)

CSS "grid" layout with modern CSS (no JS)

想要

我想要网格布局。 有点像 Pinterest,除了项目有固定的高度(所以它应该容易得多)。

它应该是响应式的。列数应根据视口大小设置。

DOM 应该是容器内子项的简单列表。我不希望每一行都有一个包装器元素。我想要的是:

<div class="container">
    <div class="item">a</div>
    <div class="item">b</div>
    <div class="item">c</div>
    <div class="item">d</div>
    <div class="item">e</div>
    <div class="item">f</div>
    <div class="item">g</div>
    <div class="item">h</div>
    <div class="item">i</div>
</div>

项目的顺序很重要,所以 DOM 的 "b" 项目应该在 "a" 项目的右边(而不是在下面)。

我的尝试

我已经 this layout 使用 flexbox,但感觉很笨拙,因为我必须用数学计算一些边距。另外我不明白如何控制我的 flexbox 行之间的垂直 space,因为它似乎随着容器高度的增长而增长。

这是我上面 Codepen 的 LESS mixin:

.flexboxGridMixin(@columnNumber,@spacingPercent) {
  @contentPercent: 100% - @spacingPercent;
  @sideMargin: @spacingPercent/(@columnNumber*2);
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  > * {
    box-sizing: border-box;
    width: (100% - @spacingPercent)/@columnNumber;
    margin-left: @sideMargin;
    margin-right: @sideMargin;
  }
}

这样的数学运算似乎以某种方式违背了 flexbox 的最初目的,不是吗?

预期答案

那么,有人可以解释一下如何修复我的 flexbox 布局吗?或者告诉我解决此布局问题的最佳、最优雅和现代的方法是什么?

我不想使用浮点数,可能不是内联块,也不是基于 JS 的解决方案,如 Packery/Masonry

请在你的答案中使用现代 CSS,因为我已经知道如何用普通的旧 CSS / JS 解决这个问题。我只针对现代浏览器(待定义)


解决方案

这是我的final result,供有兴趣的人重复使用此布局。

这里还有一个非常不错的可视化 Flexbox 教程:https://scotch.io/tutorials/a-visual-guide-to-css3-flexbox-properties

I have done this layout using flexbox but it feels quite hacky as I have to compute some margins with maths.

是的,我认为您使用的代码过多,而且没有利用一些 flexbox 功能。使用 flex 属性可以简单高效地实现您想要的布局。

HTML(删除了 codepen 中不必要的外部容器)

<ul>
    <li>a</li>
    <li>b</li>
    <li>c</li>
    <li>d</li>
    <li>e</li>
    <li>f</li>
    <li>g</li>
    <li>h</li>
    <li>i</li>
    <li>j</li>
    <li>k</li>
</ul>

CSS(我为不使用预处理器的人编译了你的CSS)

html, body { height: 100%; }

ul {
    display: flex;
    flex-wrap: wrap;
    height: 100%;
    list-style: none;
    padding: 0;
    align-content: flex-start; /* solves vertical margin problem (see note below) */
}

li {
    flex: 0 1 200px; /* don't grow, shrink proportionally, start at 200px width */
    background: pink;
    height: 100px;
    line-height: 100px; /* for demo only: center text vertically */
    text-align: center; /* for demo only: center text horizontally */
    box-sizing: border-box;
    margin: 15px;
}

演示:http://jsfiddle.net/mk8uksb2/

注意:在原始代码中,行之间的 space 相对于视口高度收缩或扩展,因为在创建 flexbox 时,默认规则是 align-content: stretch。这意味着布局将扩展以填充容器的大小。在修改后的代码中,我用 align-content: flex-start 覆盖默认值,它在容器的开头打包行。

您试图满足您的网格的多项要求。我认为修改后的代码涵盖了所有内容:

  • 我想要网格布局。
  • ...项目具有固定高度。
  • 应该是响应式的。
  • 列数应根据视口大小设置。
  • DOM 应该是一个简单的容器内子项列表。
  • 我不希望每行都有一个包装器元素。
  • 项目的顺序很重要,因此 DOM 的 "b" 项目应该在 "a" 项目的右侧。