带有 flexbox 的 css 正方形网格
Posted
技术标签:
【中文标题】带有 flexbox 的 css 正方形网格【英文标题】:css grid of squares with flexbox 【发布时间】:2015-06-01 05:04:20 【问题描述】:我正在尝试创建一个响应式正方形网格。正方形应调整大小以适应视口的宽度。更改视口高度时,方块不应调整大小。
我知道如何调整每个正方形的宽度,但我不知道如何使元素变成正方形以及如何在视口宽度发生变化时缩放它们的高度。
在小提琴下面的示例中,七个正方形应始终水平放置,并且它们应按正方形缩放。我不在乎有多少行可见。
在这里提琴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,但这似乎符合您的其他要求:***.com/a/20457076/717383 【参考方案1】:您不应该设置任何大小。 你可以使用一个额外的元素或一个以 % 为单位的带有垂直填充的伪元素。这将允许您使用宽度作为参考:一个 sn-p 显示:
.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 元素也可以,只需调整框的显示/行为及其内容即可。这里的魔力来自 padding:50% 0; (100% 垂直填充等于父级的宽度)。见 w3c 关于垂直margin 和padding
[edit 07/2021]关于将内容集中在该正方形内以供需要此功能的人使用 (make the square itself a flex boxe too):
.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;
display:flex;
align-items:center;
justify-content:center;
.flex-item:before
content:'';
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>
如果这个答案不能完全满足你的广场需求,你可能也会觉得有趣:Responsive grid of squares within a responsive grid of squares & 4x4 grid of squares that scale up to a maximum width ;)
【讨论】:
看起来我们的想法非常相似。您提到的技巧是padding: 50% 0
,但实际上您使用的是padding-top: 100%
。功能上等效,但与您的代码中的内容不一致。
没问题。我完全理解任何加起来达到 100% 的组合都可以。我只是认为你说的诀窍是在你的代码没有完全使用 padding: 50% 0
时,可能会让那些还不明白这一点的人感到困惑。如果这是故意的,那很好,可能只是我的阅读方式让它看起来很混乱。
效果很好,谢谢!相关问题:由于高度现在由伪元素确定,我似乎无法垂直对齐正方形内的文本......有什么建议吗?
请注意,当 flex 容器的子项自己被赋予 display: flex
时,这 breaks 在 Firefox 中(而不是在 Chrome 中)。请参阅 fiddle jsfiddle.net/d562oL7w 删除弹性项目上的 display: flex
声明以查看差异。
@AdamBuczynski,我想如果你想要方形,你也需要给出一个高度。它只是碰巧在 :before flex 元素上的 padding-top 效率低下,因为它以某种方式看不到宽度(在 FF 中)jsfiddle.net/d562oL7w/1【参考方案2】:
对于那些还想在方形 div 中使用 display: flex
的人,您需要将 display: table
用于 :before
元素,否则方形将适用于 Chrome,但不适用于 Firefox 或 Edge(如Firefox 47 和 Edge 13)。
在下面的 sn-p 中,它应该适用于所有浏览器,我还演示了如何用百分比列(在本例中为 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>
【讨论】:
you need to use display: table for the :before element
非常简短且不错的解决方案,谢谢。
这应该是公认的答案。 :before 元素的 display: table 是唯一可行的解决方案!
如果盒子的内容高于宽度,这将不起作用。【参考方案3】:
保持纵横比的常用技巧是使用以下事实:边距和/或填充顶部和底部的百分比值是根据包含元素的宽度而不是高度计算的。
你可以看到这个问题的非弹性版本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/
.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>
【讨论】:
非常感谢!我喜欢非弹性版本:)【参考方案4】:当然,使用 flexboxes 很好,但提到的解决方案即使使用 flexboxes
,也缺乏灵活性。您无法调整浮动框。您之前必须设置每行的框数。
在此解决方案中,您可以调整瓷砖/正方形的动态宽度,并按照您的喜好浮动它们。如果您尝试使用 flexbox 进行此操作,您将遇到 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
【讨论】:
您没有像原始海报所希望的那样将 flexbox 用于容器。此外,如果需要,您确实可以使用 flexbox 指定每行的项目数量。只需使用 flex-wrap: wrap 并将项目的 with 设置为 flex: 0 0 33%,例如。【参考方案5】: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>
结果
【讨论】:
这仍然会设置一个max-width
,当宽度应该是屏幕大小与该行有多少的函数时,这是不可取的。【参考方案6】:
还有一种方法可以不用额外的 html 元素来制作它。我用你的代码库 http://jsfiddle.net/octavioamu/kq97pm3L/ 创建了一个小提琴,但勾号是在 elemento 之后使用显示表
flex-item:after
content: ' ';
padding-top: 100%;
display: table;
您可以在任何网格中使用它,例如带有引导程序的柱状网格内的正方形... 这是一个在 % 网格列https://codepen.io/octavioamu/pen/xzeXGm 中工作的 sass mixin@
这是您的代码:
.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>
【讨论】:
【参考方案7】:当基于 padding-top 的答案对您不起作用时(例如我的情况),还有另一种解决方案。这两种变体都适用于 flexbox 以及浮动项目。
变体 1:透明像素以保持纵横比
.container
display: flex;
.item
position: relative;
width: 25%;
flex: 0 0 25%;
.item img
width: 100%;
height: auto;
.item .content
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
<div class="container">
<div class="item">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=">
<div class="content">Insert content here</div>
</div>
[...]
</div>
变体 2:空 SVG 以保持纵横比
这基本相同,但您可以修改 SVG 的 viewbox 属性以应用除 1:1 以外的其他纵横比
.container
display: flex;
.item
position: relative;
width: 25%;
flex: 0 0 25%;
.item svg
width: 100%;
height: auto;
.item .content
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
<div class="container">
<div class="item">
<svg viewbox="0 0 1 1"></svg>
<div class="content">Insert content here</div>
</div>
[...]
</div>
【讨论】:
以上是关于带有 flexbox 的 css 正方形网格的主要内容,如果未能解决你的问题,请参考以下文章