带有示例代码的常见 CSS Flexbox 布局模式
从理论上讲,使用flexbox(Flexible Box Module)来构建复杂的布局非常简单,但我经常发现自己添加display: flex
到一个元素中,然后立即花费大量时间试图弄清楚如何让任何东西表现得像我期望的那样. 如果你和我一样:这里有 10 个带有 CSS 的示例 flexbox 布局的列表。我将介绍这些基本布局模式:
每个示例都假定您的 HTML 包含一个元素,该元素具有一个类container
,然后包含几个子级,这些子级都具有一个类item
(每个示例的子级数量不同):
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
...
</div>
1.全部拉伸,固定间距
最基本的 flexbox 模式:让几个盒子拉伸并填充其父元素的整个宽度。您需要做的就是display: flex
在容器上设置,并在子级上设置一个flex-grow
值0
:
.container {
display: flex;
}
.item {
flex-grow: 1;
height: 100px;
}
.item + .item {
margin-left: 2%;
}
我们使用+
选择器只在成对的项目之间添加间隙(本质上只是跳过列表中第一个项目的左边距)。
与任何其他元素相比,增加flex-grow
将增加一个元素允许拉伸的空间量。 如果我们在这里设置flex-grow
中间2
元素,我们基本上会将可用空间划分为 6 个块(每个项目 1 个块加上中间项目 1 个额外的块,1+1+2+1+1)。中间项获得两块 ( flex-grow: 2
) 的空间,所有其他元素获得一块 ( flex-grow: 1
)。
2.拉伸中间,固定间距
一个常见的应用程序和 Web 模式是创建一个顶部栏,我们只想在其中拉伸中间元素,但保持最右边和最左边的元素固定。如果我们只想拉伸一个元素,我们可以100px
在应该保持静态flex-grow: 1
的元素和应该拉伸的元素上设置固定宽度(例如 ):
.container {
display: flex;
}
.item {
height: 100px;
width: 100px;
}
.item-center {
flex-grow: 1;
}
.item + .item {
margin-left: 2%;
}
即使此处的中间元素定义width
了100px
,flex-grow
也会使其拉伸以占用所有可用空间。
3.交替网格
一种布局模式是创建一个有一些变化的网格:在两个大小相同的项目的每一行之后,有一个项目占据一整行:
为此,我们需要:
flex-wrap: wrap
在容器上设置(或全部items
呈现在单行上)- 在容器上设置
justify-content: space-between
,仅在元素之间创建空间(而不是在父元素的边缘和项目之间) - 将每个项目设置
width
为49%
(或等于或小于的类似值50%
) - 将每第三个项目设置
width
为,100%
以便它填充整行。我们可以使用选择器来定位列表中的第三个项目nth-child()
。
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.item {
width: 48%;
height: 100px;
margin-bottom: 2%;
}
.item:nth-child(3n) {
width: 100%;
}
如果您希望第一行是全角的,并且后面的两个项目共享一行,请注意您不能编写.item:nth-child(1n) { width: 100% }
- 这将针对所有项目。您必须通过选择每隔三个元素来定位第一个项目,然后退后两个项目:.item:nth-child(3n-2) { width: 100% }
.
4.3x3 网格
我们可以通过设置所有子项的首选宽度来创建一个 3x3 网格(flex-grow
这里使用简写:)。项目之间的边距是每一行的剩余部分,即 (100%-32x3)/2=2%。我已经匹配了边距 ( ) 以实现所有元素之间的均匀间距:0``flex-basis``flex``flex: 0 32%``margin-bottom: 2%
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.item {
flex: 0 32%;
height: 100px;
margin-bottom: 2%; /* (100-32*3)/2 */
}
您可以更改flex-basis
以增加或减少每行上的项目数。flex: 0 24%
将在每行放置 4 个项目,flex: 0 19%
将在每行放置 5 个项目,依此类推。
5.3x3 网格,受限比例 (1:1)
我们可以通过使用有点 hacky 的padding
CSS 技巧来创建一个充满比例受限项目的网格。如果我们%
在设置padding
元素时使用,padding
则相对于该项目的父项设置width
,.container
在这种情况下。width
我们可以通过将项目的和padding-bottom
设置为相同的值(并通过 有效地设置该height
元素的)来使用该效果来创建正方形padding-bottom
:
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.item {
width: 32%;
padding-bottom: 32%; /* Same as width, sets height */
margin-bottom: 2%; /* (100-32*3)/2 */
position: relative;
}
由于我们创建了一个实际上仅由填充组成的元素,并且没有为内容留下空间,因此我们需要在此示例中设置position: relative
并.item
添加一个带有 的子元素position: absolute
,并使用该元素“重置”画布并添加内容。
6.3x3 网格,受限比例 (16:9)
要更改项目的比例,您需要做的就是更改 和width
的padding-bottom
比例.item
。更改width
会影响每行上的项目数,以便不影响网格结构,例如,我们可以更改padding-bottom
为18%
创建 16:9(相当于 32:18)的矩形。
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.item {
width: 32%;
padding-bottom: 18%; /* 32:18, i.e. 16:9 */
margin-bottom: 2%; /* (100-32*3)/2 */
}
7.图表:竖线
如果您想使用 flexbox 创建简单的图形可视化,您需要做的就是将align-items
容器设置为flex-end
并为每个条形定义一个height
。flex-end
将确保条形图固定在图表的底部。
.container {
display: flex;
height: 300px;
justify-content: space-between;
align-items: flex-end;
}
.item { width: 14%; }
.item-1 { height: 40%; }
.item-2 { height: 50%; }
.item-3 { height: 60%; }
.item-4 { height: 20%; }
.item-5 { height: 30%; }
8.图表:水平条
使用与垂直条相同的技术,我们可以简单地添加flex-direction
一个container
值column
来创建一组水平条。flex-direction
可以有一个值row
(默认值)或column
,其中 arow
水平运行 (→) 和 acolumn
垂直运行 (↓)。您也可以分别使用row-reverse
(←) 和column-reverse
(↑) 来反转两者的方向。
.container {
display: flex;
height: 300px;
justify-content: space-between;
flex-direction: column;
}
.item { height: 14%; }
.item-1 { width: 40%; }
.item-2 { width: 50%; }
.item-3 { width: 60%; }
.item-4 { width: 20%; }
.item-5 { width: 30%; }
9.垂直堆叠(居中)
要创建一个垂直堆栈并使项目从上到下运行,我们需要做的就是将flex-direction
默认值更改row
为column
:
.container {
display: flex;
flex-direction: column;
align-items: center;
}
.item {
height: 40px;
margin-bottom: 10px;
}
10.砌体(或马赛克)
使用 flexbox 创建砌体布局的主要挑战之一是,要使项目影响项目在其上方和下方的位置,我们需要将flex-direction
容器的 更改为column
,这使得项目从上到下运行。这创建了一个看起来不错的布局,类似于砌体效果,但它可能会让用户感到困惑;它创建了一个意想不到的元素排序。如果您从左到右阅读,元素似乎会被打乱并以看似随机的顺序出现,例如 1、3、6、2、4、7、8 等。
恰好,我们可以使用该order
属性来更改渲染元素的顺序。我们可以将该属性与nth-child()
选择器的一些巧妙使用结合起来,根据项目的原始顺序动态排序项目。如果我们想创建一个包含三列的砌体布局,我们可以将所有项目分成三个“组”,如下所示:
/* Re-order items into rows */
.item:nth-child(3n+1) { order: 1; }
.item:nth-child(3n+2) { order: 2; }
.item:nth-child(3n) { order: 3; }
/* Force new columns */
.container::before,
.container::after {
content: "";
flex-basis: 100%;
width: 0;
order: 2;
}
如果我们确保将这些组中的每一个呈现为一列(不多也不少),当您从左到右阅读时,它会产生项目已恢复到其原始顺序的错觉。如果我们在视觉上将网格解析为行,第一行将包含每个组的第一个元素 ( 1, 2, 3),第二行将包含每个组的第二个元素 ( 4, 5, 6),依此类推。然后,我们在占父级高度 100% 的列之间插入元素,这会强制列换行,并且不会意外地与相邻列合并。这是完整的 CSS 片段:
.container {
display: flex;
flex-flow: column wrap;
align-content: space-between;
height: 580px;
}
.item {
width: 32%;
margin-bottom: 2%; /* (100-32*3)/2 */
}
/* Re-order items into rows */
.item:nth-child(3n+1) { order: 1; }
.item:nth-child(3n+2) { order: 2; }
.item:nth-child(3n) { order: 3; }
/* Force new columns */
.container::before,
.container::after {
content: "";
flex-basis: 100%;
width: 0;
order: 2;
}
从视觉上看,这实现了非常接近砌体效果的效果。