CSS传统布局方式

用CSS来控制网页布局本质上就是用CSS来合理地摆放盒子,传统布局方式有三种机制:标准文档流,浮动布局和定位

标准文档流

当没有任何的CSS来控制页面布局的时候,页面中的盒子就属于标准文档流,顾名思义,就是按照写文档的方式排列,从左到右,从上到下,块级元素独占一行,而行内元素会排列在行内,当触及父元素边缘时会自动换行

文档流是一种最基础的布局,避免了在无CSS情况下(CSS加载失败)盒子堆积在浏览器的左上角的情况,减轻了开发者的布局方式指定负担

而使用CSS的意义就是,做到标准文档流所不能做到的事情

浮动布局

浮动布局的意思就是,让盒子漂浮在标准流的上面 (脱离文档流)

浮动的使用方式是 css选择器{float: 属性值}

属性值 作用
none 默认,不浮动
left 浮动
right 浮动

我们来看一个例子

1
2
3
4
5
6
7
8
9
10
11
.box1 {
width: 100px;
height: 100px;
background-color: pink;
float: left;
}
.box2 {
width: 200px;
height: 200px;
background-color: lightyellow;
}

可以发现浮动元素粉色的盒子漂浮在了正常文档流的上面,不占据文档流的位置,位置则让给了这个黄色的盒子

如果我们让这个黄色的盒子也浮起来,就可以得到一个紧密贴着排成一行的两个盒子 (正常的文档流的行内元素会有一个font的间距),浮动会改变盒子的display属性,转换为了类似行内块的东西,但是元素之间没有空白缝隙


浮动清除

使用浮动布局最常做的一件事就是清除浮动

为什么要清除浮动呢,首先来看一个例子

当我在写这篇博客的时候,对于上述两个盒子的例子,在没有清除浮动的时候,文档的显示是这样的

本应该希望出现在box下方的文字内容移了上来,这是因为浮动一开始就是用于实现图片文字环绕的,所以呈现出这样的效果

但是如果我们不希望浮动元素下方的内容受到浮动元素的影响,那么我们就需要清除浮动

浮动还会带来一个影响就是父元素塌陷,有时候我们在写css的时候,并没有设置父元素的高度,而是希望用子元素把父元素撑开,那么当子元素浮动,脱离文档流之后,就失去了支撑父元素的能力,如果我们希望子元素依旧拥有把父元素撑开的能力,那么就需要清除浮动

所谓的清除浮动,指的就是清除浮动元素带来的影响

下面介绍几种常见的清除浮动的方法:

  • 新建一个div元素来清除浮动

比如刚才的例子,我们建立一个box4,加在最后面

1
2
3
.box4{
clear: both;
}
1
2
3
<div class="box1"></div>
<div class="box3"></div>
<div class="box4"></div>

这时候下面的文字就能够按照我们所希望的在浮动元素下方正常显示

  • 用伪元素清除浮动

用伪元素来清除浮动本质上和新建div是相同的,只是给希望清除浮动的父元素自动添加一个子节点,更加方便一些

1
2
3
4
5
.clear::after {
content: "";
display: block;
clear: both;
}

我们设置一个类clear,给其设置一个after伪元素,对于需要清除浮动的父元素,我们只要给其添加一个类clear即可

  • BFC清除浮动

这个之前总结过,让元素形成BFC,上下文无关即可

定位

定位的作用是使得盒子可以根据参照点进行偏移,不同定位的方法本质上是选取不同的参照点

在定位position中用top,bottom, left,right来表示和参照点的距离,定位的默认值是static,静态定位,就是按照正常的文档流定位的意思

相对定位

相对定位relative可以使得盒子相对于自己原来的位置进行定位

比如我们设置三个box,让中间的box相对自己原来的位置往下移动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<style>
.box5 {
display: inline-block;
width: 100px;
height: 100px;
background-color: lightyellow;
}
.box6 {
display: inline-block;
width: 100px;
height: 100px;
background-color: lightgreen;
position: relative;
top: 100px;
}
.box7 {
display: inline-block;
width: 100px;
height: 100px;
background-color: lightblue;
}
</style>

就可以得到如下的效果

我们可以看到,即使绿色的盒子腾出了位置,蓝色的盒子也不会往左边靠,因为相对定位是不脱离文档流的,相对定位的元素其实还待在原来的位置上,只是看上去换了位置,对之后的元素也没有任何的影响

绝对定位

绝对定位的参照点是最近的已定位的祖先元素,如果我们希望实现相对父元素定位,则父元素必须有定位值,否则元素会参照浏览器进行定位

绝对定位absolute是脱离文档流的,完全不占据任何位置,想相对参照点怎么放就怎么放

举个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.box8 {
display: inline-block;
width: 200px;
height: 200px;
background-color: lightyellow;
position: relative;
}
.box9 {
display: inline-block;
width: 100px;
height: 100px;
background-color: lightgreen;
position: absolute;
top: 50px;
left: 50px;
}

