带有Flexbox的CSS正方形网格


75

我正在尝试创建一个自适应的正方形网格。正方形应调整大小以适合视口的宽度。更改视口高度时,正方形不应调整大小。

我了解了如何调整每个正方形的宽度,但是当视口宽度发生变化时,我不知道如何使元素变为正方形以及如何缩放其高度。

在小提琴下面的示例中,七个正方形应始终水平放置,并且应按正方形缩放。我不在乎有多少行可见。

在这里提琴http://jsfiddle.net/gonyhvz8/11/

<body>
<div class="flex-container">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
    <div class="flex-item">4</div>
    <div class="flex-item">5</div>
    <div class="flex-item">6</div>
    <div class="flex-item">7</div>
</div>
<div class="flex-container">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
    <div class="flex-item">4</div>
    <div class="flex-item">5</div>
    <div class="flex-item">6</div>
    <div class="flex-item">7</div>
</div>
<div class="flex-container">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
    <div class="flex-item">4</div>
    <div class="flex-item">5</div>
    <div class="flex-item">6</div>
    <div class="flex-item">7</div>
</div>
<div class="flex-container">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
    <div class="flex-item">4</div>
    <div class="flex-item">5</div>
    <div class="flex-item">6</div>
    <div class="flex-item">7</div>
</div>
<div class="flex-container">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
    <div class="flex-item">4</div>
    <div class="flex-item">5</div>
    <div class="flex-item">6</div>
    <div class="flex-item">7</div>
</div>
<div class="flex-container">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
    <div class="flex-item">4</div>
    <div class="flex-item">5</div>
    <div class="flex-item">6</div>
    <div class="flex-item">7</div>
</div>
<div class="flex-container">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
    <div class="flex-item">4</div>
    <div class="flex-item">5</div>
    <div class="flex-item">6</div>
    <div class="flex-item">7</div>
</div>

.flex-container {
  padding: 0;
  margin: 0;
  list-style: none;
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  -webkit-flex-flow: row;
  justify-content: space-around;
  height: 50px;
  line-height:30px;
}

.flex-item {
  background: tomato;
  margin: 5px;
  color: white;
  font-weight: bold;
  font-size: 1.5em;
  text-align: center;
  flex: 1 0 0px;
  height: auto;
}

它没有使用flexbox,但这似乎满足了您的其他要求: stackoverflow.com/a/20457076/717383
James Montagne

Answers:


103

您不应设置任何大小。您可以使用多余的元素或带有%的垂直填充的伪元素。这将允许您使用width作为参考:显示以下内容的代码段:

.flex-container {
    padding: 0;
    margin: 0;
    list-style: none;
    display: -webkit-box;
    display: -moz-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
    -webkit-flex-flow: row;
    justify-content: space-around;
   
    line-height:30px;
}
.flex-item {
    background: tomato;
    margin: 5px;
    color: white;
    font-weight: bold;
    font-size: 1.5em;
    text-align: center;
    flex: 1 0 auto;
    height:auto;
}
.flex-item:before {
    content:'';
    float:left;
    padding-top:100%;
}
<body>
    <div class="flex-container">
        <div class="flex-item">1</div>
        <div class="flex-item">2</div>
        <div class="flex-item">3</div>
        <div class="flex-item">4</div>
        <div class="flex-item">5</div>
        <div class="flex-item">6</div>
        <div class="flex-item">7</div>
    </div>
    <div class="flex-container">
        <div class="flex-item">1</div>
        <div class="flex-item">2</div>
        <div class="flex-item">3</div>
        <div class="flex-item">4</div>
        <div class="flex-item">5</div>
        <div class="flex-item">6</div>
        <div class="flex-item">7</div>
    </div>
    <div class="flex-container">
        <div class="flex-item">1</div>
        <div class="flex-item">2</div>
        <div class="flex-item">3</div>
        <div class="flex-item">4</div>
        <div class="flex-item">5</div>
        <div class="flex-item">6</div>
        <div class="flex-item">7</div>
    </div>
    <div class="flex-container">
        <div class="flex-item">1</div>
        <div class="flex-item">2</div>
        <div class="flex-item">3</div>
        <div class="flex-item">4</div>
        <div class="flex-item">5</div>
        <div class="flex-item">6</div>
        <div class="flex-item">7</div>
    </div>
    <div class="flex-container">
        <div class="flex-item">1</div>
        <div class="flex-item">2</div>
        <div class="flex-item">3</div>
        <div class="flex-item">4</div>
        <div class="flex-item">5</div>
        <div class="flex-item">6</div>
        <div class="flex-item">7</div>
    </div>
    <div class="flex-container">
        <div class="flex-item">1</div>
        <div class="flex-item">2</div>
        <div class="flex-item">3</div>
        <div class="flex-item">4</div>
        <div class="flex-item">5</div>
        <div class="flex-item">6</div>
        <div class="flex-item">7</div>
    </div>
    <div class="flex-container">
        <div class="flex-item">1</div>
        <div class="flex-item">2</div>
        <div class="flex-item">3</div>
        <div class="flex-item">4</div>
        <div class="flex-item">5</div>
        <div class="flex-item">6</div>
        <div class="flex-item">7</div>
    </div>
