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 相关文章推荐
CSS3弹性盒模型flex box快速入门心得(必看篇)
May 24 HTML / CSS
CSS的background属性及CSS3的背景图片设置总结
Jun 13 HTML / CSS
CSS3,线性渐变(linear-gradient)的使用总结
Jan 09 HTML / CSS
css3实现wifi信号逐渐增强效果实例
Aug 09 HTML / CSS
HTML5中的nav标签学习笔记
Jun 24 HTML / CSS
html5 Canvas画图教程(7)—canvas里画曲线之quadraticCurveTo方法
Jan 09 HTML / CSS
实例讲解利用HTML5 Canvas API操作图形旋转的方法
Mar 22 HTML / CSS
html5简介_动力节点Java学院整理
Jul 07 HTML / CSS
教你使用Canvas处理图片的方法
Nov 28 HTML / CSS
canvas实现二维码和图片合成的示例代码
Aug 01 HTML / CSS
HTML5 video 上传预览图片视频如何设置、预览视频某秒的海报帧
Aug 28 HTML / CSS
css3应用示例:新增的选择器
Mar 16 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
PHP添加图片水印、压缩、剪切的封装类
2015/08/17 PHP
PHP实现接收二进制流转换成图片的方法
2017/01/10 PHP
PHP共享内存使用与信号控制实例分析
2018/05/09 PHP
PHP模版引擎原理、定义与用法实例
2019/03/29 PHP
php无限极分类实现方法分析
2019/07/04 PHP
javascript中的document.open()方法使用介绍
2013/10/09 Javascript
node中socket.io的事件使用详解
2014/12/15 Javascript
详解JavaScript中的客户端消息框架设计原理
2015/06/24 Javascript
详解Angularjs 如何自定义Img的ng-load 事件
2017/02/15 Javascript
解决jQuery ajax动态新增节点无法触发点击事件的问题
2017/05/24 jQuery
Express + Session 实现登录验证功能
2017/09/08 Javascript
浅谈在Vue-cli里基于axios封装复用请求
2017/11/06 Javascript
VUE element-ui 写个复用Table组件的示例代码
2017/11/18 Javascript
对vux点击事件的优化详解
2018/08/28 Javascript
详解json串反转义(消除反斜杠)
2019/08/12 Javascript
小程序实现多个选项卡切换
2020/06/19 Javascript
解决elementui表格操作列自适应列宽
2020/12/28 Javascript
Python基于有道实现英汉字典功能
2015/07/25 Python
Python作用域用法实例详解
2016/03/15 Python
Python制作刷网页流量工具
2017/04/23 Python
python+matplotlib实现鼠标移动三角形高亮及索引显示
2018/01/15 Python
widows下安装pycurl并利用pycurl请求https地址的方法
2018/10/15 Python
Python数据类型之Tuple元组实例详解
2019/05/08 Python
基于Python的Post请求数据爬取的方法详解
2019/06/14 Python
python将类似json的数据存储到MySQL中的实例
2019/07/12 Python
Python实现二叉树的最小深度的两种方法
2019/09/30 Python
TensorFlow2.X使用图片制作简单的数据集训练模型
2020/04/08 Python
python 获取字典键值对的实现
2020/11/12 Python
美国儿童珠宝在线零售商:Loveivy
2019/05/22 全球购物
WEB控件及HTML服务端控件能否调用客户端方法?如果能,请解释如何调用?
2015/08/25 面试题
面试后的英文感谢信
2014/02/01 职场文书
空中乘务员岗位职责
2014/03/08 职场文书
可口可乐广告词
2014/03/20 职场文书
详解Python 3.10 中的新功能和变化
2021/04/28 Python
Python进程间的通信之语法学习
2022/04/11 Python
Python使用BeautifulSoup4修改网页内容
2022/05/20 Python