简单来说Html Dom元素就2类:行内元素和块级元素,前者在行内显示(span等),后者换行显示(div等)。所谓布局,比如早期的4大布局:块布局、行内布局、表格布局、定位布局,多半解决的是块级元素行内显示问题。我们可以看下块级元素行内显示的常见方式:
基于此,基本上早期的页面都是表格布局,后来逐渐被div+css替代,现在呢?
除此之外,display:table-cell也有很多粉丝,其表现基本上同td,俗称不是表格的表格。早期块级元素行内显示有2个难点:
随着CSS3引入多列column-count和flex布局,块级元素行内显示问题,我们有了更多地选择,同时也可以比较优雅地解决垂直居中和宽度、高度自适应问题。接下来,本文将先简单介绍下display:table-cell的使用,然后重点讲解多列column-count和flex布局。
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: cell1div>
<div class="table-cell cell2" style="width: 100%;">table-cell: cell2div>
<div class="table-cell cell3" style="width: 200px;">table-cell: cell3div>
div>
div>
<div class="table">
<div class="table-cell cell1" style="width: 200px;">table-cell: cell1div>
<div class="table-cell cell2" style="width: 100%;">table-cell: cell2, 没有table-row元素div>
<div class="table-cell cell3" style="width: 200px;">table-cell: cell3div>
div>
从上述案例可以看出,有无< div class=“table-row”>元素,效果一样,原因是:浏览器会自动创建一个表格匿名行,另外:
除此之外,display: table-cell还有一个妙用:元素等高对齐或者说高度跟随
.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: cell1div>
<div class="table-cell cell2" style="width: 100%;">table-cell: cell2, 把cell3的高度设置成80px,cell1和cell2的高度也变成了80pxdiv>
<div class="table-cell cell3" style="width: 200px;">table-cell: cell3div>
div>
说明: cell3设置了高度80px,cell1和cell2高度跟随cell3变成了80px
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">col1div>
<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)/3div>
div>
<div class="columns columns-width" style="column-width:200px;">
<div class="col col1">col1div>
<div class="col col2">column-width:200pxdiv>
<div class="col col3">col3div>
div>
<div class="columns columns-width" style="column-width:300px;">
<div class="col col1">col1div>
<div class="col col2">column-width:300pxdiv>
<div class="col col3">col3div>
div>
- 同时设置了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;
CSS3 弹性盒子( Flexible Box 或 flexbox),是一种当页面需要适应不同的屏幕大小以及设备类型时确保元素拥有恰当的行为的布局方式,并且x轴和y轴(或flex主轴、辅轴)都适用,flex布局是微信小程序页面布局首选。flex布局规范、语法说明,大家参考下述2篇,讲解的比较透彻、形象。
本文以flex实际案例为主,于案例间讲解flex相关属性使用说明及注意事项。
.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'>1span>div>td>
<td><div class='box' style="justify-content:center"><span class='point'>2span>div>td>
<td><div class='box' style="justify-content:flex-end"><span class='point'>3span>div>td>
<td><div class='box' style="align-items:center"><span class='point'>4span>div>td>
<td><div class='box' style="justify-content:center;align-items:center"><span class='point'>5span>div>td>
<td><div class='box' style="justify-content:center;align-items:flex-end"><span class='point'>8span>div>td>
<td><div class='box' style="justify-content:flex-end;align-items:flex-end"><span class='point'>9span>div>td>
tr>
<tr>
<td>td>
<td>justify-content:centertd>
<td>justify-content:flex-endtd>
<td>align-items:centertd>
<td>justify-content:center;<br>align-items:centertd>
<td>justify-content:center;<br>align-items:flex-endtd>
<td>justify-content:flex-end;<br>align-items:flex-endtd>
tr>
table>
语法: -content: flex-start | flex-end | center | space-between | space-around
说明: flex-direction = row|row-reverse的话,主轴为x轴,默认值flex-start,各个值说明如下:
语法: align-items: flex-start | flex-end | center | baseline | stretch
说明: flex-direction = row|row-reverse的话,辅轴为y轴,默认值stretch;以y轴为辅轴为例,各个值说明如下:
上个案例主要说明在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:centertd>
<td>flex-col<br>justify-content:space-between;<br>align-items:centertd>
<td>flex-row<br>p2 align-self:center<br>p3 align-self:flex-endtd>
<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:centertd>
tr>
table>
align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
语法: align-self: auto | flex-start | flex-end | center | baseline | stretch
说明: 除auto值外,其它值同align-items参数值。
案例中,骰子4点,5点,6点使用了flex嵌套,先是flex-direction: column布局,然后每行又是flex-direction: row布局;
通过class统一设置flex布局,flex-col class,flex布局,主轴为y轴;flex-row class,flex布局,主轴为x轴。flex布局里的item元素,用内敛style具体实现。
剩余高度、宽度填充需要使用到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;
最常见恐怕莫过是form表单里的label+input框啦,前者固定宽度,后者填充剩余宽度,看个案例:
剩余宽度填充常见处理方式: