【问题标题】:Keeping all elements aligned to the same grid and spanning multiple columns保持所有元素对齐到同一个网格并跨越多列
【发布时间】:2016-04-04 19:19:28
【问题描述】:

我是第一次尝试 CSS3 的 flexbox,它看起来很有希望,但我在让它正常运行时遇到了一些麻烦。

基本上,我希望 flexbox 表现得像一个表格,但有一个 order 属性,所以我可以在 CSS 中告诉它在网格中显示元素的顺序。这甚至可以通过 flexbox 实现吗?

这是我创建的测试页面:https://jsfiddle.net/Lb838dwf/

HTML:

<div id="main">
  <div id="div1">div 1</div>
  <div id="div2">div 2</div>
  <div>generic</div>
  <div id="div3">div 3</div>
  <div>generic</div>
  <div id="div4">div 4</div>
  <div>generic</div>
  <div>generic</div>
  <div>generic</div>
  <div>generic</div>
  <div>generic</div>
</div>

CSS:

#main {
    width: 100%;
    border: 1px solid #c3c3c3;
    display: -webkit-flex;
    display: flex;
    -webkit-flex-wrap: wrap;
    flex-wrap: wrap;
}

#main div {
    min-width: 25%;
    height: 100px;
    -webkit-flex: 1;
    flex: 1;
    -webkit-order: 2;
    order: 1;
    background-color: #ccc;
}

#main #div1 {
    -webkit-order: 3;
    order: 3;
    background-color: coral;
}
#main #div2 {
    -webkit-order: 5;
    order: 5;
    background-color: lightblue;
}
#main #div3 {
    -webkit-flex: 2;
    flex: 2;
    -webkit-order: 2;
    order: 2;
    background-color: lightgreen;
}
#main #div4 {
    -webkit-order: 4;
    order: 4;
    background-color: pink;
}

您可以看到#div3 有flex: 2,这意味着它应该跨越两列,但它只占用一列。此外,底部的 3 个 div(div1、div4、div2)未与其上方的项目对齐到相同的网格。如果我将max-width: 25% 添加到#main div 样式中,它会将所有内容保持在同一个网格中,但跨列不起作用。我尝试为所有 div 设置 max-width: 25% 并为 #div3(带有 flex:2 的那个)设置 max-width: none 但这没有影响。

【问题讨论】:

    标签: html css flexbox


    【解决方案1】:

    让我们剖析一下你写的一些东西,以便我们澄清 flexbox 的行为。


    您可以看到#div3flex: 2,这意味着它应该跨越两个 列,但它只占用 1 列。

    flex: 2 并不意味着它应该跨越两列。这不像 HTML colspan 属性。 (即使是这样,您还有其他三个弹性项目 [“表格单元格”] 已经占据了剩余的三个列,那么 #div3 将如何扩展两列?它必须打破网格。)

    flex propertyflex-growflex-shrinkflex-basis 属性的简写。

    flex-grow 属性通过 分配 flex 容器中的剩余空间来控制 flex 项如何展开。因此,通过应用flex: 2,您是说您希望弹性项目占用的剩余空间是其兄弟项目的两倍,而不一定是其大小的两倍。

    来自specflex-grow 属性:

    ...确定弹性项目相对于其余项目将增长多少 当可用空间为正时,flex 容器中的 flex 项目 分布式。

    但是,由于您已为容器 (#main) 分配了 width: 100%,并且每个弹性项目 min-width: 25%没有剩余空间可分配。所以什么都没有发生。

    为了说明这种行为,将每个弹性项目的宽度更改为 50 像素。这为分发留下了额外的空间,#div3 占用了 2 倍的空间。见演示:https://jsfiddle.net/Lb838dwf/6/


    另外,底部的 3 个 div (div1,div4,div2) 没有对齐 与上面的项目相同的网格。

    正确。它们没有对齐,因为您在 #main div 中将 flex: 1 应用于它们。这告诉他们在他们之间平均分配所有剩余空间。


    如果我将 max-width: 25% 添加到 #main div 样式中,它会保持 一切都到同一个网格,但跨列不起作用。我 尝试为所有 div 设置 max-width: 25% 并为所有 div 设置 max-width: none 只是 #div3(带有 flex:2 的那个),但这没有影响。

    什么?你失去了我。


    我希望 flexbox 表现得像一个表格,但有一个 order 属性,所以我 可以在 CSS 中告诉它在网格中显示元素的顺序。 这甚至可以通过 flexbox 实现吗?

    是的,这是可能的。

    HTML

    <div id="main">
        <div>div 1</div>
        <div>div 2</div>
        <div>div 3</div>
        <div>div 4</div>
        <div>div 5</div>
        <div>div 6</div>
        <div>div 7</div>
        <div>div 8</div>
        <div>div 9</div>
        <div>div 10</div>
        <div>div 11</div>
    </div>
    

    CSS

    #main {
        display: flex;
        justify-content: flex-start;
        flex-wrap: wrap;
        width: 100%;
    }
    
    #main div {
        flex: 0 0 150px; /* don't grow, don't shrink, stay at 150px */
        height: 100px;
        margin: 5px;
        background-color: #ccc;
        border: 1px dashed black;
    }
    
    #main div:nth-child(2)  { order: -4; background-color: lightblue; }
    #main div:nth-child(5)  { order: -3; background-color: lightgreen; }
    #main div:nth-child(8)  { order: -2; background-color: lightyellow; }
    #main div:nth-child(11) { order: -1; background-color: lightpink; }
    

    演示:http://jsfiddle.net/Lb838dwf/4/


    跨越多列

    如上所述,flex 属性是flex-growflex-shrinkflex-basis 属性的简写。

    flex-grow 告诉弹性项目如何分配可用空间,因此它不是模拟 HTML colspan 属性的可靠工具。 (容器中的可用空间和弹性项目的两倍大小是不相关的长度,不一定相等。)

    但是,flex-basis 属性设置了弹性项目的初始大小,可用于将弹性项目设置为两倍宽、三倍宽等等。

    在我上面的代码中,弹性项目设置为:flex: 0 0 150px; 第三个值代表flex-basis。所以每个框都设置为 150px 宽。

    对于占据两列的弹性项目,只需将该值加倍即可。

    由于flex 级联到所有div,我们只需要针对目标项目调整flex-basis

    #main div:nth-child(11) { flex-basis: calc(300px + 10px); } /* factoring in margin space */
    #main div:nth-child(7)  { flex-basis: calc(450px + 20px); } /* factoring in margin space */
    

    DEMO:http://jsfiddle.net/Lb838dwf/5/(展开效果窗口)

    【讨论】:

    • order:999 并没有使订购商品变得更容易,实际上您只是引入了难以理解的模棱两可的大数字(为什么 998 在列表顶部?)。 order 可以有负值,所以默认的0 是一个不错的选择。如果您需要向上移动,请使用-1,如果您需要向下移动,请使用1。此外,与z-index 类似,在一致的位置(预处理器 FTW)使用变量特别有用,这样就可以描述元素的整体顺序,而无需找到单独的选择器。
    • @zzzzBov,通过在order 属性上设置一个高值,您实际上消除了使用负数的需要,并且排序可以从1 开始。但是有一些可能的缺点。你提到了一些。另一个是需要将order 属性应用于弹性项目,否则在订购一组项目时不需要它。我并不是很想重新设置order 默认值。放下它我没有问题。感谢您的反馈。答案已修改。
    • 哇,感谢您如此详细的回复。这清楚了很多,但我仍然不确定跨越“列”。假设我希望粉红色元素占据两列,这意味着黄色元素将与现在的大小相同,但在其自己的行上,其下方行上的粉红色元素跨越两列。这可能吗,或者这不是 flexbox 的工作原理?
    • 嗨,Gavin,我更新了我的答案以解决跨栏问题。如果您仍有疑问,请告诉我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-11
    • 1970-01-01
    • 2021-05-05
    • 2019-10-27
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多