css中“流”与浮动

“流”

什么是“流”,我们通过一个实例来认识一下“流”。

1
2
3
4
5
6
7
8
9
10
11
12
/* 将一个div元素设置为同父元素一样宽,高度为50px */
.div {
width: 100%;
height: 50px;
}
/* 上面的写法仔细一看,可以发现没有必要这么写,完全可以按照下面这种写法 */
.div {
height: 50px;
}
/* 究其原因,div元素是块状元素,元素会自动占一行,这种特性就是流的表现形式之一 */

流特性就像在有水的容器里面放入木块。放入一个块状元素,就会自动占满一行;放入行内元素,元素就会按照从左往右,在一行内依次排开。

css流

浮动

css中的float属性会把元素向左或者向右浮动。浮动的初衷是为了实现文字环绕效果。float会破坏上面的流特性,让原本按照流特性布局的元素,重新按照浮动布局。

float

float属性在使用之后,元素本身的某些特性会发生更改,也会增添一些新特性。

包裹性

float元素会“收缩到合适”,这里的合适,理解为inline-block元素的特性,会自动根据子元素来定义宽和高。通常包裹性可以理解为两个方面,一个是“包裹”,一个是“自适应”。

1
2
3
4
5
6
<div class="contain">
<div class="float">
<img src="https://fallbacks.carbonads.com/nosvn/fallbacks/731050e6bd3fc6979e1cb1a972294dae.png">
测试文字测试文字测试文字测试文字测试文字
</div>
</div>
1
2
3
4
5
6
7
8
9
10
.contain {
width: 200px;
}
.contain img {
width: 150px;
}
.float {
float: left;
}

当我们没有上面的测试文字的时候,我们就能发现float元素的宽度为150px,这就是float元素的包裹性;当我们添加上测试文字的时候,我们就会发现float元素的宽度为200px,这就是float元素的自适应性。

查看示例

块状性

元素在使用float属性的时候,且其值不为none的时候,元素的dispaly属性会自动成为block或者table。再去定义display属性的时候就是多余的操作。

1
<span class="float">测试文字</span>

1
2
3
4
.float {
float: left;
display: block; /* 多余 */
}

我们可以在js脚本中获取这个元素然后打印出其display属性的值来验证。

查看示例

没有margin合并

这个也很好理解,多个块状元素布局的时候,上下margin会自动合并,其值取决于margin较大的值。使用浮动的时候,会发现元素的margin不会合并。

1
2
3
4
5
<div class="margin">
<div class="box">margin-top合并</div>
<div class="box">margin-top合并</div>
<div class="box float">margin-top没有合并</div>
</div>

1
2
3
4
5
6
7
8
9
10
11
12
.float {
float: left;
}
.margin {
margin-top:50px;
height: 200px;
}
.box {
height:20px;
margin: 10px 0 20px;
border: 1px dashed #999;
}

你会发现第二个.box元素和上面的.box元素外间距为20px,而第二个和第三个.box元素的外间距为30px。

查看示例

破坏文档流

其主要表现在于,float元素会脱离文档流,导致父元素的高度坍塌。

1
2
3
<div class="father">
<div class="block float">高度坍塌</div>
</div>
1
2
3
4
5
6
7
8
9
10
.father {
margin-top: 20px;
border: 1px solid #0f0;
}
.block {
height: 50px;
}
.float {
float: left;
}

在页面中,你会发现.contain元素的父元素会出现高度坍塌。

查看示例

clear

css中有一个专门来处理float属性带来的高度坍塌等问题的属性,这个属性就是clear。官方对clear属性的解释是:“元素盒子的彼岸不能和前面的浮动元素相邻”。里面提到的前面到底是左面还是右面,这里和元素的float属性取值有关,取值为left的时候,就是左面,取值为right的时候,就是右面;还有就是clear属性并没有清楚浮动,浮动一直还在,只是改变了浮动的一些规则。关于这里面的疑问,下面例子会给出解释。

只能作用于块级元素

我们知道,利用伪元素来解决高度坍塌问题的方案,中间有一个很重要的属性,就是display属性必须设置为块级元素才能生效,也就是clear属性只有块级元素才能生效。

1
2
3
<div class="clearb father">
<div class="block float">解决高度坍塌</div>
</div>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.clearb::after {
height: 0;
content: '';
display: block;
clear: both;
}
.father {
margin-top: 20px;
border: 1px solid #0f0;
}
.block {
height: 50px;
}
.float {
float: left;
}

查看示例

margin-top失效

当我们前面的元素使用float的时候,当起元素使用了clear的时候,就会发现该元素的margin-top会失效。

1
2
3
4
5
<div class="margin">
<div class="box w50 float"></div>
<div class="box w50 float"></div>
<div class="box w50 clearl mt"></div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.margin {
margin-top:50px;
height: 200px;
}
.box {
height:20px;
margin: 10px 0 20px;
border: 1px dashed #999;
}
.w50 {
width: 50px
}
.mt {
margin-top: -999px;
}
.clearl {
clear: left;
}

查看示例

只能消除影响

因为clear属性作用的本质是让自己不和float元素在一行显示,并不是真正意义上的清除浮动。

BFC

块级格式化上下文(block formatting context ),如果一个元素具有 BFC特性,内部子元素再怎么翻江倒海,都不会影响外部的元素 。同时他也是一个结界,外面的一些影响也不会进入到该结界内部。

也就是说满足BFC特性的元素就无须使用 clear:both 属性去清除浮动对外部或者兄弟元素带来的影响了。
只要元素满足下面的任意一个条件,那么它就具有BFC特性。

  • 根元素;
  • float 的值不为 none;
  • overflow 的值为 auto、scroll 或 hidden;
  • display 的值为 table-cell、table-caption 和 inline-block 中的任何一个;
  • position 的值不为 relative 和 static。

overflow

要想彻底清除浮动的影响,最合适的属性不是clear而是overflow,一般使用overflow:hidden,利用 BFC 的“结界”特性彻底解决浮动对外部或兄弟元素的影响。上述BFC特性的条件很多,但其他的属性都会让元素产生“包裹性”,会影响原来元素的样式布局。

彩蛋

彩蛋示例图片1
彩蛋示例图片1

这个是之前主站M端我做的一个处理。选择城市后,因为城市名字不一样,所以宽度会发生变化,会影响后端元素的宽度,怎样仅用css动态的去处理,而不是依靠js去计算。

这里我就使用了float + overflow 然后解决了这个问题。

1
2
3
4
5
6
7
8
9
<div class="egg">
<div class="left-area">北京</div>
<div class="right-area">测试文字</div>
</div>
<!-- 为了产生对比,我写了两个 -->
<div class="egg">
<div class="left-area">呼和浩特</div>
<div class="right-area">测试文字</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.egg {
height: 30px;
line-height: 30px;
margin: 20px;
}
.left-area {
background-color: #999;
height: 30px;
border-radius:5px;
float: left;
margin-right: 10px;
}
.right-area {
background-color: #999;
height: 30px;
border-radius:5px;
overflow: hidden;
}

查看示例

本文参考

《css世界》-张鑫旭著