页面架构-布局解决方案

一、居中布局

水平居中

前提要求:父容器和子容器的宽度不定

方案一: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

目前大部分的浏览器不能支持,方案略。

以上方案的比较:

原文地址:https://www.cnblogs.com/rosestudy/p/4852376.html