CSS3新特性详解(五):多列columns column-count和flex布局


Posted in HTML / CSS onApril 30, 2021

简单来说Html Dom元素就2类:行内元素和块级元素,前者在行内显示(span等),后者换行显示(div等)。所谓布局,比如早期的4大布局:块布局、行内布局、表格布局、定位布局,多半解决的是块级元素行内显示问题。我们可以看下块级元素行内显示的常见方式:

  • float,浮动显示,float-left或float-right;
  • display: inline-block,块级元素转为行内块显示,大名鼎鼎的前端框架bootstrap深谙此道,btn-group|form-group|input-group等都是基于此实现;
  • 表格布局:将块元素放到td里,“任凭你块元素多?,也只能在我的td里猫着”;
  • position:流氓布局,可以想哪显示就哪显示,设z-index:9999基本上就可以遮挡所有元素在最前显示啦

基于此,基本上早期的页面都是表格布局,后来逐渐被div+css替代,现在呢?

  • 以bootstrap为例,依然还是float布局,经典的col-*栅格系统就是基于此实现;
  • 以微信小程序为例,则是flex布局;

除此之外,display:table-cell也有很多粉丝,其表现基本上同td,俗称不是表格的表格。早期块级元素行内显示有2个难点:

  • 垂直居中显示问题;
  • 剩余宽度(高度)100%填充问题;

随着CSS3引入多列column-count和flex布局,块级元素行内显示问题,我们有了更多地选择,同时也可以比较优雅地解决垂直居中和宽度、高度自适应问题。接下来,本文将先简单介绍下display:table-cell的使用,然后重点讲解多列column-count和flex布局。

一、display: table-cell

CSS display属性与表格相关的值有下述几种:

描述
table 此元素会作为块级表格来显示(类似 < table >),表格前后带有换行符。
inline-table 此元素会作为内联表格来显示(类似 < table>),表格前后没有换行符。
table-row-group 此元素会作为一个或多个行的分组来显示(类似 < tbody>)。
table-header-group 此元素会作为一个或多个行的分组来显示(类似 < thead>)。
table-footer-group 此元素会作为一个或多个行的分组来显示(类似 < tfoot>)。
table-row 此元素会作为一个表格行显示(类似 < tr>)。
table-column-group 此元素会作为一个或多个列的分组来显示(类似 < colgroup>)。
table-column 此元素会作为一个单元格列显示(类似 < col>)
table-cell 此元素会作为一个表格单元格显示(类似 < td> 和 < th>)
table-caption 此元素会作为一个表格标题显示(类似 < caption>)

比较常用的有:display: table; display: table-row; display: table-cell; 一个经典的table-cell布局为:table -> table-row -> table-cell,对应表格的table->tr->td,看个案例:

.table {display: table; border-collapse: collapse;}
.table-cell{display: table-cell; border: 1px solid #e2e2e2; height: 60px; vertical-align: middle; min-width: 200px; padding: 8px}

<div class="table">
	<div class="table-row">
		<div class="table-cell cell1" style="width: 200px;">table-cell: cell1</div>
		<div class="table-cell cell2" style="width: 100%;">table-cell: cell2</div>
		<div class="table-cell cell3" style="width: 200px;">table-cell: cell3</div>
	</div>
</div>
<div class="table">
	<div class="table-cell cell1" style="width: 200px;">table-cell: cell1</div>
	<div class="table-cell cell2" style="width: 100%;">table-cell: cell2, 没有table-row元素</div>
	<div class="table-cell cell3" style="width: 200px;">table-cell: cell3</div>
</div>

CSS3新特性详解(五):多列columns column-count和flex布局
从上述案例可以看出,有无< div class=“table-row”>元素,效果一样,原因是:浏览器会自动创建一个表格匿名行,另外:

  • 轻松实现文字(换成图片也一样,某宝很多店铺的宝贝图片就是采用此法实现图片垂直居中显示)垂直居中;
  • 轻松实现剩余宽度100%填充,这里有个技巧:cell1,cell3需要设置width、min-width,cell2的width: 100%才有意义;
  • 将cell2变成一个只是占宽度,没有意义的空div,则可实现cell1,cell3两端对齐。

除此之外,display: table-cell还有一个妙用:元素等高对齐或者说高度跟随
CSS3新特性详解(五):多列columns column-count和flex布局

.table {display: table; border-collapse: collapse;}
.table-cell{display: table-cell; border: 1px solid #e2e2e2; height: 60px; vertical-align: middle; min-width: 200px; padding: 8px}
.table-height .cell1{background: rgba(255,0,0,0.6);}
.table-height .cell3{background: rgba(0,0,255,0.6); height: 80px;}
<div class="table table-height">
	<div class="table-cell cell1" style="width: 200px;">table-cell: cell1</div>
	<div class="table-cell cell2" style="width: 100%;">table-cell: cell2, 把cell3的高度设置成80px,cell1和cell2的高度也变成了80px</div>
	<div class="table-cell cell3" style="width: 200px;">table-cell: cell3</div>
</div>

说明: cell3设置了高度80px,cell1和cell2高度跟随cell3变成了80px

二、多列columns、column-count

css3引入了多列文本布局:columns, column-count, column-gap等相关属性设置,其本意是实现如报纸一样的多栏显示,因此我们看到很多案例的class都命名为报纸(newspaper)。多列本质是将容器内的文本元素或div等块级元素按column-count或column-width进行等分,因此多列布局也可用于块级元素行内显示,很多瀑布流就是基于多列布局来实现的。下面我们先看下与多列布局有关的几个关键属性:

  • column-count: number|auto,默认值auto,列数设置;
    如设置了column-width则可以不设置column-count,浏览器会按容器宽度、column-width、column-gap计算列数;
  • column-gap: length|normal,默认值normal(通常是1em,如果没有设置font-size,则常见浏览器1em = 16px),列间隙设置;
  • column-rule: column-rule-width column-rule-style column-rule-color;
    设置列之间分割线的宽度、样式、颜色,column-rule:3px outset #ff00ff,类似border:1px solid #ff00ff,也可宽度、样式和颜色单独设置:
  • column-rule-width: thin|medium|thick|length;
    设置分割线宽度,其值有:纤细|中等|宽厚|指定宽度,默认值为medium
  • column-rule-style: none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset;
    设置分割线样式,默认值为none;groove,ridge,inset和outset效果取决于宽度和颜色;
  • column-rule-color: color; 设置分割线颜色,默认为black

看个案例:

.columns {column-count: 3; column-gap: 20px; column-rule:2px outset #ff00ff;  column-width: 100px; margin-bottom: 20px}
.columns-width {column-count: auto; column-width: 100px;}
.columns .col {border: 1px solid #e2e2e2; padding: 10px; height: 100px;}
.columns-width .col{height: 50px}
<div class="columns">
	<div class="col col1">col1</div>
	<div class="col col2">column-count: 3;<br>column-gap: 20px;<br>column-rule: 2px outset #ff00ff;</div>
	<div class="col col3">col3<br>column-width=(1140 - 20 *2)/3</div>
</div>
<div class="columns columns-width" style="column-width:200px;">
	<div class="col col1">col1</div>
	<div class="col col2">column-width:200px</div>
	<div class="col col3">col3</div>
</div>
<div class="columns columns-width" style="column-width:300px;">
	<div class="col col1">col1</div>
	<div class="col col2">column-width:300px</div>
	<div class="col col3">col3</div>
</div>

CSS3新特性详解(五):多列columns column-count和flex布局
说明:

  • 同时设置了column-count、column-width,则column-width无效;
  • 设置column-width需谨慎,根据column-width计算列数不太好计算,假设column-width: 200px,容器宽度1140px,则具体步骤如下:
    1)先确定列数n,200*n + (n-1)*20<=1140,求得n最大值 = 5;
    2)根据列数,重新计算列宽 = (1140 - (5 -1)*20)/5 = 212;

三、flex布局

CSS3 弹性盒子( Flexible Box 或 flexbox),是一种当页面需要适应不同的屏幕大小以及设备类型时确保元素拥有恰当的行为的布局方式,并且x轴和y轴(或flex主轴、辅轴)都适用,flex布局是微信小程序页面布局首选。flex布局规范、语法说明,大家参考下述2篇,讲解的比较透彻、形象。

  • CSS Flexible Box Layout,https://www.w3.org/TR/css-flexbox-1/
  • Flex 布局教程:语法篇,http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

本文以flex实际案例为主,于案例间讲解flex相关属性使用说明及注意事项。

1、justify-content和align-items

.table .box {
	width: 92px; height: 92px; border: 1px solid #e2e2e2; border-radius: 5px; 
	box-shadow: 0px 0px 10px rgba(0,0,0,0.8);
	display: flex;
}
.table .point {
	width: 20px; height: 20px; margin: 5px; border-radius: 50%; background: #000; 
	display:block; color:#fff; font-size:12px; text-align:center; line-height: 20px;
}
<table class='table table-bordered'>
	<tr>
		<td><div class='box'><span class='point'>1</span></div></td>
		<td><div class='box' style="justify-content:center"><span class='point'>2</span></div></td>
		<td><div class='box' style="justify-content:flex-end"><span class='point'>3</span></div></td>
		<td><div class='box' style="align-items:center"><span class='point'>4</span></div></td>
		<td><div class='box' style="justify-content:center;align-items:center"><span class='point'>5</span></div></td>
		<td><div class='box' style="justify-content:center;align-items:flex-end"><span class='point'>8</span></div></td>
		<td><div class='box' style="justify-content:flex-end;align-items:flex-end"><span class='point'>9</span></div></td>
	</tr>
	<tr>
		<td></td>
		<td>justify-content:center</td>
		<td>justify-content:flex-end</td>
		<td>align-items:center</td>
		<td>justify-content:center;<br>align-items:center</td>
		<td>justify-content:center;<br>align-items:flex-end</td>
		<td>justify-content:flex-end;<br>align-items:flex-end</td>
	</tr>
</table>

CSS3新特性详解(五):多列columns column-count和flex布局

1)justify-content,元素在主轴上的对齐方式

语法: -content: flex-start | flex-end | center | space-between | space-around

说明: flex-direction = row|row-reverse的话,主轴为x轴,默认值flex-start,各个值说明如下:

  • flex-start:元素从行开始处开始摆放;
  • flex-end:元素靠着行结尾摆放;
  • center:元素居中摆放;
  • space-between:元素均匀分布在该行上,元素之间间隙一致;
  • space-around:元素均匀分布在该行上,元素之间间隙一致,首尾元素距离行首、行尾为元素间隙一半;
2)align-items,元素在辅轴上的对齐方式

语法: align-items: flex-start | flex-end | center | baseline | stretch
说明: flex-direction = row|row-reverse的话,辅轴为y轴,默认值stretch;以y轴为辅轴为例,各个值说明如下:

  • flex-start:元素顶部对齐
  • flex-end:元素底部对齐
  • center:元素垂直居中;
  • baseline:与基线对齐,基本上同flex-start,受元素line-height影响;
  • stretch:默认值,如果元素高度没设置或auto,则高度拉伸为容器的高度,但同时会遵照’min/max-width/height’属性的限制;
    CSS3新特性详解(五):多列columns column-count和flex布局
3)案例说明
  • 元素设置了display: flex, 启用flex布局
  • 没有设置flex-direction,默认值为row,主轴为x轴,辅轴为y轴;

2、一个完整的骰子?案例

上个案例主要说明在flex-direction:row的情况下,align-items和justify-content属性的运用,本案例将绘制骰子的6个面,涉及align-self、flex布局嵌套等更多flex布局应用。

.flex-row {display: flex; flex-direction: row;}
.flex-col {display: flex; flex-direction: column;}
.flex-dice .box {
	width: 92px; height: 92px; border: 1px solid #e2e2e2; border-radius: 8px; 
	box-shadow: 0px 0px 8px rgba(0,0,0,0.8);
}
.flex-dice .point {
	width: 20px; height: 20px; margin: 5px; border-radius: 50%; background: blue; 
	display:block; color:#fff; font-size:12px; text-align:center; line-height: 20px;
}
.box-dice4 .point {background: red}
<table class='table table-bordered flex-dice'>
	<tr>
		<td><div class='box flex-row' style="justify-content:center;align-items:center"><span class='point point1' style="background:red;"></span></div></td>
		<td><div class='box flex-col' style="justify-content:space-between; align-items:center">
			<span class='point'></span><span class='point'></span>
		</div></td>
		<td><div class='box flex-row'>
			<span class='point'></span>
			<span class='point' style="align-self:center"></span>
			<span class='point' style="align-self:flex-end"></span>
		</div></td>
		<td><div class='box flex-col box-dice4' style="justify-content: space-between;">
				<div class='flex-row' style="justify-content: space-between;">
					<span class='point'></span><span class='point'></span>
				</div>
				<div class='flex-row' style="justify-content: space-between;">
					<span class='point'></span><span class='point'></span>
				</div>
		</div></td>
		<td><div class='box flex-col'>
				<div class='flex-row' style="justify-content: space-between;">
					<span class='point'></span><span class='point'></span>
				</div>
				<div class='flex-row' style="justify-content: center;">
					<span class='point'></span>
				</div>					
				<div class='flex-row' style="justify-content: space-between;">
					<span class='point'></span><span class='point'></span>
				</div>
		</div></td>			
		<td><div class='box flex-col'>
				<div class='flex-row' style="justify-content: center;">
					<span class='point'></span><span class='point'></span>
				</div>
				<div class='flex-row' style="justify-content: center;">
					<span class='point'></span><span class='point'></span>
				</div>					
				<div class='flex-row' style="justify-content: center;">
					<span class='point'></span><span class='point'></span>
				</div>
		</div></td>
	</tr>
	<tr>
		<td>flex-row<br>justify-content:center<br>align-items:center</td>
		<td>flex-col<br>justify-content:space-between;<br>align-items:center</td>
		<td>flex-row<br>p2 align-self:center<br>p3 align-self:flex-end</td>
		<td>flex-col<br>justify-content:space-between;<br>flex-col<br>justify-content:space-between;</td>
		<td>flex-col<br>flex-row<br>justify-content:space-between;<br>justify-content:center;<br>justify-content:space-between;</td>
		<td>flex-col<br>flex-row<br>justify-content:center</td>
	</tr>
</table>

CSS3新特性详解(五):多列columns column-count和flex布局
案例说明:

1)align-self 属性解析

align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
语法: align-self: auto | flex-start | flex-end | center | baseline | stretch
说明: 除auto值外,其它值同align-items参数值。

2)flex布局嵌套

案例中,骰子4点,5点,6点使用了flex嵌套,先是flex-direction: column布局,然后每行又是flex-direction: row布局;

3)代码结构

通过class统一设置flex布局,flex-col class,flex布局,主轴为y轴;flex-row class,flex布局,主轴为x轴。flex布局里的item元素,用内敛style具体实现。

3、剩余高度、宽度填充

剩余高度、宽度填充需要使用到flex布局的另外3个关键属性:flex-grow、flex-shrink、flex-basis和flex(前三者的简写),具体说明如下:

  • flex-grow 属性用于设置或检索弹性盒子的扩展比率,默认 0
    语法: flex-grow: number|initial|inherit;
  • flex-shrink 属性指定了 flex 元素的收缩规则。flex 元素仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据 flex-shrink 的值,默认值为1,即同比例收缩。
    语法: flex-shrink: number|initial|inherit;
  • flex-basis 属性用于设置或检索弹性盒伸缩基准值,默认值auto
    语法: flex-basis: number|auto|initial|inherit;
  • flex 属性用于设置或检索弹性盒模型对象的子元素如何分配空间,是 flex-grow、flex-shrink 和 flex-basis 属性的简写属性。
    语法: flex: flex-grow flex-shrink flex-basis|auto|initial|inherit; 默认值flex: 0 1 auto,flex:auto = flex: 1 1 auto,flex:1 = flex:1 1 auto;
1)剩余高度填充

CSS3新特性详解(五):多列columns column-count和flex布局
剩余高度填充常见处理方式:

  • 固定元素:定义其高度,或设置flex-basis属性,如hd-4
  • 填充元素:设置flex:1
  • 需要解决内容溢出问题,如hd-4,bd-5,需要overflow:hidden;
2)剩余宽度填充

最常见恐怕莫过是form表单里的label+input框啦,前者固定宽度,后者填充剩余宽度,看个案例:
CSS3新特性详解(五):多列columns column-count和flex布局剩余宽度填充常见处理方式:

  • 固定元素:定义其宽度,或设置flex-basis属性,如label width统一设置为60px
  • 填充元素:设置flex:1,若flex:1的显示结果不是期望值,请在flex:1元素上添加overflow:hidden试试。
  • 可以铜鼓align-items,设置label垂直方向对齐方式,如“意见”垂直居中显示。
HTML / CSS 相关文章推荐
CSS伪类与CSS伪元素的区别及由来具体说明
Dec 07 HTML / CSS
html5+css3之CSS中的布局与Header的实现
Nov 21 HTML / CSS
基于CSS3实现图片模糊过滤效果
Nov 19 HTML / CSS
CSS3 3D旋转rotate效果实例介绍
May 03 HTML / CSS
利用CSS3实现折角效果实例源码
Sep 28 HTML / CSS
详解CSS3新增的背景属性
Dec 25 HTML / CSS
涂鸦板简单实现 Html5编写属于自己的画画板
Jul 05 HTML / CSS
网页中的电话号码如何实现一键直呼效果_附示例
Mar 15 HTML / CSS
基于html5实现的图片墙效果
Oct 16 HTML / CSS
canvas 实现 github404动态效果的示例代码
Nov 15 HTML / CSS
html5小程序飞入购物车(抛物线绘制运动轨迹点)
Oct 19 HTML / CSS
html解决浏览器记住密码输入框的问题
May 07 HTML / CSS
css position fixed 左右双定位的实现代码
Apr 29 #HTML / CSS
css3 利用transform-origin 实现圆点分布在大圆上布局及旋转特效
CSS3实现的侧滑菜单
CSS完成视差滚动效果
Html5通过数据流方式播放视频的实现
Apr 27 #HTML / CSS
CSS3实现的3D隧道效果
用CSS3画一个爱心
You might like
2020最新CPU的性能排名
2020/04/02 数码科技
php中常用编辑器推荐
2007/01/02 PHP
PHP中去除换行解决办法小结(PHP_EOL)
2011/11/27 PHP
php中base_convert()进制数字转换函数实例
2014/11/20 PHP
javascript 表格排序和表头浮动效果(扩展SortTable)
2009/04/07 Javascript
JS定义回车事件(实现代码)
2013/07/08 Javascript
枚举的实现求得1-1000所有出现1的数字并计算出现1的个数
2013/09/10 Javascript
JavaScript实现的经典文件树菜单效果
2015/09/08 Javascript
JavaScript基础篇(6)之函数表达式闭包
2015/12/11 Javascript
去除字符串左右两边的空格(实现代码)
2016/05/12 Javascript
JavaScript中常用的验证reg
2016/10/13 Javascript
jQuery实现多张图片上传预览(不经过后端处理)
2017/04/29 jQuery
详解Angular之constructor和ngOnInit差异及适用场景
2017/06/22 Javascript
浅谈jquery中ajax跨域提交的时候会有2次请求的问题
2017/11/10 jQuery
详解mpvue开发小程序小总结
2018/07/25 Javascript
vue瀑布流组件实现上拉加载更多
2020/03/10 Javascript
Javascript异步编程async实现过程详解
2020/04/02 Javascript
[02:41]辉夜杯现场一家三口 “我爸玩风行 我玩血魔”
2015/12/27 DOTA
在PyCharm环境中使用Jupyter Notebook的两种方法总结
2018/05/24 Python
Python中的 enum 模块源码详析
2019/01/09 Python
解决python3中的requests解析中文页面出现乱码问题
2019/04/19 Python
PyCharm-错误-找不到指定文件python.exe的解决方法
2019/07/01 Python
Python3.7 pyodbc完美配置访问access数据库
2019/10/03 Python
python 实现将list转成字符串,中间用空格隔开
2019/12/25 Python
Keras设置以及获取权重的实现
2020/06/19 Python
python能否java成为主流语言吗
2020/06/22 Python
Matplotlib中%matplotlib inline如何使用
2020/07/28 Python
Python列表推导式实现代码实例
2020/09/09 Python
Python通过fnmatch模块实现文件名匹配
2020/09/30 Python
aden + anais英国官网:美国婴儿贴身用品品牌
2019/09/08 全球购物
实习生体会的自我评价范文
2013/11/28 职场文书
结对共建协议书
2014/08/20 职场文书
我是特种兵观后感
2015/06/11 职场文书
公司车辆管理制度
2015/08/04 职场文书
详解Flutter网络请求Dio库的使用及封装
2022/04/14 Java/Android
Android 界面一键变灰 深色主题工具类
2022/04/28 Java/Android