</body>

一个inline-block的元素可以做太多,只是适应框的显示/行为和它的内容。这里的魔力来自于填充:50%0; (100%的垂直填充等于父级的宽度)。有关垂直边距填充,请参见w3c


1
看起来我们有非常相似的想法。您提到了诀窍,padding: 50% 0但实际上是在使用padding-top: 100%。功能上等效,但与代码中的内容不一致。
詹姆斯·蒙塔涅2015年

1
没问题 我完全理解,任何组合加起来等于100%都可以。我只是以为这可能会使那些还不了解这一点的人感到困惑,因为您说的诀窍是padding: 50% 0在代码未完全使用该技巧时使用。如果那是故意的,那很好,也许只是我的阅读方式使它看起来令人困惑。
詹姆斯·蒙塔涅2015年

1
效果很好,谢谢!相关问题:由于高度现在由伪元素确定,因此我似乎无法在正方形内垂直对齐文本...有什么建议吗?
Moto

5
请注意,当为自己指定flex容器的子代时,这在Firefox(而不是Chrome)中中断display: flex。请参阅fiddle jsfiddle.net/d562oL7w删除display: flexflex项目上的声明以查看区别。
亚当·雷斯

1
@AdamBuczynski,我想如果您要平方也需要给个高度。恰好发生在:before flex元素上的padding-top效率低下的原因是,它以某种方式看不到宽度(在FF中) jsfiddle.net/d562oL7w/1
G-Cyrillus

26

对于那些也想用display: flex正方形的div里面,你需要使用display: table:before元素,否则方将与Chrome浏览器,但不会与Firefox或边缘工作(如火狐47和边缘13)。

在下面的代码段中,该代码段适用于所有浏览器,我还演示了如何用百分比列(在本例中为20%)包装无限制的项目,并使用填充和内部div分隔它们,因为在FF和当然是Edge。

.flex-container {
  display: flex;
  justify-content: start;
  flex-wrap: wrap; 
}

.flex-cell {
  flex: 0 0 20%;
  display: flex;
  justify-content: center;
  align-items: stretch;
  padding: 0.5rem;
  box-sizing: border-box;
}

.flex-cell:before {
  content: '';
  display: table;
  padding-top: 100%;
}

.flex-item {
  flex-grow: 1;
  border: 1px solid black;
  background: tomato;
  color: white;
  
  display: flex;
  justify-content: center;
  align-items: center;
}
<body>
    <div class="flex-container">
        <div class="flex-cell">
            <div class="flex-item">1</div>
        </div>
        <div class="flex-cell">
            <div class="flex-item">2</div>
        </div>
        <div class="flex-cell">
            <div class="flex-item">3</div>
        </div>
        <div class="flex-cell">
            <div class="flex-item">4</div>
        </div>
        <div class="flex-cell">
            <div class="flex-item">5</div>
        </div>
        <div class="flex-cell">
            <div class="flex-item">6</div>
        </div>
        <div class="flex-cell">
            <div class="flex-item">7</div>
        </div>
        <div class="flex-cell">
            <div class="flex-item">8</div>
        </div>
        <div class="flex-cell">
            <div class="flex-item">9</div>
        </div>
        <div class="flex-cell">
            <div class="flex-item">10</div>
        </div>
        <div class="flex-cell">
            <div class="flex-item">11</div>
        </div>
        <div class="flex-cell">
            <div class="flex-item">12</div>
        </div>
    </div>
</body>


2
you need to use display: table for the :before element非常简短而不错的解决方案,谢谢。
OlehZiniak

2
这应该是公认的答案。display::before元素的表是唯一可行的解​​决方案!
戴维(David)

如果盒子的内容比宽度高,这将不起作用。
r3wt

22

保持纵横比的通常技巧是使用以下事实:边距和/或填充顶部和底部的百分比值是根据包含元素的宽度而不是高度来计算的。

你可以看到这个问题的非柔性版HERE

但是,您希望flex处理元素的宽度,而不是设置基于百分比的宽度。为此,我想出了一种可以与flex一起使用的方法的变体:

.flex-item:before {
    content: "";
    display: block;
    padding-top: 100%;
    float: left;
}

这里的窍门是使用:before伪元素插入宽度为0的元素,并添加一个padding-top为100%。100%是宽度的100%,这意味着没有内容的元素将和其容器一样高。这会将弹性项目拉伸到与其宽度相同的高度:

此外,您将需要从弹性容器中删除定义的高度,否则高度将无法增长。您可能还需要添加min-width: 1.5em元素,以使元素不会缩小到每个方格中的字符高度以下。

http://jsfiddle.net/gonyhvz8/14/


2
非常感谢!我喜欢非弹性版本:)
蓝色电车

3

当然可以使用flexboxes,但是提到的解决方案即使使用也缺乏灵活性flexboxes。您无法调整浮动框。您必须先设置每行的框数。