定位有一个重要的口诀叫”子绝父相”,意思就是子元素绝对定位则父元素一般需要相对定位,这样才能使得子元素相对于父元素定位,同时如果父元素也是绝对定位,则会影响到下方的元素 (整体上移)

固定定位

固定定位fixed的参照点是浏览器的可视窗口,也就是说,不会随着页面的上下滚动而移动,就比如博客右下角的看板娘以及回到首部这些功能都是由fixed来实现的,固定定位是脱离文档流的,和父元素没有任何关系,单独使用

粘性定位

粘性定位sticky是一种比较特殊的定位方式,他可以先跟随文档流随着页面的滚动一起移动,当移动到特定的位置的时候,粘在那里不再移动,达到fixed一样的效果

如果需要更复杂的定位效果,则可以使用js监听滚动事件来实现

弹性布局

弹性布局 (flex) 是一种一维的布局方式,通过给父元素添加flex属性,能够使得父元素成为弹性容器,子元素则成为容器中的弹性项 (flex item)

因为是一维布局,父元素设置为弹性布局后,子元素的 float、clear 和 vertical-align 属性将失效

我们来简单地使用一下弹性布局

1
2
3
4
5
6
7
8
9
10
.container{
display: flex;
border: orange solid 2px;
}
.item{
width: 100px;
height: 100px;
background-color: orange;
margin: 5px;
}

效果如下


弹性布局的主轴方向

我们在上文的例子中可以看到弹性项在容器中能够横向顺序排列,因为在弹性布局中主轴默认是横向的 (row)

当然我们也可以用flex-direction属性来改变主轴的方向,使得弹性项在容器中纵向顺序排列

我们为container增添如下属性,就可以使得弹性容器的方向变为纵向 (column)

1
2
3
4
.plus{
flex-direction: column;
width: 110px;
}

效果如下


flex-direction还有row-reverse和column-reverse两种属性值,可以改变弹性项的方向

比如为容器添加如下类

1
2
3
.direction{
flex-direction: row-reverse;
}

就能够使得元素倒过来排布,达到类似float:right的效果

1
2
3

主轴内容的排列方式

justify-content属性可以更改主轴内容的排列方式

属性值 效果
flex-start 默认值,从侧轴头部开始排列
flex-end 从侧轴尾部开始排列
center 水平居中
space-between 两侧弹性项贴边,剩余空间平分
space-around 平分剩余空间,两侧空间为间距一半

我们来测试一下效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.start{
justify-content: flex-start;
}
.end{
justify-content: flex-end;
}
.center{
justify-content: center;
}
.between{
justify-content: space-between;
}
.around{
justify-content: space-around;
}





换行设置

弹性布局默认是不换行的,如果弹性项超出了容器宽度,则会被强行压缩,比如我们给容器添加一个宽度类

1
2
3
.w{
width: 120px;
}

容器里橙色的小方块就会被压缩


如果我们希望超出去的部分换行,我们可以通过设置换行属性值 (flex-wrap), 默认值不换行 (no-wrap),当我们将其改成换行的时候就能使得超出部分换行 (wrap)

1
2
3
.wrap{
flex-wrap: wrap;
}

侧轴元素的排列方式

单行情况的排列方式

align-items属性可以设置单行情况下,侧轴方向的排列方式,设置一维元素靠侧轴方向的头尾或者居中,或是元素拉伸 (换行情况下无效)

属性值 效果
flex-start 默认值,从侧轴头部开始排列
flex-end 从侧轴尾部开始排列
center 居中显示
stretch 元素拉伸

因为侧轴方向只有一行,所以只能设置头尾,居中或者元素拉伸 (拉伸会受到min-width/max-width/height的限制)

多行情况的排列方式

多行 (即设置了换行wrap的情况下), 需要使用align-content来设置排列方式,设置的属性如下

属性值 效果
flex-start 默认值,从侧轴头部开始排列
flex-end 从侧轴尾部开始排列
center 居中显示
stretch 元素拉伸
space-around 侧轴平分剩余空间
space-between 侧轴平分剩余空间,侧轴头尾贴边

弹性项设置

子项份额设置

给弹性项设置flex属性可以配置份额

比如我们设置一下item的flex属性为1,2,3,就可以使得盒子按照比例1:2:3分配剩余空间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.item1{
background-color: orange;
height: 100px;
flex: 1;
}
.item2{
background-color: pink;
height: 100px;
flex: 2;
}
.item3{
background-color: skyblue;
height: 100px;
flex: 3;
}

子项自身在侧轴的排列方式

在子项设置align-self属性,可以使得弹性项自己在侧轴上的排列方式,可以脱离弹性容器的侧轴排列的限制

举个例子,比如说我们希望单独一个元素排列方式不同,则可以在子项上设置自身的排列方式

我们给最后一个子项设置一个侧轴属性

1
2
3
.item-spc{
align-self: flex-end;
}

可以看到如下效果


弹性项排序

用属性order可以控制弹性项的排序,order值越小,排列越靠前,order的默认值为0

随缘更新,如有错误欢迎指正