常见 CSS 布局
水平垂直居中
/* 公共代码 */ <div class="wp"><div class="box size">123123</div> </div>居中元素定宽高
absolute + 负 margin
.wp {border: 1px solid red;width: 300px;height: 300px;position: relative; } .box {background: green; width: 100px;height: 100px;position: absolute;top: 50%;left: 50%;margin-left: -50px;margin-top: -50px; }absolute + margin auto
.wp {border: 1px solid red;width: 300px;height: 300px;position: relative; } .box {background: green; width: 100px;height: 100px;position: absolute;top: 0;left: 0;bottom: 0;right: 0;margin: auto; }absolute + calc
.wp {border: 1px solid red;width: 300px;height: 300px;position: relative; } .box {background: green; width: 100px;height: 100px;position: absolute;top: calc(50% - 50px);left: calc(50% - 50px); }居中元素不定宽高
absolute + transform
.wp {border: 1px solid red;width: 300px;height: 300px;position: relative; } .box {background: green; position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%); }line-height + height
.wp {border: 1px solid red;width: 300px;height: 300px;line-height: 300px; /*行高的值与height相等*/text-align: center;font-size: 0; /*消除幽灵空白节点、近似居中的bug*/ } .box {background: green; display: inline-block; /*如果是块级元素需改为行内或行内块级才生效*/vertical-align: middle;font-size: 16px;line-height: initial; /*默认值*/text-align: left; /*修正文字*/ }inline-block
.wp {border: 1px solid red;width: 300px;height: 300px;position: relative;display: inline-block;white-space: nowrap;text-align: center; } .wp::after { content:''; display: inline-block; vertical-align: middle; height: 100%; } .box {background: green; display: inline-block; /*如果是块级元素需改为行内或行内块级才生效*/vertical-align: middle; }table
tabel 单元格中的内容天然就是垂直居中的,需添加一个水平居中属性即可,该方法代码太冗余
table-cell: CSS 新增的 table 属性,可把普通元素变为 table 元素的现实效果,该方法和table一样原理,但没有那么多冗余代码,兼容性也还不错
.wp {display: table-cell;vertical-align: middle;text-align: center;border: 1px solid red;width: 300px;height: 300px; } .box {background: green; display: inline-block; }flex: 注意兼容性
.wp {display: flex;justify-content: center;align-items: center;border: 1px solid red;width: 300px;height: 300px; } .box {background: green; }grid: 网格布局,代码量也很少,但兼容性不如 flex
.wp {display: grid;border: 1px solid red;width: 300px;height: 300px; } .box {background: green; align-self: center;justify-self: center; }writing-mode: 可以改变文字的显示方向,如可通过 writing-mode 让文字的显示变为垂直方向,结合 text-align 可实现
<div class="wp"><div class="wp-inner"><div class="box">123123</div></div> </div>wp {writing-mode: vertical-lr;text-align: center;border: 1px solid red;width: 300px;height: 300px; } .wp-inner {writing-mode: horizontal-tb;display: inline-block;width: 100%; } .box {background: green; display: inline-block; }两列布局
左列定宽,右列自适应
float + margin
<div class="left">左列定宽</div> <div class="right">右列自适应</div>.left {background-color: red;float: left;width: 100px;height: 500px; } .right {background-color: yellow;height: 500px;margin-left: 100px; /*大于等于 left 的宽度*/ }float + margin(fix)
<div class="left">左列定宽</div> <div class="right-fix"><div class="right">右列自适应</div> </div>.left {background-color: red;float: left;width: 100px;height: 500px; } .right-fix {float: right;width: 100%;margin-left: -100px; /*正值大于或等于 left 的宽度,才能显示在同一行*/ } .right {background-color: yellow;height: 500px;margin-left: 100px; /*大于等于 left 的宽度*/ }float + overflow
优点:代码简单,容易理解,无需关注定宽的宽度,利用 bfc 达到自适应效果
缺点:浮动脱离文档流,需要手动清除浮动,否则容易产生高度塌陷;不支持ie6
绝对定位
<div class="parent"><div class="left">左列定宽</div><div class="right">右列自适应</div> </div>.parent {position: relative; /*子绝父相*/ } .left {background-color: red;position: absolute;top: 0;left: 0;width: 100px;height: 500px; } .right {background-color: yellow;height: 500px;position: absolute;top: 0;left: 100px; /*值大于等于 left 的宽度*/right: 0; }flex
<div class="parent"><div class="left">左列定宽</div><div class="right">右列自适应</div> </div>.parent {width: 100%;height: 500px;display: flex; } .left {width: 100px;background-color: red; } .right {background-color: yellow;flex: 1; /*均分了父元素剩余空间*/ }table
优点:代码简单,容易理解,无需关注定宽的宽度,利用单元格自动分配达到自适应效果
缺点:margin失效;设置间隔比较麻烦;不支持ie8-
Grid
<div class="parent"><div class="left">左列定宽</div><div class="right">右列自适应</div> </div>.parent {width: 100%;height: 500px;display: grid;grid-template-columns: 100px auto; /*设定 2 列就 ok 了,auto 换成 1fr 也行*/ } .left {background-color: red; } .right {background-color: yellow; }左列自适应,右列定宽
float + margin
<div class="parent"><div class="left">左列自适应</div><div class="right">右列定宽</div> </div>.parent {padding-left: 100px; /*抵消 left 的 margin-left 以达到 parent 水平居中*/ } .left {width: 100%;height: 500px;float: left;margin-left: -100px; /*正值等于 right 的宽度*/background-color: #f00; } .right {height: 500px;width: 100px;float: right;background-color: #0f0; }float + overflow
<div class="parent"><div class="right">右列定宽</div><div class="left">左列自适应</div> <!--顺序要换一下--> </div>.left {background-color: #f00;overflow: hidden; /*触发bfc*/height: 500px; } .right {height: 500px;width: 100px;float: right;background-color: #0f0; }其他的方法如绝对定位、flex、table、grid 与【左列定宽右列自适应】相反
一列不定宽,一列自适应(盒子宽度随着内容增加或减少发生变化,另一个盒子自适应)
改变前
改变后
float + overflow
<div class="parent"><div class="left">左列不定宽</div><div class="right">右列自适应</div> </div>.left {margin-right: 10px;float: left; /*只设置浮动,不设宽度*/height: 500px;background-color: #f00; } .right {overflow: hidden; /*触发 bfc */height: 500px;background-color: #0f0; }flex
<div class="parent"><div class="left">左列不定宽</div><div class="right">右列自适应</div> </div>.parent{display: flex; } .left { /*不设宽度*/margin-right: 10px;height: 500px;background-color: #f00; } .right {height: 500px;background-color: #0f0;flex: 1; /*均分 parent 剩余的部分*/ }Grid
<div class="parent"><div class="left">左列不定宽</div><div class="right">右列自适应</div> </div>.parent{display: grid;grid-template-columns: auto 1fr; /* auto 和 1fr 换一下顺序就是左列自适应,右列不定宽了*/ } .left {margin-right: 10px;height: 500px;background-color: red; } .right {height: 500px; }三列布局
两列定宽,一列自适应
float + margin
<div class="parent"><div class="left">左列定宽</div><div class="center">中间定宽</div><div class="right">右列自适应</div> </div>.parent {min-width: 310px; /* 100+10+200,防止宽度不够,子元素换行*/ } .left {margin-right: 10px; /* left 和 center 间隔*/float: left;width: 100px;height: 500px;background-color: red; } .center {float: left;width: 200px;height: 500px;background-color: green; } .right {margin-left: 320px; /*等于 left 和 center 的宽度之和加上间隔,多出来的就是 right 和 center 的间隔*/height: 500px;background-color: #0f0; }float + overflow
<div class="parent"><div class="left">左列定宽</div><div class="center">中间定宽</div><div class="right">右列自适应</div> </div>.parent{min-width: 320px; /* 100+10+200+10,防止宽度不够,子元素换行*/ } .left {margin-right: 10px; /* left 和 center 间隔*/float: left;width: 100px;height: 500px;background-color: red; } .center {float: left;width: 200px;height: 500px;background-color: green;margin-right: 10px; /*在此定义和 right 的间隔*/ } .right {overflow: hidden; /*触发 bfc*/height: 500px;background-color: yellow; }flex
<div class="parent"><div class="left">左列定宽</div><div class="center">中间定宽</div><div class="right">右列自适应</div> </div>.parent{height: 500px;display: flex; } .left {margin-right: 10px; /* left 和 center 间隔*/width: 100px;background-color: red; } .center {width: 200px;background-color: green;margin-right: 10px; /*在此定义和 right 的间隔*/ } .right { flex: 1; /*均分 parent 剩余的部分达到自适应*/background-color: yellow; }table
<div class="parent"><div class="left">左列定宽</div><div class="center">中间定宽</div><div class="right">右列自适应</div> </div>.parent{width: 100%; display: table;height: 520px; /*抵消上下间距 10*2 的高度影响*/margin: -10px 0; /*抵消上下间距 10 的位置影响*//*左右两边间距大了一点,子元素改用 padding 设置盒子间距就没有这个问题*/border-spacing: 10px; /*以下子元素 margin 设置间距失效,关键!!!设置间距*/ } .left {display: table-cell;width: 100px;background-color: red; } .center {width: 200px;background-color: green;display: table-cell; } .right { display: table-cell;background-color: yellow; }Grid
<div class="parent"><div class="left">左列定宽</div><div class="center">中间定宽</div><div class="right">右列自适应</div> </div>.parent{height: 500px;display: grid;grid-template-columns: 100px 200px auto; /*设置 3 列,固定第一第二列的宽度,第三列 auto 或者 1fr*/ } .left {margin-right: 10px; /*间距*/background-color: red; } .center {margin-right: 10px; /*间距*/background-color: green; } .right { background-color: yellow; }两侧定宽,中间自适应
** 圣杯布局**
利用浮动和相对定位实现
缺点:圣杯布局会有个问题,当将浏览器宽度缩短到一定程度时会使得中间子元素的宽度比左右子元素宽度小,这时布局就会出现问题,所以在使用圣杯布局时一定要设置整个容器的最小宽度
双飞翼布局
为了解决圣杯布局的弊端,实现中间部分自适应时多嵌套了一个 div 且不再使用相对定位
<div class="header">header</div> <div class="parent"><!--#center需要放在前面--><div class="center"><div class="center_inner">中间自适应</div><hr> <!--方便观察原理--></div><div class="left">左列定宽</div><div class="right">右列定宽</div> </div> <div class="footer">footer</div>.header, .footer {height: 60px;background-color: #ccc; }.parent, .parent div {height: 300px }.left, .center, .right {float: left; }.left {margin-left: -100%; /*使 left 上去一行*/background-color: red;width: 100px; }.center {width: 100%;border: 1px solid #000;background-color: yellow; }.center_inner {height: 280px;border: 1px solid #000;margin: 0 220px 0 120px; /*关键!!!左右边界等于左右盒子的宽度,多出来的为盒子间隔*/ }.right {width: 200px;margin-left: -200px; /*使 right 上去一行*/background-color: green; }flex
flex: flex-grow | flex-shrink | flex-basis; 分别为:空间充足放大比,空间不足缩小比以及计算剩余空间之前的宽度值
<div class="parent"><div class="left">左列定宽</div><div class="center">中间自适应</div><div class="right">右列定宽</div> </div>.parent {display: flex; }.parent div {height: 300px; }.left, .right {width: 200px; /* flex: 0 0 200px; */ }.left {background-color: red; }.center {flex: 1;background-color: yellow; }.right {background-color: green; }position
优点:容易理解,兼容性比较好
缺点:需手动计算宽度确定边距;脱离文档流;代码繁多
table
优点:代码简洁,容易理解;
缺点:margin失效,采用border-spacing表格两边的间隔无法消除;不支持ie8-
Grid
Grid 是微软提出的网页布局解决方案,最新的 Safari、Chrome、Firefox 都已经进行了支持。个人感觉 Grid 布局比 flex 布局更强大一些,宽高两个方向上都可以得到控制且 Grid 也更容易理解(但 Grid 在移动端的支持应该没有 flex 强)
<div class="parent"><div class="left">左列定宽</div><div class="center">中间自适应</div><div class="right">右列定宽</div> </div>.parent {display: grid;grid-template-columns: 200px auto 200px;grid-template-rows: 100px }.left {background-color: red; }.center {background-color: yellow; }.right {background-color: green; } <div class="parent"><div class="header"></div><div class="left">左列定宽</div><div class="center">中间自适应<hr /></div><div class="right">右列定宽</div><div class="footer"></div> </div>.parent {height: 500px;display: grid;grid-template-columns: 100px auto 200px; /*设定3列*/grid-template-rows: 60px auto 60px; /*设定3行*//*设置网格区域分布*/grid-template-areas:"header header header""leftside main rightside""footer footer footer"; }.header,.footer {background-color: #ccc; }.header {grid-area: header; /*指定在哪个网格区域*/ }.left {grid-area: leftside;background-color: red; }.center {grid-area: main; /*指定在哪个网格区域*/margin: 0 15px; /*设置间隔*/border: 1px solid #000;background-color: yellow; }.right {grid-area: rightside; /*指定在哪个网格区域*/background-color: green; }.footer {grid-area: footer; /*指定在哪个网格区域*/ }**CSS3 的 calc **
CSS3 提供的 calc 功能能够实现给宽高等设置动态的值,支持 + - * / 四则运算,注意运算符两边要个留一个空格否则设置无效
同样需要设置浮动将三个元素并排显示
多列布局
多列等宽布局
float
优点:代码简单,容易理解;兼容性较好
缺点:需要手动清除浮动,否则会容易产生高度塌陷
flex
<div class="parent"><div class="column">等宽等宽等宽等宽等宽等宽等宽等宽等宽等宽</div><div class="column">等宽等宽等宽等宽等宽等宽等宽等宽等宽等宽</div><div class="column">等宽等宽等宽等宽等宽等宽等宽等宽等宽等宽</div><div class="column">等宽等宽等宽等宽等宽等宽等宽等宽等宽等宽</div> </div>.parent {margin-left: -15px; /*使内容看起来居中*/height: 500px;display: flex; }.column {flex: 1; /*一起平分 parent*/margin-left: 15px; /*设置间距*/ }.column:nth-child(odd) {background-color: red; } .column:nth-child(even) {background-color: green; }table
<div class="parent"><div class="column">等宽等宽等宽等宽等宽等宽等宽等宽等宽等宽</div><div class="column">等宽等宽等宽等宽等宽等宽等宽等宽等宽等宽</div><div class="column">等宽等宽等宽等宽等宽等宽等宽等宽等宽等宽</div><div class="column">等宽等宽等宽等宽等宽等宽等宽等宽等宽等宽</div> </div>.parent {height: 500px; display: table; margin: -20px 0; /*抵消上下边 20*2 间距的位置影响*//*两边离页面间距较大,改用子元素设置 padding 来当成间隔就不会有这样的问题*/border-spacing: 20px; /*设置间距*/ }.column {display: table-cell; }.column:nth-child(odd) {background-color: red; }.column:nth-child(even) {background-color: green; }Grid
<div class="parent"><div class="column">等宽等宽等宽等宽等宽等宽等宽等宽等宽等宽</div><div class="column">等宽等宽等宽等宽等宽等宽等宽等宽等宽等宽</div><div class="column">等宽等宽等宽等宽等宽等宽等宽等宽等宽等宽</div><div class="column">等宽等宽等宽等宽等宽等宽等宽等宽等宽等宽</div> </div>.parent {height: 500px;display: grid;grid-template-columns: repeat(4, 1fr); /*4 就是列数*/ }.column:nth-child(odd) {background-color: red; }.column:nth-child(even) {background-color: green; }九宫格布局
table
<div class="parent"><div class="row"><div class="item">1</div><div class="item">2</div><div class="item">3</div></div><div class="row"><div class="item">4</div><div class="item">5</div><div class="item">6</div></div><div class="row"><div class="item">7</div><div class="item">8</div><div class="item">9</div></div> </div>.parent {width: 1200px;height: 500px;margin: 0 auto;display: table; }.row {display: table-row; }.item {border: 1px solid #000;display: table-cell; }flex
<div class="parent"><div class="row"><div class="item">1</div><div class="item">2</div><div class="item">3</div></div><div class="row"><div class="item">4</div><div class="item">5</div><div class="item">6</div></div><div class="row"><div class="item">7</div><div class="item">8</div><div class="item">9</div></div> </div>.parent {width: 1200px;height: 500px;margin: 0 auto;display: flex;flex-direction: column; }.row {display: flex;flex: 1; }.item {flex: 1;border: 1px solid #000; }Grid
CSS Grid 非常强大,可以实现各种各样的三维布局
<div class="parent"><div class="item">1</div><div class="item">2</div><div class="item">3</div><div class="item">4</div><div class="item">5</div><div class="item">6</div><div class="item">7</div><div class="item">8</div><div class="item">9</div> </div>.parent {width: 1200px;height: 500px;margin: 0 auto;display: grid;grid-template-columns: repeat(3, 1fr); /*等同于1fr 1fr 1fr,此为重复的合并写法*/grid-template-rows: repeat(3, 1fr); /*等同于1fr 1fr 1fr,此为重复的合并写法*/ }.item {border: 1px solid #000; }栅格系统
优点:代码简洁,容易理解;提高页面内容的流动性,能适应多种设备
Less
/*生成栅格系统*/ @media screen and (max-width: 768px){.generate-columns(12); /*此处设置生成列数*/.generate-columns(@n, @i: 1) when (@i <= @n) {.column-xs-@{i} {width: (@i * 100% / @n);}.generate-columns(@n, (@i+1));} } @media screen and (min-width: 768px){.generate-columns(12); /*此处设置生成列数*/.generate-columns(@n, @i: 1) when (@i <= @n) {.column-sm-@{i} {width: (@i * 100% / @n);}.generate-columns(@n, (@i+1));} } div[class^="column-xs-"]{float: left; } div[class^="column-sm-"]{float: left; }编译后的 CSS 代码
@media screen and (max-width: 768px) {.column-xs-1 { width: 8.33333333%; }.column-xs-2 { width: 16.66666667%; }.column-xs-3 { width: 25%; }.column-xs-4 { width: 33.33333333%; }.column-xs-5 { width: 41.66666667%; }.column-xs-6 { width: 50%; }.column-xs-7 { width: 58.33333333%; }.column-xs-8 { width: 66.66666667%; }.column-xs-9 { width: 75%; }.column-xs-10 { width: 83.33333333%; }.column-xs-11 { width: 91.66666667%; }.column-xs-12 { width: 100%; } } @media screen and (min-width: 768px) {.column-sm-1 { width: 8.33333333%; }.column-sm-2 { width: 16.66666667%; }.column-sm-3 { width: 25%; }.column-sm-4 { width: 33.33333333%; }.column-sm-5 { width: 41.66666667%; }.column-sm-6 { width: 50%; }.column-sm-7 { width: 58.33333333%; }.column-sm-8 { width: 66.66666667%; }.column-sm-9 { width: 75%; }.column-sm-10 { width: 83.33333333%; }.column-sm-11 { width: 91.66666667%; } .column-sm-12 { width: 100%; } } div[class^="column-xs-"]{float: left; } div[class^="column-sm-"]{float: left; } 《新程序员》:云原生和全面数字化实践50位技术专家共同创作,文字、视频、音频交互阅读总结
- 上一篇: 改善前端优化的有用技巧
- 下一篇: element-ui table点击某行