本文要解决的问题:列表的布局。

一直以来,栅格布局由于其响应式的特点广为应用,但它的原理是将一列分为12份再进行组合,所以对于每列宽度的划分不是很灵活。

本文介绍flex、table-cell两种方式,来解决列表问题。

  • 使列表宽度灵活定义,并能根据屏幕大小进行自适应。
  • 解决不定高度的行,内容垂直居中、水平居中的问题。
  • 解决响应式的问题(采用媒体查询)。

基本知识的介绍:

flex:

是一种不同于盒模型的布局方式,它是一种弹性布局可以便捷的实现各种布局。

  • 添加display属性的取值flex。
  • 该布局中引入主轴、交叉轴的概念。
  • 主轴可以指横向、也可以指纵向,由flex-direction属性的取值决定。
  • 主轴确定后,与其交叉的方向即为纵轴。
  • 在该布局下存在类似float、vertical-align功能的新属性,所以float、clear、vertical-align不再生效。
  • 本例中用到的属性:
    • flex-basis:用于子元素上设置宽度,与width类似。
    • justify-content: 用于父元素上,设置主轴上的对齐方式,可取flex-start | flex-end |center |space-between |space-around;
    • align-items: 用于父元素上,设置交叉轴上的对齐方式,可取flex-start | flex-end |center |space-between |space-around;
  • flex介绍可参考flex教程
table-cell:

table布局是一种传统的布局方式,display:table-cell去掉了table标签,用css的形式实现类似的布局,去掉了语义化。

  • 当display设置为table-cell时元素类似一个单元格,对margin不敏感,只对padding敏感。
  • 对高度敏感,当同行其他列高度变化时,该列高度随之变化,vertical-align也可以使内部元素动态垂直居中。
  • table-cell是一个较早的属性,其兼容性较好。
  • 可以在内部嵌套栅格布局,不会引起冲突。

案例:

  • 希望固定操作列的宽度。
  • 其他列的宽度可以根据屏幕的宽度自适应。
  • 当屏幕宽度过窄时,折行显示。

flex实现:

DOM结构:

1
2
3
4
5
6
7
8
<div class="container">
<div class="item0">
这里是列表内容
</div>
<div class="item1">
操作
</div>
</div>

CSS样式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
.container {
background-color: pink; //采用背景颜色来标注div位置
display: flex; // 外层div采用flex布局
}
.item0 {
background-color: grey;
flex-basis: 100%; // 宽度占满除操作列之外的宽度
height: 100px; // 设置内容列高度,也可让其随内容变化
/**以下解决内容水平、垂直居中问题**/
display: flex;
justify-content: center; // 操作列内容水平居中
align-items: center; // 操作列内容垂直居中
}
.item1 {
background-color: purple;
flex-basis: 80px; // 固定操作列宽度
min-height: 40px; // 设置操作列最小高度,真是高度随内容列高度变化
/**以下解决内容水平、垂直居中问题**/
display: flex; // 设置操作列布局方式
justify-content: center; // 操作列内容水平居中
align-items: center; // 操作列内容垂直居中
}
/**响应式处理**/
@media screen and (max-width: 750px){
.container {
display: block; // 当屏幕宽度小于750px时,将外层布局变为block;此时两列各占一行。内部内容仍然是flex布局。
}
}
  • 元素内部需要flex布局,需要设置该元素display:flex

table-cell实现:

DOM结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div class="container">
<div class="item0">
<div class="content">
<div class="content-inner">
这里是列表内容
</div>
</div>
</div>
<div class="item1">
<div class="content">
<div class="content-inner">
操作
</div>
</div>
</div>
</div>

CSS样式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**实现外层布局**/
.container {
background-color: pink;
display: table;
width: 100%;
}
.item0 {
background-color: grey;
display: table-cell;
height: 100px;
}
.item1 {
background-color: purple;
display: table-cell;
width: 80px;
min-height: 40px;
}
/**实现内容居中**/
.content {
display: table;
width: 100%;
height: 100%;
}
.content-inner {
display: table-cell;
text-align: center;
vertical-align: middle;
}
/**实现响应式**/
@media screen and (max-width: 750px){
.container {
display: block;
}
.item0 {
display: block;
}
.item1 {
display: block;
width: 100%;
height: 40px;
}
}
  • 父元素需要设置display:table
  • 子元素display:table-cell,且设置了高度或者其他列设置了高度,vertical-align: middle;才能生效。

实现效果

屏幕宽度>750px

图片

屏幕宽度<750px

响应后

小结

flex用简单的样式,就实现了不定高垂直居中,宽度灵活自适应,flex目前所有类型浏览器都已支持,只是某些低版本浏览器会存在兼容性问题。table-cell兼容性良好,但稍显复杂。总体来看flex才是大势所趋。