css-布局(未完)

常用的居中方法

水平居中

根据子元素为行内元素还是块状元素,宽度一定还是宽度未定,采取的布局方案不同。

子元素为行内元素

对父元素设置text-align:center;

1
2
3
<div style="text-align: center">
<span>子元素是行内元素,设置父元素:text-align:center</span>
</div>

子元素为定宽块状元素

设置左右margin值为auto

1
2
3
<div>
<p style="width: 400px;margin: 0 auto">子元素是定宽块元素,设置子元素:margin: 0 auto</p>
</div>

子元素为不定宽块状元素

设置子元素为display:inline,然后再父元素上设置text-align:center

1
2
3
<div style="text-align: center">
<p style="display: inline">子元素是不定宽块元素,设置子元素:display: inline ; 父元素:text-align: center</p>
</div>

通用方案

flex布局,对父元素设置display:flex;justify-content:center;

1
2
3
4
5
6
7
8
9
<div style="display:flex;justify-content:center;">
<span>行内元素</span>
</div>
<div style="display:flex;justify-content:center;">
<p>不定宽块状元素</p>
</div>
<div style="display:flex;justify-content:center;">
<p style="width: 200px">定宽块状元素</p>
</div>

垂直居中

垂直居中对于子元素是单行内联文本,多行内联文本以及块状元素采用的方案是不同的。

父元素一定,子元素为单行内联文本

将包含文字元素的容器行高设置为大于字体大小并且等于元素的高度。默认情况下,文字上下部分会留有相同的空间,因而实现文字的垂直居中。

1
2
3
<div style="width: 300px;height: 300px;background: azure">
<p style="line-height: 300px">子元素为单行内联文本</p>
</div>

父元素一定,子元素为单行内联文本

设置父元素的display: table-cell;,再设置vertical-align: middle;

1
2
3
4
5
<div style="width: 300px;height: 300px;display: table-cell;vertical-align: middle;background: azure">
<p>子元素为多行内联文本</p>
<p>子元素为多行内联文本</p>
<p>子元素为多行内联文本</p>
</div>

块状元素

设置子元素position:absolute,并设置top,bottom为0,父元素的position要设置为static以外的值margin:auto

1
2
3
<div style="width: 300px;height:300px;position: absolute;background: azure">
<p style="width: 100px;height:100px;position: absolute;top: 0;bottom: 0;margin: auto">块状元素</p>
</div>

通用方法

flex布局,给父元素设置display:flex; align-items:center;

1
2
3
<div style="width: 300px;height:300px;display:flex; align-items:center;background: azure">
<p>块状元素</p>
</div>

水平垂直居中

flexbox

简单,但是有兼容性问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<style>
html,body{width:100%;height:100%}
.parent{
width:100%;height:100%;
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /*垂直居中*/
}
</style>
<div class="parent">
<div class="child">
<p>hello</p>
</div>
</div>

absolute+transform

先相对于(0,0)在x,y上各偏移百分之50,transfrom的translate根据自身中心点,偏移-50%,达到水平垂直居中目的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div class="parent">
<div class="child">Demo</div>
</div>

<style>
.parent {
position: relative;
}
.child {
position: absolute;/*绝对定位元素的定位基准点是其有定位元素的祖先元素*/
left: 50%;
top: 50%;
transform: translate(-50%, -50%);/*而translate要做偏移,是相对于自身的中心点而言,如果用百分比做单位,参考值就是本身元素的宽度*/
}
</style>

relative+absolute + 负margin

1
2
3
4
5
6
7
8
9
10
11
.parent{
position:relative;
}
.child{
width: 100px;
height: 100px;
position: absolute;
top: 50%;
left: 50%;
margin: -50px 0 0 -50px;
}

绝对定位方式+四个方向置0

子元素可以是块级元素也可以是行内元素,没有影响

1
2
3
4
5
6
7
8
9
10
.parent{
position:relative
}
.child{
margin:auto;/*一定要加*/
height: 100px;
width: 100px;
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
}

Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<p>flex 实现水平垂直居中</p>
<div style="width: 800px;height: 600px;background-color: #b2b2b2;display: flex;justify-content: center;align-items: center">
<div style="width: 200px;height:200px;background-color: #0bb20c">
</div>
</div>

<p>absolute + transform</p>
<div style="width: 800px;height: 600px;background-color: #b2b2b2;position: relative">
<div style="width: 200px;height:200px;background-color: #0bb20c;position: absolute;top: 50%;left:50%;transform: translate(-50%,-50%)">
</div>
</div>

<p>absolute + 负margin实现水平垂直居中</p>
<div style="width: 800px;height: 600px;background-color: #b2b2b2;position: relative">
<div style="width: 200px;height:200px;background-color: #0bb20c;position: absolute;top: 50%;left:50%;margin: -100px 0 0 -100px">
</div>
</div>

<p>absolute + 四个方位为0 + margin:auto实现水平垂直居中</p>
<div style="width: 800px;height: 600px;background-color: #b2b2b2;position: relative">
<div style="width: 200px;height:200px;background-color: #0bb20c;position: absolute;top: 0;bottom: 0;left: 0;right: 0;margin: auto;">
</div>
</div>

两栏布局

固定左栏右侧自适应(flexbox实现方案)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自适应两栏布局</title>
</head>
<style>
#wrapper{display: flex;flex-direction: column;justify-content: center;}
#header{width: 100%;height: 100px;background-color: red;}
#body{width: 100%;height: 500px;display: flex;}
#aside{width: 300px;background-color: #ff6600;}
#main{flex: 1;background-color: cyan;}
#footer{width: 100%;height: 100px;background-color: #0088ff;}
</style>
<body>
<div id="wrapper">
<div id="header">header</div>
<div id="body">
<div id="aside">
<div class="inner">
aside
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</div>
<div id="main">
<div class="inner">
main
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</div>
</div>
<div id="footer">footer</div>
</div>
</body>
</html>

image.png

固定右栏左侧自适应(flexbox实现方案)

只需要对上面的例子稍作修改,把左右栏样式对调即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自适应两栏布局</title>
</head>
<style>
#wrapper{display: flex;flex-direction: column;justify-content: center;}
#header{width: 100%;height: 100px;background-color: red;}
#body{width: 100%;height: 500px;display: flex;}
#aside{width: 300px;background-color: #ff6600;}
#main{flex: 1;background-color: cyan;}
#footer{width: 100%;height: 100px;background-color: #0088ff;}
</style>
<body>
<div id="wrapper">
<div id="header">header</div>
<div id="body">
<div id="main">
<div class="inner">
main
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</div>
<div id="aside">
<div class="inner">
aside
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</div>
</div>
<div id="footer">footer</div>
</div>
</body>
</html>

image.png

三栏布局

自适应三栏布局(flexbox实现方案)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自适应三栏布局</title>
</head>
<style>
#wrapper{width: 100%;display: flex;flex-direction: column;}
#header{width: 100%;height: 100px;background-color: red;}
#body{width: 100%;height: 500px;display: flex;}
#aside{width: 200px;background-color: cadetblue;}
#content{flex: 1;background-color: #262aa0;display: flex;}
#main{flex: 1;}
#content-aside{width: 200px;background-color: cyan;}
#footer{width: 100%;height: 100px;background-color: #ff6600;}
</style>
<body>
<div id="wrapper">
<div id="header">header</div>
<div id="body" class="cls">
<div id="aside">
<div class="inner">
aside
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</div>
<div id="content" class="cls">
<div id="main">
<div class="inner">
main
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</div>
<div id="content-aside">
<div class="inner">
content-aside
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</div>
</div>
</div>
<div id="footer">footer</div>
</div>
</body>
</html>

image.png

Grid布局

CSS网格布局用于将页面分割成数个主要区域,或者用来定义组件内部元素间大小、位置和图层之间的关系。

