【问题标题】:CSS "grid" layout with modern CSS (no JS)带有现代 CSS 的 CSS“网格”布局(无 JS)
【发布时间】:2016-01-28 00:54:08
【问题描述】:

通缉

我想要一个网格布局。 有点像 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”项目的右侧(而不是在下方)。

我的尝试

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

这是我上面 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 布局?或者告诉我解决这个布局问题的最好、最优雅和现代的方法是什么?

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

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


解决方案

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

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

【问题讨论】:

  • 关于垂直空间,我觉得很好。
  • 你有没有研究过新的 bootstrap 4,它是一个测试版,但它可能有用
  • @Ionut 问题不在于它看起来好不好,而在于如何控制它。例如,如果我想将行垂直间隔仅为 1px,我不知道该怎么做!
  • 谢谢@jsg 我会去寻找灵感也许那里会有一个优雅而现代的解决方案

标签: html css layout flexbox


【解决方案1】:

我已经使用 flexbox 完成了这个布局,但感觉很hacky,因为我必须用数学计算一些边距。

是的,我认为您使用了不必要的代码,并且没有利用几个 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/

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

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

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

【讨论】:

  • 非常感谢@Michael_B。这不是我想要的,但给了我这样做的灵感:jsfiddle.net/mk8uksb2/2
  • 碰巧你知道如何对非固定高度的物品做同样的事情吗?
  • 你也知道如何让我的盒子保持相同的宽高比吗?我已经尝试过了,但它并不完全有效......jsfiddle.net/mk8uksb2/7
  • re: 相同的宽度/高度比:对于您的特定代码,我会说为 flex-basis 选择 one 值,并在所有媒体查询中使用它:@987654325 @
  • 谢谢,我已经可以得到我的最终结果了 :) jsfiddle.net/mk8uksb2/21
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-09
  • 2022-07-29
  • 1970-01-01
  • 2020-09-21
  • 1970-01-01
  • 2019-08-01
  • 1970-01-01
相关资源
最近更新 更多