一、居中布局
水平居中
前提要求:父容器和子容器的宽度不定
方案一:inline-block+text-align
优点:兼容性好,在IE67上,用display:inline;zoom:1;模拟inline-block。
缺点:在父容器里设置了text-align:center;所以child也会继承这个属性,child容器里面的文字也会水平居中,因此要在child里重新设置text-align。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>水平居中</title> <link rel="stylesheet" type="text/css" href="demo.css"> <style type="text/css"> body{margin:20px;} .parent{ text-align: center;/*只对行内元素有效*/ } .child{ display: inline-block; } </style> </head> <body> <div class="parent"> <div class="child">用inline-block和text-align实现水平居中DEMO</div> </div> </body> </html>
demo.css如下:
html,body,h1,h2,h3,h4,h5,h6,div,dl,dt,dd,ul,ol,li,p,blockquote,pre,hr,figure,table,caption,th,td,form,fieldset,legend,input,button,textarea,menu{margin:0;padding:0;} header,footer,section,article,aside,nav,hgroup,address,figure,figcaption,menu,details{display:block;} table{border-collapse:collapse;border-spacing:0;} caption,th{text-align:left;font-weight:normal;} html,body,fieldset,img,iframe,abbr{border:0;} i,cite,em,var,address,dfn{font-style:normal;} [hidefocus],summary{outline:0;} li{list-style:none;} h1,h2,h3,h4,h5,h6,small{font-size:100%;} sup,sub{font-size:83%;} pre,code,kbd,samp{font-family:inherit;} q:before,q:after{content:none;} textarea{overflow:auto;resize:none;} label,summary{cursor:default;} a,button{cursor:pointer;} h1,h2,h3,h4,h5,h6,em,strong,b{font-weight:normal;} del,ins,u,s,a,a:hover{text-decoration:none;} body,textarea,input,button,select,keygen,legend{font:30px/1.5 'microsoft yahei';color:#333;outline:0;} body{background:#fff;} a,a:hover{color:#333;} .parent{background:#ddd;} .child{background:#666;color:#fff;}
方案二:table+margin
设置了display:table的元素的宽度也是由内容决定。
优点:只需要对child进行设置;兼容性较好,display:table能兼容IE8及以上。
.child{ display:table; margin:0 auto; }
方案三:absolute+transform
优点:absolute的元素脱离文档流,不会对其他元素产生影响。
缺点:IE8不支持transform
.parent{ position:relative; } .child{ position:absolute; left:50%; //相对于父容器的50% transform:translateX(-50%); //相对于自身的50% }
方案四:flex+justify-content
缺点:对于display:flex;IE89不支持、IE10部分支持
.parent{ display:flex; //给父元素设置flex属性,那么子元素就是flex-item,子元素的宽度是 auto,即宽度由内容决定 justify-content:center; }
或者
.parent{ display:flex; } .child{ margin:0 auto; }
垂直居中
前提要求:父容器的高度和子容器的高度不定
方案一:table-cell+vertical-align
优点:IE8及以上支持table-cell
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>垂直居中</title> <link rel="stylesheet" type="text/css" href="demo.css"> <style type="text/css"> body{margin:20px;} .parent{width:4em;height:500px;} .child{width:100%;} .parent{ display: table-cell; vertical-align: middle; /*vertical-align 只对行内元素有效*/ } </style> </head> <body> <div class="parent"> <div class="child">DEMO</div> </div> </body> </html>
方案二:absolute+transform
优点:子元素设置了绝对定位,不会影响其他元素
缺点:IE8不支持transform
.parent{ position:relative; } .child{ position:absolute; top:50%; transform:translateY:-50%; }
方案三:flex+align-items
优点:只需要对父元素设置样式
缺点:兼容性问题。对于display:flex;IE89不支持、IE10部分支持。对于align-items,IE89不支持,IE10部分支持。
.parent{ display:flex; align-items:center; }
水平垂直居中
前提要求:父容器的宽高不定,子容器的宽高不定
方案一:inline-block+text-align+table-cell+vertical-align
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>居中</title> 6 <link rel="stylesheet" type="text/css" href="demo.css"> 7 <style type="text/css"> 8 body{margin:20px;} 9 .parent{width:200px;height:300px;} 10 11 .parent{ 12 text-align: center; 13 display: table-cell; /* 此元素会变成一个行内元素,作为一个表格单元格显示(类似 <td> 和 <th>) */ 14 vertical-align: middle; /* 只对行内元素起作用 */ 15 16 .child{ 17 display: inline-block; 18 } 19 </style> 20 </head> 21 <body> 22 <div class="parent"> 23 <div class="child">DEMO</div> 24 </div> 25 </body> 26 </html>
方案二:absolute+transform
.parent{ position: relative; } .child{ position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%); }
方案三:flex+justify-content+align-items
.parent{ display: flex; justify-content: center; align-items: center; }
做解决方案时,需要了解CSS属性和值的特性,对问题进行分解。
二、多列布局
一列定宽+一列自适应
方案一:float+margin
缺点:IE6里会产生3px bug;当right容器里有清除浮动的时,会产生bug。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>多列布局</title> 6 <link rel="stylesheet" type="text/css" href="demo.css"> 7 <style type="text/css"> 8 body{margin:20px;} 9 10 .parent{ 11 12 } 13 .left{ 14 float: left; 15 width: 100px; 16 } 17 .right{ 18 margin-left: 120px; 19 } 20 /*模拟bug*/ 21 /*.right p:first-child{ 22 clear:both; 23 background-color: red; 24 }*/ 25 </style> 26 </head> 27 <body> 28 <div class="parent"> 29 <div class="left"> 30 <p>left</p> 31 </div> 32 <div class="right"> 33 <p>right</p> 34 <p>right</p> 35 </div> 36 </div> 37 </body> 38 </html>
方案二:float+margin+(fix)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>多列布局</title> 6 <link rel="stylesheet" type="text/css" href="demo.css"> 7 <style type="text/css"> 8 body{margin:20px;} 9 10 .parent{ 11 12 } 13 .left{ 14 float: left; 15 width: 100px; 16 position: relative; //提高层级 17 } 18 .right-fix{ 19 float: right; width: 100%; 20 margin-left: -100px; 21 } 22 .right{ 23 margin-left: 120px; 24 } 25 </style> 26 </head> 27 <body> 28 <div class="parent"> 29 <div class="left"><p>left</p></div> 30 <!-- 多了一层容器 --> 31 <div class="right-fix"> 32 <div class="right"> 33 <p>right</p><p>right</p> 34 </div> 35 </div> 36 </div> 37 </body> 38 </html>
方案三:float+overflow
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>多列布局</title> 6 <link rel="stylesheet" type="text/css" href="demo.css"> 7 <style type="text/css"> 8 body{margin:20px;} 9 10 .parent{ 11 12 } 13 .left{ 14 float: left; 15 width: 100px; 16 margin-right: 20px; 17 } 18 .right{ 19 20 overflow: hidden; /* 该设置很重要 ,触发BFC模式 */ 21 } 22 </style> 23 </head> 24 <body> 25 <div class="parent"> 26 <div class="left"> 27 <p>left</p> 28 </div> 29 <div class="right"> 30 <p>right</p> 31 <p>right</p> 32 </div> 33 </div> 34 </body> 35 </html>
方案四:table
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>多列布局</title> <link rel="stylesheet" type="text/css" href="demo.css"> <style type="text/css"> body{margin:20px;} .parent{ display: table; /* table导致容器宽度由内容决定,故需要在下面设置width:100% */ width: 100%; /*table-layout的好处:加速table的渲染;实现了布局优先 fixed 列宽由表格宽度和列宽度设定。*/ table-layout: fixed; } .left,.right{ display: table-cell; /* 以表格单元格的形式呈现,类似td */ } .left{ /*表格的特点就是每一列的宽度之和会等于table的宽度,因此right容器会填充剩余宽度*/ width: 100px; padding-right: 20px; /* 表格中不能用margin设置距离,必须用padding */ } </style> </head> <body> <div class="parent"> <div class="left"> <p>left</p> </div> <div class="right"> <p>right</p> <p>right</p> </div> </div> </body> </html>
方案五:flex
缺点:1.兼容性问题 2.性能问题,不适合做大范围布局
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>多列布局</title> 6 <link rel="stylesheet" type="text/css" href="demo.css"> 7 <style type="text/css"> 8 body{margin:20px;} 9 10 .parent{ 11 display: flex; 12 } 13 .left{ 14 width: 100px; 15 margin-right: 20px; 16 } 17 .right{ 18 flex: 1; /* 子元素可伸缩值,使得其占据剩余的所有空间,而不是宽度由内容决定 */ 19 } 20 </style> 21 </head> 22 <body> 23 <div class="parent"> 24 <div class="left"> 25 <p>left</p> 26 </div> 27 <div class="right"> 28 <p>right</p> 29 <p>right</p> 30 </div> 31 </div> 32 </body> 33 </html>
两列定宽+一列自适应
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>多列布局</title> 6 <link rel="stylesheet" type="text/css" href="demo.css"> 7 <style type="text/css"> 8 body{margin:20px;} 9 10 .parent{ 11 12 } 13 .left,.center{ 14 float: left; 15 width: 100px; 16 margin-right: 20px; 17 } 18 .right{ 19 overflow: hidden; /*很重要、触发BFC模式*/ 20 } 21 </style> 22 </head> 23 <body> 24 <div class="parent"> 25 <div class="left"> 26 <p>left</p> 27 </div> 28 <div class="center"> 29 <p>center</p> 30 </div> 31 <div class="right"> 32 <p>right</p> 33 <p>right</p> 34 </div> 35 </div> 36 </body> 37 </html>
一列不定宽+一列自适应
方案一:float+overflow
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>多列布局</title> 6 <link rel="stylesheet" type="text/css" href="demo.css"> 7 <style type="text/css"> 8 body{margin:20px;} 9 10 .parent{ 11 12 } 13 .left{ 14 float: left; 15 margin-right: 20px; 16 } 17 .right{ 18 overflow: hidden; 19 } 20 .left p{width: 200px;} 21 </style> 22 </head> 23 <body> 24 <div class="parent"> 25 <div class="left"> 26 <p>left</p> 27 </div> 28 <div class="right"> 29 <p>right</p> 30 <p>right</p> 31 </div> 32 </div> 33 </body> 34 </html>
方案二:table
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>多列布局</title> 6 <link rel="stylesheet" type="text/css" href="demo.css"> 7 <style type="text/css"> 8 body{margin:20px;} 9 10 .parent{ 11 display: table; 12 width: 100%; 13 } 14 .left,.right{ 15 display: table-cell; 16 17 } 18 .left{ 19 width: 0.1%; /*为了让right自适应剩余的宽度,这里不能用1px,因为在IE8里会有bug */ 20 padding-right: 20px; 21 } 22 .left p{ 23 width:200px; 24 } 25 </style> 26 </head> 27 <body> 28 <div class="parent"> 29 <div class="left"> 30 <p>left</p> 31 </div> 32 <div class="right"> 33 <p>right</p> 34 <p>right</p> 35 </div> 36 </div> 37 </body> 38 </html>
方案三:flex
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>多列布局</title> 6 <link rel="stylesheet" type="text/css" href="demo.css"> 7 <style type="text/css"> 8 body{margin:20px;} 9 10 .parent{ 11 display: flex; 12 } 13 .left{ 14 margin-right: 20px; 15 } 16 .right{ 17 flex: 1; /* 分配剩余宽度 */ 18 } 19 .left p{width: 200px;} 20 </style> 21 </head> 22 <body> 23 <div class="parent"> 24 <div class="left"> 25 <p>left</p> 26 </div> 27 <div class="right"> 28 <p>right</p> 29 <p>right</p> 30 </div> 31 </div> 32 </body> 33 </html>
两列不定宽+一列自适应
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>多列布局</title> 6 <link rel="stylesheet" type="text/css" href="demo.css"> 7 <style type="text/css"> 8 body{margin:20px;} 9 10 .parent{ 11 12 } 13 .left,.center{ 14 float: left; 15 margin-right: 20px; 16 } 17 .right{ 18 overflow: hidden; 19 } 20 .left p,.center p{ 21 width: 100px; 22 } 23 </style> 24 </head> 25 <body> 26 <div class="parent"> 27 <div class="left"> 28 <p>left</p> 29 </div> 30 <div class="center"> 31 <p>center</p> 32 </div> 33 <div class="right"> 34 <p>right</p> 35 <p>right</p> 36 </div> 37 </div> 38 </body> 39 </html>
等分布局
方案一:float+box-sizing:border-box
缺点:当列数发生变化时,需要修改结构和样式,即结构和样式具有耦合性
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>多列布局</title> 6 <link rel="stylesheet" type="text/css" href="demo.css"> 7 <style type="text/css"> 8 body{margin:20px;} 9 10 .parent{ 11 margin-left: -20px; /*父元素的宽度增加了20px*/ 12 } 13 .column{ 14 float: left; 15 width: 25%; /* 由于设置成了border-box,故这个25%包含padding的宽度*/ 16 padding-left: 20px;/* 只能用padding设置距离 */ 17 box-sizing: border-box; /*box-sizing: content-box|border-box|inherit; 18 content-box 宽度和高度分别应用到元素的内容框。 19 在宽度和高度之外绘制元素的内边距和边框。 20 border-box 为元素设定的宽度和高度决定了元素的边框盒。 21 通过从已设定的宽度和高度分别减去边框和内边 22 距才能得到内容的宽度和高度。 23 */ 24 } 25 </style> 26 </head> 27 <body> 28 <div class="parent"> 29 <div> 30 <div class="column"><p>1</p></div> 31 <div class="column"><p>2</p></div> 32 <div class="column"><p>3</p></div> 33 <div class="column"><p>3</p></div> 34 </div> 35 </div> 36 </body> 37 </html>
方案二:table
优点:结构和样式解耦
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>多列布局</title> 6 <link rel="stylesheet" type="text/css" href="demo.css"> 7 <style type="text/css"> 8 body{margin:20px;} 9 10 .parent-fix{ 11 margin-left: -20px; /*为了解决table的宽度增加20px的问题*/ 12 } 13 .parent{ 14 display: table; 15 width:100%; 16 table-layout: fixed; /* 17 假设单元格没有设置宽度,单元格将平分表格宽度 18 fixed 具有布局优先,加速渲染的效果 19 */ 20 } 21 .column{ 22 display: table-cell; 23 padding-left: 20px; 24 } 25 </style> 26 </head> 27 <body> 28 <div class="parent-fix"> 29 <div class="parent"> 30 <div class="column"><p>1</p></div> 31 <div class="column"><p>2</p></div> 32 <div class="column"><p>3</p></div> 33 <div class="column"><p>4</p></div> 34 </div> 35 </div> 36 </body> 37 </html>
方案三:flex
此方案与方案一进行比较。flex分配的是除去margin-left后的父容器剩余空间。
优点:结构和样式解耦。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>多列布局</title> 6 <link rel="stylesheet" type="text/css" href="demo.css"> 7 <style type="text/css"> 8 body{margin:20px;} 9 10 .parent{ 11 display: flex; 12 } 13 .column{ 14 flex: 1; /*如果不设置flex,那么每一列的宽度就由内容决定。 15 设置flex之后,每一列的宽度就是平分了父元素的剩余空间*/ 16 } 17 .column+.column{ 18 margin-left:50px; 19 } 20 </style> 21 </head> 22 <body> 23 <div class="parent"> 24 <div class="column"><p>1</p></div> 25 <div class="column"><p>2</p></div> 26 <div class="column"><p>3</p></div> 27 <div class="column"><p>4</p></div> 28 </div> 29 </body> 30 </html>
等高布局
方案一:table
table的特性就是每一列的单元格等宽,每一行的单元格等高。
方案二:flex
flex-items 默认的align-items:stretch,天生的等高。
方案三:float
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>多列布局</title> 6 <link rel="stylesheet" type="text/css" href="demo.css"> 7 <style type="text/css"> 8 body{margin:20px;} 9 p{background: none!important;} 10 .left,.right{background: #444;} 11 .parent{ 12 overflow: hidden; 13 } 14 .left,.right{ 15 /*较难理解的伪等高*/ 16 padding-bottom: 9999px; 17 margin-bottom: -9999px; 18 } 19 .left{ 20 float: left; 21 width: 100px; 22 margin-right: 20px; 23 } 24 .right{ 25 overflow: hidden; 26 } 27 28 </style> 29 </head> 30 <body> 31 <div class="parent"> 32 <div class="left"> 33 <p>left</p> 34 </div> 35 <div class="right"> 36 <p>right</p> 37 <p>right</p> 38 </div> 39 </div> 40 </body> 41 </html>
三、全屏布局
需求1:
方案一:position
缺点:IE6不支持
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>全屏布局</title> 6 <link rel="stylesheet" type="text/css" href="demo.css"> 7 <style type="text/css"> 8 /*overflow:hidden;禁用滚动条*/ 9 html,body,.parent{margin:0;height:100%;overflow:hidden;} 10 body{color:white;} 11 .top{ 12 /*left:0;right:0;能使宽度变成100%*/ 13 position:absolute;top:0;left:0;right:0;height:100px; 14 background:blue; 15 } 16 .left{ 17 position:absolute;left:0;top:100px;bottom:50px;width:200px; 18 background:red; 19 } 20 .right{ 21 position:absolute;left:200px;top:100px;bottom:50px;right:0; 22 background:pink;overflow: auto; 23 } 24 .right .inner{min-height: 1000px;} 25 .bottom{ 26 position:absolute;left:0;right:0;bottom:0;height:50px; 27 background: black; 28 } 29 </style> 30 </head> 31 <body> 32 <div class="parent"> 33 <div class="top">top</div> 34 <div class="left">left</div> 35 <div class="right"><div class="inner">right</div></div> 36 <div class="bottom">bottom</div> 37 </div> 38 </body> 39 </html>
demo.css
1 html,body,h1,h2,h3,h4,h5,h6,div,dl,dt,dd,ul,ol,li,p,blockquote,pre,hr,figure,table,caption,th,td,form,fieldset,legend,input,button,textarea,menu{margin:0;padding:0;} 2 header,footer,section,article,aside,nav,hgroup,address,figure,figcaption,menu,details{display:block;} 3 table{border-collapse:collapse;border-spacing:0;} 4 caption,th{text-align:left;font-weight:normal;} 5 html,body,fieldset,img,iframe,abbr{border:0;} 6 i,cite,em,var,address,dfn{font-style:normal;} 7 [hidefocus],summary{outline:0;} 8 li{list-style:none;} 9 h1,h2,h3,h4,h5,h6,small{font-size:100%;} 10 sup,sub{font-size:83%;} 11 pre,code,kbd,samp{font-family:inherit;} 12 q:before,q:after{content:none;} 13 textarea{overflow:auto;resize:none;} 14 label,summary{cursor:default;} 15 a,button{cursor:pointer;} 16 h1,h2,h3,h4,h5,h6,em,strong,b{font-weight:normal;} 17 del,ins,u,s,a,a:hover{text-decoration:none;} 18 body,textarea,input,button,select,keygen,legend{font:30px/1.5 'microsoft yahei';color:#333;outline:0;} 19 body{background:#fff;} 20 a,a:hover{color:#333;} 21 .clearfix:after{content:'';clear:both;display:block;height:0;overflow:hidden;visibility:hidden;}
方案二:flex
缺点:IE8、9不支持,IE10部分支持
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>全屏布局</title> 6 <link rel="stylesheet" type="text/css" href="demo.css"> 7 <style type="text/css"> 8 html,body,.parent{margin:0;height:100%;overflow:hidden;} 9 body{color: white;} 10 .parent{display: flex;flex-direction: column;} 11 .top{height:100px;background: blue;} 12 .bottom{height:50px;background: black;} 13 /*flex-direction的默认值是row*/ 14 .middle{flex:1;display:flex;} 15 .left{width:200px;background: red;} 16 .right{flex: 1;overflow: auto;background:pink;} 17 .right .inner{min-height: 1000px;} 18 </style> 19 </head> 20 <body> 21 <div class="parent"> 22 <div class="top">top</div> 23 <div class="middle"> 24 <div class="left">left</div> 25 <div class="right"> 26 <div class="inner">right</div> 27 </div> 28 </div> 29 <div class="bottom">bottom</div> 30 </div> 31 </body> 32 </html>
需求2:
把以上两个方案中的单位变成百分比即可。
需求3:
方案一:Flex
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>全屏布局</title> 6 <link rel="stylesheet" type="text/css" href="demo.css"> 7 <style type="text/css"> 8 html,body,.parent{margin:0;height:100%;overflow:hidden;} 9 body{color:white;} 10 .parent{display:flex;flex-direction:column;} 11 .top{background:blue;} 12 .bottom{background:black;} 13 .middle{flex:1;display:flex;} 14 .left{background: red;} 15 .right{flex:1;overflow:auto;background: pink;} 16 .right .inner{min-height:1000px;} 17 </style> 18 </head> 19 <body> 20 <div class="parent"> 21 <div class="top">top</div> 22 <div class="middle"> 23 <div class="left">left</div> 24 <div class="right"> 25 <div class="inner">right</div> 26 </div> 27 </div> 28 <div class="bottom">bottom</div> 29 </div> 30 </body> 31 </html>
方案二:Grid
目前大部分的浏览器不能支持,方案略。
以上方案的比较: