CSS-块级布局
相关定义
自适应布局:一套代码,多设备自适应显示。
响应式布局:多套代码,不同设备尺寸范围布局方案不同。
布局样式
弹性盒
弹性盒子是一种用于按行或按列布局元素的一维布局方法 。元素可以膨胀以填充额外的空间, 收缩以适应更小的空间。
Flex 基本概念
Flex 用来为盒状模型提供最大的灵活性,弹性盒子。
采用 Flex 布局的元素,称为 Flex 容器,它的所有子元素自动成为容器成员。
容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start
,结束位置叫做main end
;交叉轴的开始位置叫做cross start
,结束位置叫做cross end
。
项目默认沿主轴排列。单个项目占据的主轴空间叫做main size
,占据的交叉轴空间叫做cross size
。
语法
display: flex; /* 将对象作为弹性伸缩盒显示 */
display: inline-flex; /* 将对象作为内联块级弹性伸缩盒显示 */
块级会默认 width = 100%,而内联样式需要指定 width,或者内容撑开 width。
父元素属性
flex-direction 主轴方向
决定主轴方向,即子元素排列方向。
.box {
flex-direction: row | row-reverse | column | column-reverse;
}
flex 默认横向。
row
(默认值):主轴为水平方向,起点在左端。row-reverse
:主轴为水平方向,起点在右端。column
:主轴为垂直方向,起点在上沿。column-reverse
:主轴为垂直方向,起点在下沿。
flex-wrap 换行
默认情况下,项目都排在一条线(又称”轴线”)上。flex-wrap
属性定义,如果一条轴线排不下,如何换行。
.box{
flex-wrap: nowrap | wrap | wrap-reverse;
}
nowrap
(默认值):不换行。wrap
:换行,第一行在上方。wrap-reverse
:换行,第一行在下方。
flex-flow 联合属性
flex-flow
属性是flex-direction
属性和flex-wrap
属性的简写形式,默认值为row nowrap
。
.box {
flex-flow: <flex-direction> || <flex-wrap>;
}
justify-content 主轴对齐方式
justify-content
属性定义了项目在主轴上的对齐方式。
.box {
justify-content: flex-start | flex-end | center | space-between | space-around;
}
默认主轴方向横向:
flex-start
(默认值):左对齐flex-end
:右对齐center
: 居中space-between
:两端对齐,项目之间的间隔都相等。space-around
:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
align-items 交叉轴上对齐方式
align-items
属性定义项目在交叉轴上如何对齐。
.box {
align-items: flex-start | flex-end | center | baseline | stretch;
}
默认交叉轴为纵轴:
flex-start
:交叉轴的起点对齐。flex-end
:交叉轴的终点对齐。center
:交叉轴的中点对齐。baseline
: 项目的第一行文字的基线对齐。stretch
(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
align-content 多根轴线对齐方式
.box {
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
一般换行才会有多根轴线情况出现:
flex-start
:与交叉轴的起点对齐。flex-end
:与交叉轴的终点对齐。center
:与交叉轴的中点对齐。space-between
:与交叉轴两端对齐,轴线之间的间隔平均分布。space-around
:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。stretch
(默认值):轴线占满整个交叉轴。
子元素属性
order 排列顺序
order
属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
.item {
order: <integer>;
}
flex-grow 放大比例
flex-grow
属性定义项目的放大比例,默认为0
,即如果存在剩余空间,也不放大。
.item {
flex-grow: <number>; /* default 0 */
}
如果所有项目的flex-grow
属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow
属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
flex-shrink 缩小比例
flex-shrink
属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
.item {
flex-shrink: <number>; /* default 1 */
}
设置为0时,不缩小。负值对该属性无效。
如果所有项目的flex-shrink
属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink
属性为0,其他项目都为1,则空间不足时,前者不缩小。
flex-basis 占主轴空间大小
flex-basis
属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto
,即项目的本来大小。
.item {
flex-basis: <length> | auto; /* default auto */
}
它可以设为跟width
或height
属性一样的值(比如350px),则项目将占据固定空间。
flex-basis 属性设置的 0 和 0%,表示的不一样,0% 的效果和 auto 的效果是一样的。
The issue is related to the usage of percentage. Using
0
or0px
is trivial since you will set the initial height to be0
and then the element will grow to fill the remaining space.Using
N%
is a different story because in this case you are setting the initial height to be based on the parent height.Percentages: relative to the flex container’s inner main size ref
In your case, the flex container doesn’t have any explicit size since your are using only a
min-height
definition so we cannot resolve the percentange value and it will fail toauto
flex 联合属性
flex
属性是flex-grow
, flex-shrink
和 flex-basis
的简写,默认值为0 1 auto
。后两个属性可选。
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
该属性有两个快捷值:auto
(1 1 auto
) 和 none
(0 0 auto
)。
建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
参考链接:
缩写语法:
单值语法 | 等同于 | 备注 |
---|---|---|
flex: initial | flex: 0 1 auto | 初始值,常用 |
flex: 0 | flex: 0 1 0% | 适用场景少 |
flex: none | flex: 0 0 auto | 推荐 |
flex: 1 | flex: 1 1 0% | 推荐 |
flex: auto | flex: 1 1 auto | 适用场景少 |
其中:
flex:0 1 0%
表示flex-grow
是0,flex-shrink
是1,因此元素尺寸会收缩但不会扩展,在加上flex-basis:0%
表示建议支持是0,因此,设置flex:0
的元素的最终尺寸表现为最小内容宽度;flex:0 0 auto
表示元素尺寸不会收缩也不会扩展,再加上flex-basis:auto
表示固定尺寸由内容决定,由于元素不具有弹性,因此,元素内的内容不会换行,最终尺寸通常表现为最大内容宽度。
需要注意单值语法会不会被 loader 插件进行转换,浏览器自动推算不生效。可能会出现和预想不一样的效果。
应用场景:
flex: none;
当flex子项的宽度就是内容的宽度,且内容永远不会换行,则适合使用flex:none
,这个场景比flex:0
适用的场景要更常见。flex:1
的尺寸表现更为内敛(优先牺牲自己的尺寸)。当希望元素充分利用剩余空间,同时不会侵占其他元素应有的宽度的时候,适合使用flex:1
,这样的场景在Flex布局中非常的多。不确定可分配到的空间,且子元素不会撑开父元素空间。flex: 1;
和flex: 1 1;
最后浏览器推算的是一样的。flex:auto
的尺寸表现则更为霸道(优先扩展自己的尺寸)。当希望元素充分利用剩余空间,但是各自的尺寸按照各自内容进行分配的时候,适合使用flex:auto
。flex:auto
多用于内容固定,或者内容可控的布局场景,
总结:
flex:initial
表示默认的flex状态,无需专门设置,适合小控件元素的分布布局,或者某一项内容动态变化的布局;flex:0
适用场景较少,适合设置在替换元素的父元素上;flex:none
适用于不换行的内容固定或者较少的小控件元素上,如按钮。flex:1
适合等分布局;flex:auto
适合基于内容动态适配的布局;
align-self 当前元素对齐方式
align-self
属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items
属性。默认值为auto
,表示继承父元素的align-items
属性,如果没有父元素,则等同于stretch
。
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
auto
(默认值):表示继承父元素的align-items
属性,如果没有父元素,则等同于stretch
。flex-start
:交叉轴的起点对齐。flex-end
:交叉轴的终点对齐。center
:交叉轴的中点对齐。baseline
: 项目的第一行文字的基线对齐。stretch
(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
参考链接
Flex 布局教程:语法篇 - 阮一峰: https://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
Flex 布局教程:实例篇 - 阮一峰:https://www.ruanyifeng.com/blog/2015/07/flex-examples.html
A Complete Guide to Flexbox : https://css-tricks.com/snippets/css/a-guide-to-flexbox/
网格
网格是一个用于web的二维布局系统。利用网格,你可以把内容按照行与列的格式进行排版。
Grid概念
网格布局,它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局。
行和列:网格布局有行和列的概念。
单元格:行和列的交叉区域。
网格线:划分网络的线。
与 Flex 的区别
Grid 布局与 Flex 布局有一定的相似性,都可以指定容器内部多个项目的位置。但是,它们也存在重大区别。
Flex 布局是轴线布局,只能指定”项目”针对轴线的位置,可以看作是一维布局。Grid 布局则是将容器划分成”行”和”列”,产生单元格,然后指定”项目所在”的单元格,可以看作是二维布局。Grid 布局远比 Flex 布局强大。
语法
.container {
display: grid | inline-grid;
}
grid
:块级元素inline-grid
:内联块级元素
父元素属性
grid-template-columns 列 & grid-template-rows 行
grid-template-columns
划分容器的列,定义每一列的列宽。
grid-template-rows
划分容器的行,定义每一列的行高。
none
关键字,所有的列和其大小都将由grid-auto-columns
属性隐式的指定。绝对单位
百分比
repeat()
函数,简化重复值。接受两个参数,重复的次数和重复的值。auto-fill
关键字,如果希望每一行(列)容纳尽可能多的单元格,这时可以使用auto-fill
关键字表示自动填充。fr
关键字,为了方便表示比例关系,网格布局提供了fr
关键字。如果两列的宽度分别为1fr
和2fr
,就表示后者是前者的两倍。fr
可以与绝对长度的单位结合使用,这时会非常方便。minmax()
函数产生一个长度范围,表示长度就在这个范围之中。它接受两个参数,分别为最小值和最大值。auto
关键字表示由浏览器自己决定长度。网格线名称,可以使用方括号指定网格线的名称,方便以后引用。网格线可以拥有多个名字。
/* Keyword value 这个关键字表示不明确的网格。所有的列和其大小都将由 grid-auto-columns 属性隐式的指定。 */
grid-template-columns: none;
/* <track-list> values */
grid-template-columns: 100px 1fr;
grid-template-columns: [linename] 100px;
grid-template-columns: [linename1] 100px [linename2 linename3];
grid-template-columns: minmax(100px, 1fr);
grid-template-columns: fit-content(40%);
grid-template-columns: repeat(3, 200px);
/* <auto-track-list> values */
grid-template-columns: 200px repeat(auto-fill, 100px) 300px;
grid-template-columns: minmax(100px, max-content)
repeat(auto-fill, 200px) 20%;
grid-template-columns: [linename1] 100px [linename2]
repeat(auto-fit, [linename3 linename4] 300px)
100px;
grid-template-columns: [linename1 linename2] 100px
repeat(auto-fit, [linename1] 300px) [linename3];
/* Global values */
grid-template-columns: inherit;
grid-template-columns: initial;
grid-template-columns: unset;
grid-template-areas 区域
网格布局允许指定”区域”(area),一个区域由单个或多个单元格组成。
网格区块(grid areas)和网格项(grid item)沒有关联,但是它们可以和一些网格定位属性(grid-placement properties)关联起来
grid-template-areas
属性用于定义区域。
- none:网格容器没有定义任何的网格区块(grid areas)。
- string+:每一个给定的字符串会生成一行,一个字符串中用空格分隔的每一个单元(cell)会生成一列。多个同名的,跨越相邻行或列的单元称为网格区块(grid area)。非矩形的网格区块是无效的。string 可以是 grid-area-name。
CSS 类中设置 grid-area-name。如:(grid-area也可为子元素指定区域)
.a { grid-area: a }
/* Keyword value */
grid-template-areas: none;
/* <string> values */
grid-template-areas: "a b"; /* 一行 两列 */
grid-template-areas: "a b b"
"a c d"; /* 两行 三列 */
grid-template-areas: "a a ." /* .表示空的表格 */
"a a ."
". b c";
/* Global values */
grid-template-areas: inherit; /* 继承 */
grid-template-areas: initial; /* 默认值 */
grid-template-areas: unset; /* 未设置 */
注意,区域的命名会影响到网格线。每个区域的起始网格线,会自动命名为
区域名-start
,终止网格线自动命名为区域名-end
。比如,区域名为
header
,则起始位置的水平网格线和垂直网格线叫做header-start
,终止位置的水平网格线和垂直网格线叫做header-end
。
grid-template 联合属性
grid-template
,CSS属性简写,用以定义网格中rows、columns与areas。
/* 值为关键词 */
grid-template: none;
/* 为 grid-template-rows / grid-template-columns */
grid-template: 100px 1fr / 50px 1fr;
grid-template: auto 1fr / auto 1fr auto;
grid-template: [linename] 100px / [columnname1] 30% [columnname2] 70%;
grid-template: fit-content(100px) / fit-content(40%);
/* 为 grid-template-areas grid-template-rows / grid-template-column */
grid-template: "a a a"
"b b b";
grid-template: "a a a" 20%
"b b b" auto;
grid-template: [header-top] "a a a" [header-bottom]
[main-top] "b b b" 1fr [main-bottom]
/ auto 1fr auto;
/* 为全局值 */
grid-template: inherit;
grid-template: initial;
grid-template: unset;
row-gap 行间距 & column-gap 列间距 & gap 联合间距
row-gap
属性设置行与行的间隔(行间距)。
column-gap
属性设置列与列的间隔(列间距)。
gap
属性是row-gap
和column-gap
的合并简写形式。
.container {
row-gap: 20px;
column-gap: 20px;
}
.container {
gap: 20px 20px; /* <row-gap> <column-gap> */
}
.container {
gap: 20px; /* <row-gap> = <column-gap> */
}
grid-auto-flow 子元素顺序
划分网格以后,容器的子元素会按照顺序,自动放置在每一个网格。默认的放置顺序是”先行后列”,即先填满第一行,再开始放入第二行,即下图数字的顺序。
row
(默认值):先行后列column
:先列后行dense
:剩下的位置如何摆放。“稠密”堆积算法,如果后面出现了稍小的元素,则会试图去填充网格中前面留下的空白。这样做会填上稍大元素留下的空白,但同时也可能导致原来出现的次序被打乱。如果省略它,使用一种「稀疏」算法,在网格中布局元素时,布局算法只会「向前」移动,永远不会倒回去填补空白。这保证了所有自动布局元素「按照次序」出现,即使可能会留下被后面元素填充的空白。
/* Keyword values */
grid-auto-flow: row;
grid-auto-flow: column;
grid-auto-flow: dense;
grid-auto-flow: row dense;
grid-auto-flow: column dense;
/* Global values */
grid-auto-flow: inherit;
grid-auto-flow: initial;
grid-auto-flow: unset;
justify-items 单元格内水平位置 & align-items 单元格内垂直位置 & place-items 联合属性
justify-items
属性设置单元格内容的水平位置(左中右)。
align-items
属性设置单元格内容的垂直位置(上中下)。
place-item
属性是align-items
属性和justify-items
属性的合并简写形式。
- start:对齐单元格的起始边缘。
- end:对齐单元格的结束边缘。
- center:单元格内部居中。
- stretch:拉伸,占满单元格的整个宽度(默认值)。
.container {
justify-items: start;
align-items: start;
}
.container {
place-items: start start; /* <align-items>, <justify-items> */
}
.container {
place-items: start; /* <align-items> = <justify-items> */
}
justify-content 整体内容水平位置 & align-content 整体内容垂直位置 & place-content 联合属性
justify-content
属性是整个内容区域在容器里面的水平位置(左中右)。
align-content
属性是整个内容区域的垂直位置(上中下)。
place-content
属性是align-content
属性和justify-content
属性的合并简写形式。
- start: 对齐容器的起始边框。
- end :对齐容器的结束边框。
- center: 容器内部居中。
- stretch: 项目大小没有指定时,拉伸占据整个网格容器。
- space-around: 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍。
- space-between: 项目与项目的间隔相等,项目与容器边框之间没有间隔。
- space-evenly: 项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔。
grid-auto-columns 自动创建列 & grid-auto-rows 自动创建行
grid-auto-columns
指定了隐式创建的网格纵向轨道(track)的宽度。
grid-auto-rows
用于指定隐式创建的行轨道大小。
有时候,一些项目的指定位置,在现有网格的外部。比如网格只有3列,但是某一个项目指定在第5行。这时,浏览器会自动生成多余的网格,以便放置项目。
grid-auto-columns
属性和grid-auto-rows
属性用来设置,浏览器自动创建的多余网格的列宽和行高。它们的写法与grid-template-columns
和grid-template-rows
完全相同。如果不指定这两个属性,浏览器完全根据单元格内容的大小,决定新增网格的列宽和行高。
.container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-auto-rows: 50px;
}
划分好的网格是3行 x 3列,但是,8号项目指定在第4行,9号项目指定在第5行。
grid 合并属性
grid
属性是grid-template-rows
、grid-template-columns
、grid-template-areas
、 grid-auto-rows
、grid-auto-columns
、grid-auto-flow
这六个属性的合并简写形式。
/* <'grid-template'> values */
grid: none;
grid: "a" 100px "b" 1fr;
grid: [linename1] "a" 100px [linename2];
grid: "a" 200px "b" min-content;
grid: "a" minmax(100px, max-content) "b" 20%;
grid: 100px / 200px;
grid: minmax(400px, min-content) / repeat(auto-fill, 50px);
/* <'grid-template-rows'> /
[ auto-flow && dense? ] <'grid-auto-columns'>? values */
grid: 200px / auto-flow;
grid: 30% / auto-flow dense;
grid: repeat(3, [line1 line2 line3] 200px) / auto-flow 300px;
grid: [line1] minmax(20em, max-content) / auto-flow dense 40%;
/* [ auto-flow && dense? ] <'grid-auto-rows'>? /
<'grid-template-columns'> values */
grid: auto-flow / 200px;
grid: auto-flow dense / 30%;
grid: auto-flow 300px / repeat(3, [line1 line2 line3] 200px);
grid: auto-flow dense 40% / [line1] minmax(20em, max-content);
/* Global values */
grid: inherit;
grid: initial;
grid: unset;
子元素属性
gird-column-start & grid-column-end & grid-row-start & grid-row-end 指定边框
项目的位置是可以指定的,具体方法就是指定项目的四个边框,分别定位在哪根网格线。
grid-column-start
属性:左边框所在的垂直网格线grid-column-end
属性:右边框所在的垂直网格线grid-row-start
属性:上边框所在的水平网格线grid-row-end
属性:下边框所在的水平网格线
值为网格线序列号或者网格线名称。
使用span
关键字,表示”跨越”,即左右边框(上下边框)之间跨越多少个网格。
使用这四个属性,如果产生了项目的重叠,则使用z-index
属性指定项目的重叠顺序。
grid-column & grid-row 边框合并属性
grid-column
属性是grid-column-start
和grid-column-end
的合并简写形式。
grid-row
属性是grid-row-start
属性和grid-row-end
的合并简写形式。
.item {
grid-column: <start-line> / <end-line>;
grid-row: <start-line> / <end-line>;
}
.item-1 {
grid-column: 1 / 3;
grid-row: 1 / 2;
}
/* 等同于 */
.item-1 {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 2;
}
grid-area 指定区域
grid-area
属性指定项目放在哪一个区域。值可以为指定的 grid-area-name
grid-area
是一种对于 grid-row-start
(en-US)、grid-column-start
(en-US)、grid-row-end
(en-US) 和 grid-column-end
(en-US) 的简写,通过基线(line),跨度(span)或没有(自动)的网格放置在 grid row 中指定一个网格项的大小和位置,继而确定 grid area 的边界。
/* Keyword values */
grid-area: auto;
grid-area: auto / auto;
grid-area: auto / auto / auto;
grid-area: auto / auto / auto / auto;
/* <custom-ident> values */
grid-area: some-grid-area;
grid-area: some-grid-area / another-grid-area;
/* <integer> && <custom-ident>? values */
grid-area: some-grid-area 4;
grid-area: some-grid-area 4 / 2 another-grid-area;
/* span && [ <integer> || <custom-ident> ] values */
grid-area: span 3;
grid-area: span 3 / span some-grid-area;
grid-area: 2 span / another-grid-area span;
/* Global values */
grid-area: inherit;
grid-area: initial;
grid-area: unset;
justify-self 单元格内容水平位置 & align-self 单元格内容的垂直位置 & place-self 联合属性
justify-self
属性设置单元格内容的水平位置(左中右),跟justify-items
属性的用法完全一致,但只作用于单个项目。
align-self
属性设置单元格内容的垂直位置(上中下),跟align-items
属性的用法完全一致,也是只作用于单个项目。
place-self
属性是align-self
属性和justify-self
属性的合并简写形式。
- start:对齐单元格的起始边缘。
- end:对齐单元格的结束边缘。
- center:单元格内部居中。
- stretch:拉伸,占满单元格的整个宽度(默认值)。
.item-1 {
justify-self: start;
align-self: start;
}
.item-1 {
place-self: start start; /* <align-self> <justify-self> */
}
.item-1 {
place-self: start; /* <align-self> = <justify-self> */
}
参考链接
A Complete Guide to Grid - CSS Tricks
更多阅读
格式上下文
BFC - 块级格式上下文
Block formatting contexts
具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。
触发BFC
- body 根元素
- 浮动元素:float 除 none 以外的值
- 绝对定位元素:position (absolute、fixed)
- display 为 inline-block、table-cells、flex、table-caption
- overflow 除了 visible 以外的值 (hidden、auto、scroll)
应用
- BFC 可以包含浮动的元素(清除浮动)
- BFC 可以阻止元素被浮动元素覆盖
IFC - 内联格式上下文
IFC(Inline formatting contexts) 的线框高度由其包含行内元素中最高的实际高度计算而来,不受到竖直方向的 padding / margin 影响。
IFC 中的 line box 一般左右都贴紧整个 IFC,但是会因为 float 元素而扰乱。
float 元素会位于 IFC 与 line box 之间,使得 line box 宽度缩短。
同个 IFC 下的多个 line box 高度会不同。
IFC 中不能有块级元素,当插入块级元素时(如 p 中插入 div)会产生两个匿名块与 div 分隔开,即产生两个 IFC,每个 IFC 对外表现为块级元素,与 div 垂直排列。
应用
水平居中:当一个块要在环境中水平居中时,设置其为 inline-block 则会在外层产生 IFC,通过 text-align 则可以使其水平居中。
垂直居中:创建一个 IFC,用其中一个元素撑开父元素的高度,然后设置其 vertical-align: middle,其他行内元素则可以在此父元素中垂直居中。
GFC - 网格布局格式化上下文
GrideLayout formatting contexts
触发条件
设置 display 值为 grid。
FFC - 自适应格式上下文
Flex formatting contexts
触发条件
display 值为 flex 或者 inline-flex 的元素将会生成自适应容器(flex container)。
通过设置元素的 display 属性为 flex 或 inline-flex 可以得到一个伸缩容器。
设置为 flex 的容器被渲染为一个块级元素,而设置为 inline-flex 的容器则渲染为一个行内元素。
伸缩容器中的每一个子元素都是一个伸缩项目。伸缩项目可以是任意数量的。伸缩容器外和伸缩项目内的一切元素都不受影响。
实践
flex:
聊天界面
瀑布流
grid:
- 等分响应式
- 固定列宽,改变列数量
- 去掉右侧空白
- 补全空缺