像表格一样,网格布局让我们能够按行或列来对齐元素。 但是,使用CSS网格可能还是比CSS表格更容易布局。 例如,网格容器的子元素可以自己定位,以便它们像CSS定位的元素一样,真正的有重叠和层次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.wrapper{
display: grid;
grid-template-columns: 100px 100px 100px; /*三个值表示三列,列宽为100px*/
grid-template-rows: 50px 50px; /*两个值表示两行,行高为50px*/
}
.one{
/*grid-column: 1/4; === grid-column-start: 1;grid-column-end: 4; 表示从第一条网格线开始,第四条网格线结束*/
background-color: #0bb20c;
}
.two{background-color: #586c94;}
.three{background-color: #9ed99d;}
.four{background-color: #0000FF;}
.five{background-color: #10aeff;}
.six{background-color: #f76260;}
</style>
</head>
<body>
<div class="wrapper">
<div class="one">1</div><div class="two">2</div><div class="three">3</div>
<div class="four">4</div><div class="five">5</div><div class="six">6</div>
</div>
</body>
</html>

image.png

BFC

简介

BFC(Block formatting Context块级格式化上下文),他规定了内部的块级元素的布局方式,默认情况下只有一个根元素(即body)一个块级上下文。通俗理解为页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,外面的元素不会影响到容器里面的子元素。

BFC布局规则

  1. 内部的块级元素会在垂直方向,一个一个地放置。
  2. 块级元素垂直方向的距离由margin决定。属于同一个BFC的两个相邻的块级元素会发生margin合并,不属于同一个BFC的两个相邻的块级元素不会发生margin合并。
  3. 每个元素的margin box的左边,与包含border box的左边相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此。
  4. BFC的区域不会与float box重叠(所以可以解决浮动造成的重叠覆盖问题)。
  5. BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响外部的元素,外面的元素也不会影响到容器里面的子元素。
  6. 计算BFC的高度时,浮动元素也参与计算。(所以可以消除浮动)

创建一个BFC

一个BFC可以显示触发,只要满足以下条件之一:

  1. float的值不为none
  2. overflow的值不为visible
  3. position的值为fixed/absolute
  4. display的值为table-cell / table-caption / inline-block / flex / inline-flex

BFC应用

消除margin合并

之所以会出现margin合并,就是因为2个块属于同个BFC,因此,把2个块分成2个BFC就能消除合并。

1
2
3
4
5
6
7
8
9
10
11
<body>  
<div class='bro1'></div>
<div class='bro2'></div>
</body>

<!--消除margin合并-->
<!--给.bro1新建一个BFC,并添加 overflow:hidden;-->
<body>
<div style="overflow:hidden"> <div class='bro1'></div> </div>
<div class='bro2'></div>
</body>

包含浮动子元素

这也是我们的主要议题——为什么”overflow:hidden”能清除浮动的影响?

我们经常会在父元素里设置某个子元素浮动。浮动后,子元素脱离了文档流,使得父元素无法包住这个浮动的子元素。

通常在父元素上设置一个clearfix的伪元素来清除浮动;同样,我们可以利用BFC可以包含浮动这一特性来清除浮动,例子已经在之前讲过

当给父级设置”overflow:hidden”时,实际上创建了一个超级属性BFC,此超级属性反过来决定了”height:auto”是如何计算的

因为在“BFC布局规则”中提到:计算BFC的高度时,浮动元素也参与计算。因此,父元素在计算其高度时,加入了浮动元素的高度,“顺便”达成了清除浮动的目标,所以父元素就包裹住了子元素

解决由于浮动造成的重叠覆盖问题

​ 一般情况下,浮动元素会脱离文档流,即不占位置。它的兄弟元素会与它在左上角重叠。但是如果两个相邻元素都设置了浮动,那么意味着它们都是以BFC的规则渲染,根据上述第四条规则,BFC区域不会相互重叠,所以便能理解为什么设置浮动后元素能独占空间了

http://riny.net/lab/

https://zhuanlan.zhihu.com/p/25565751

https://www.jianshu.com/p/086364d3d5e2

BFC详解