在此解决方案中,您可以调整图块/正方形的动态宽度,并根据需要浮动它们。如果您使用flexboxes尝试此操作,则会遇到问题,padding-top因为它不会定向在包含块的给定宽度上。

没有flexboxes更大灵活性的解决方案:

.flex-container {
  padding: 0;
  margin: -5px;
  font-size: 0;
  font-family: Helvetica, Arial, sans-serif;
}

.flex-item {
  position: relative;
  display: inline-block;
  height: 0;
  width: 100%;
  padding-top: 100%;
  height: auto;
  font-size: 20px;
  color: white;
  font-weight: bold;
  text-align: center;
}
@media (min-width: 480px) {
  .flex-item {
    width: 33.3333%;
    padding-top: 33.3333%;
  }
}
@media (min-width: 768px) {
  .flex-item {
    width: 25%;
    padding-top: 25%;
  }
}
.flex-item-inner {
  position: absolute;
  display: flex;
  justify-content: center;
  align-items: center;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  margin: 10px;
  background: tomato;
}
<body>
  <div class="flex-container">
    <div class="flex-item">
      <div class="flex-item-inner">
        <div class="flex-item-inner-content">
          1
        </div>
      </div>
    </div>
    <div class="flex-item">
      <div class="flex-item-inner">
        <div class="flex-item-inner-content">
          2
        </div>
      </div>
    </div>
    <div class="flex-item">
      <div class="flex-item-inner">
        <div class="flex-item-inner-content">
          3
        </div>
      </div>
    </div>
    <div class="flex-item">
      <div class="flex-item-inner">
        <div class="flex-item-inner-content">
          4
        </div>
      </div>
    </div>
    <div class="flex-item">
      <div class="flex-item-inner">
        <div class="flex-item-inner-content">
          5
        </div>
      </div>
    </div>
    <div class="flex-item">
      <div class="flex-item-inner">
        <div class="flex-item-inner-content">
          6
        </div>
      </div>
    </div>
  </div>
</body>

链接到Codepen:http://codepen.io/dailysh-it/pen/xOVydO


1
您没有按照原始海报的要求将flexbox用于容器。另外,您确实可以根据需要使用flexbox指定每行的项目数量。只需使用flex-wrap:例如,包装并设置flex:0 0 33%的项的with。
CGodo '16

3

有一种方法也可以不使用任何额外的html元素。我用您的代码库http://jsfiddle.net/octavioamu/kq97pm3L/创建了一个小提琴,但打勾的是在带显示表的elemento之后使用

flex-item:after {
    content: ' ';
    padding-top: 100%;
    display: table;
}

您可以在任何网格中使用它,例如带有引导程序的列网格中的正方形...这是在%网格列内工作的无礼的混音https://codepen.io/octavioamu/pen/xzeXGm

这是您的代码:

.flex-container {
  display: flex;
}

.flex-item {
  display: flex;
  width: 100%;
  justify-content: center;
  align-items: center;
  background-color: red;
  margin: 5px
}

.flex-item:after {
  content: ' ';
  padding-top: 100%;
  display: table;
}
<body>
  <div class="flex-container">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
    <div class="flex-item">4</div>
    <div class="flex-item">5</div>
    <div class="flex-item">6</div>
    <div class="flex-item">7</div>
  </div>
  <div class="flex-container">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
    <div class="flex-item">4</div>
    <div class="flex-item">5</div>
    <div class="flex-item">6</div>
    <div class="flex-item">7</div>
  </div>
  <div class="flex-container">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
    <div class="flex-item">4</div>
    <div class="flex-item">5</div>
    <div class="flex-item">6</div>
    <div class="flex-item">7</div>
  </div>
  <div class="flex-container">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
    <div class="flex-item">4</div>
    <div class="flex-item">5</div>
    <div class="flex-item">6</div>
    <div class="flex-item">7</div>
  </div>
  <div class="flex-container">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
    <div class="flex-item">4</div>
    <div class="flex-item">5</div>
    <div class="flex-item">6</div>
    <div class="flex-item">7</div>
  </div>
  <div class="flex-container">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
    <div class="flex-item">4</div>
    <div class="flex-item">5</div>
    <div class="flex-item">6</div>
    <div class="flex-item">7</div>
  </div>
  <div class="flex-container">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
    <div class="flex-item">4</div>
    <div class="flex-item">5</div>
    <div class="flex-item">6</div>
    <div class="flex-item">7</div>
  </div>
</body>


3

G-Cyr答案的简化版本

.flex-container {
  display: flex;
  flex-flow: row;
  justify-content: center;
}

.flex-item {
  background: tomato;
  margin: 10px;
  max-width: 50px;
  flex-grow: 1;
  flex-shrink: 0;
  flex-basis: 0;
  height: auto;
}

.flex-item:before {
  /* The psuedo-element's padding-top percentage is based on the element's width. */
  padding-top: 100%;
  content: '';
  float: left;
}
<div class="flex-container">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
</div>
<div class="flex-container">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
</div>
<div class="flex-container">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
</div>
<div class="flex-container">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
</div>

结果

在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.