带有 flexbox 的 css 正方形网格

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29307971/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 03:07:45  来源:igfitidea点击:

css grid of squares with flexbox

cssresponsive-designflexbox

提问by Moto

I am trying to create a responsive grid of squares. The squares should resize to fit the viewport's width. The squares should not resize when changing the viewport's height.

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

I got how to adjust the width of each square, but I don't know how to make the elements square and how to scale their height when the viewport width changes.

我知道如何调整每个正方形的宽度,但我不知道如何使元素变成正方形以及如何在视口宽度发生变化时缩放它们的高度。

In the example at the fiddle below the seven squares should always fit horizontally, and they should scale as squares. I do not care how many rows are visible.

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

Fiddle here http://jsfiddle.net/gonyhvz8/11/

在这里小提琴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;
}

回答by G-Cyrillus

you should not set any size. you may use an extra element or a pseudo elemnt with vertical padding in %. this will allow you to use width as reference : a snippet to show:

你不应该设置任何大小。您可以使用额外的元素或带有 % 垂直填充的伪元素。这将允许您使用宽度作为参考:一个片段来显示:

.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>

an inline-blockelement could do too, just adapt the display/behavior of the box and it's content. the magic here comes from padding:50% 0; (100% vertical padding equals width of parent). see w3c about vertical marginand padding

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

回答by CGodo

For those that also want to use display: flexinside the square divs, you need to use display: tablefor the :beforeelement, otherwise the square will work with Chrome but won't work with Firefox or Edge (as of Firefox 47 and Edge 13).

对于那些还想display: flex在方形 div 内使用的人,您需要使用display: tablefor:before元素,否则方形将适用于 Chrome,但不适用于 Firefox 或 Edge(从 Firefox 47 和 Edge 13 开始)。

In the snippet bellow, which should work for all browsers, I also demonstrate how to wrap unlimited items with percentage columns (in this case 20%) and separate them with padding and inner divs, since margins with percentages do not work correctly in FF and of course Edge.

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

.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>

回答by James Montagne

The usual trick for maintaining aspect ratio is to use the fact that percentage values of margin and/or padding top & bottom are calculated based on the width of the containing element, and not the height.

保持纵横比的常用技巧是利用这样一个事实,即根据包含元素的宽度而不是高度计算边距和/或填充顶部和底部的百分比值。

You can see a non-flex version of this question HERE

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

However, you would like to have flexdeal with the width of your elements, not set percentage based widths. For that, I have come up with a variation of that approach that will work with flex:

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

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

The trick here is to use the :beforepseudo-element to insert a 0 width element with a padding-topof 100%. That 100% is 100% of the width, meaning this element with no content will be equally as tall as its container. This will stretch the flex-item to the same height as its width:

这里的技巧是使用:before伪元素插入一个宽度为 0、apadding-top为 100% 的元素。100% 是宽度的 100%,这意味着这个没有内容的元素将与其容器一样高。这会将 flex-item 拉伸到与其宽度相同的高度:

Additionally, you will need to remove the defined height from your flex-container or the height can't grow. You also may want to add min-width: 1.5emso that your elements don't shrink below the height of the character you have in each square.

此外,您需要从 flex-container 中删除定义的高度,否则高度无法增长。您可能还想添加,min-width: 1.5em以便您的元素不会缩小到您在每个方块中所拥有的角色的高度以下。

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

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

.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 0px;
    min-width: 1.5em;
}
.flex-item:before {
    content: "";
 display: block;
 padding-top: 100%;
    float: left;
}
<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>

回答by Octavioamu

There is a way to made it with no extra html elements also. I created a fiddle with your codebase http://jsfiddle.net/octavioamu/kq97pm3L/but the tick is to use after elemento with display table

还有一种方法可以在没有额外的 html 元素的情况下制作它。我用你的代码库http://jsfiddle.net/octavioamu/kq97pm3L/创建了一个小提琴,但勾号是在 elemento 和显示表之后使用

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

You can use it in any grid, for example an square inside a column grid with bootstrap... Here is a sass mixin working inside a % grid column https://codepen.io/octavioamu/pen/xzeXGm

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

And here is with your code:

这是您的代码:

.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>

回答by Michael Czechowski

Surely it is nice to use flexboxes, but the solution mentioned has a lack of flexability even it uses flexboxes. You are not able to adjust a floating of boxes. You are bounded to set the number of boxes per row before.

使用 flexboxes 当然很好,但是提到的解决方案缺乏灵活性,即使它使用flexboxes. 您无法调整浮动框。您必须在之前设置每行的框数。

In this solution you can adapt a dynamic width of tiles/square and float them how you like. If you try this with flexboxes, you will get a problem with padding-topbecause it does not orientate on the given width of the containing blocks.

在此解决方案中,您可以调整瓷砖/正方形的动态宽度并按照您的喜好浮动它们。如果你用 flexboxes 尝试这个,你会得到一个问题,padding-top因为它没有定位在包含块的给定宽度上。

Solution without flexboxesbut more flexability:

没有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>

Link to the codepen: http://codepen.io/dailysh-it/pen/xOVydO

代码笔链接:http://codepen.io/dailysh-it/pen/xOVydO

回答by Shaun Luttin

Simplified Version of G-Cyr's Answer

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>

Result

结果

enter image description here

在此处输入图片说明