前言
在我们刚开始学习前端的时候,都知道一个页面可以由几个部分组成:html、css和js。而在程序员中有句话:“只要css写的好,那么js就可以写的很轻松”,为了写好css呢接下来我们来聊聊css几个重要布局之一的浮动布局和BFC容器。
为了让代码简洁一点下面的代码都将其余部分先省略,只展示body和style部分
1. 浮动
1.1 浮动的效果和使用
在css中有一个特殊的属性:浮动(float),这个属性在被设计的时候是为了让网页中的文字有环绕效果。 下面先简单了解一下float属性几个常用属性值的效果
left:让元素向左边浮动
right:让元素向右边浮动
下面我们来看一段代码和效果展示:
<body>
<div class="box">
<img width="300" height="400" src="https://tse4-mm.cn.bing.net/th/id/OIP-C.nd6x1jLwJlLWqWBOf_a9ogHaLG?w=202&h=303&c=7&r=0&o=5&dpr=1.5&pid=1.7" alt="">
<p>
综合美联社、路透社等西方媒体报道,民主党政府松口消息17日经由一名不愿公开姓名的美国政府官员和数名知情人士之口放出。白宫未予确认。
知情人士称,美国“开绿灯”后,乌克兰对俄罗斯本土的第一次远程打击可能使用最大射程约300公里的ATACMS导弹,打击库尔斯克州一带的目标。
乌军今年8月对库尔斯克州发起地面攻势,这是乌克兰危机2022年2月全面升级以来,乌军首次越过边境线大举进攻俄罗斯本土。俄军近期在库尔斯克州投入更多兵力试图驱逐乌军,西方盟友担心战局朝不利于乌方的方向发展。
乌克兰总统弗拉基米尔·泽连斯基17日在晚间电视讲话中说:“今天许多媒体报道说我方已获准采取‘恰当行动’。不过,实施打击不是靠说的。这种事情不会公布。导弹自己会说话。”
很长一段时间以来,泽连斯基不断请求美国放开对使用美制武器打击俄纵深目标的限制,其所求包括ATACMS、高机动性火箭炮系统(海马斯)、F-16战斗机等先进武器。而美方在最初“犹豫”过后,一步步松口。比如,去年10月同意提供射程165公里的ATACMS导弹,今年初开始输送射程300公里的ATACMS导弹。
按照路透社的说法,乌克兰危机升级后两年多时间里,民主党政府一直没允许乌军使用美国援助的武器打击俄境内目标,但在今年5月俄军进攻乌克兰哈尔科夫州后“秘密授权”乌军使用这类武器打击俄军用于攻击哈尔科夫州的军事设施。
一些美国官员先前对允许乌军使用远程武器打击俄腹地是否能影响战局整体走势表示质疑。按照路透社的说法,当下俄军在战场上占据优势,各方敦促俄乌双方尽快进行停火谈判,若谈判能启动,美方此举或可增加乌方筹码。
</p>
</div>
</body>
在上面的代码中我们可以知道由于img和div都是属于块级标签,在文档流中它们的排列顺序是从上到下,从左到右的,那么我们如果想要让文字呈现环绕图片的效果,就可以为img增添float属性,接下来我们为其添加float属性看看效果:
//其余代码还是一样,只是为img添加属性,只展示style标签中的内容
<style>
img{
float: left;
}
</style>
这时候我们可以发现,在为img添加了float: left属性之后,文字就出现了环绕图片的效果,而这正是float所存在的意义。那么就有同学可能会问了,为什么为img增加了float属性之后就可以出现这种效果了呢?为了解答这个问题,我们得先了解一下文档流这个东西。
文档流概念:网页是一个多层的结构,一层摞着一层通过CSS可以分别为每一层来设置样式。作为用户来讲只能看到最顶上一层、这些层中,最底下的一层称为文档流,文档流是网页的基础,我们所创建的元素默认都是在文档流中进行排列对于我们来说元素主要由两个形态:在文档流中,脱离文档流。
块级元素在文档流中的特点:
- 块元素会在页面中独占一行(自上向下,从左到右排列)
- 默认宽度是父元素的全部(会把父元素撑满)
- 默认高度是被内容撑开(子元素)
在了解完了文档流以及块级元素在其中的排列方式之后,我们就可以来看看float为什么可以让文字环绕了。float能让该图片被文字环绕是因为float让该元素脱离了文档流,但是并不会覆盖文字,文字会围绕着图片排版。浮动能让块级元素水平排列。
1.2 浮动带来的影响
众所周知,任何程序都不是完美的,既然有利就有弊,下面我们来看看浮动所带来的影响。
首先呢我们先定义一个ul,在里面放上三个不同颜色的li。
<style>
ul{
list-style: none;
margin: 0;
padding: 0;
}
li{
width: 200px;
height: 50px;
}
li:nth-child(1){
background-color: red;
}
li:nth-child(2){
background: yellow;
}
li:nth-child(3){
background-color: green;
}
</style>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</body>
可以看到ul中的元素从上到下排开,我们接下来让这三个li一字排开,只需要在li中添加display:inline-block即可。
<style>
ul{
list-style: none;
margin: 0;
padding: 0;
}
li{
width: 200px;
height: 50px;
display: inline-block;/*行内样式不能设置宽高,所以设置行内块*/
}
li:nth-child(1){
background-color: red;
}
li:nth-child(2){
background: yellow;
}
li:nth-child(3){
background-color: green;
}
</style>
这时候虽然将li一字排开但是我们会发现三个li中间留有间隙,这是为什么呢?这是因为三个li标签前面的空格在执行时会被认为是文字,这时候我们可以不用display,而是用float来让三个元素一字排开。
li{
width: 200px;
height: 50px;
float: left;
}
接下来让我们来猜猜li的父容器的高度是多少?可能有同学会说是50,又或者是150。不对,它的高度是0。这里有同学就会问了为什么高度是0呢?这是因为三个li由于被设置了float属性,那么这三个li就脱离了文档流,自然就不在父容器ul的内部,而ul的高度是由子元素所撑开的,这时候内部没有了li,那么高度自然就是0了(后面需要用到这点),下面我们来浏览器中看看。
在设置完了上面的li的样式之后,我们再到ul的下面设置一个紫色的box盒子。
<style>
ul{
list-style: none;
margin: 0;
padding: 0;
}
li{
width: 200px;
height: 50px;
float: left;
}
li:nth-child(1){
background-color: red;
}
li:nth-child(2){
background: yellow;
}
li:nth-child(3){
background-color: green;
}
.box{
width: 500px;
height: 100px;
background-color: blueviolet;
}
</style>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<div class="box"></div>
</body>
在展示代码效果之前,大家可以猜一下效果是什么样子的,有同学可能会猜测展示效果应该是box这个盒子展现在上面三个li的下面,下面我们来看看是不是这样的:
这时有同学可能会问了,为什么box不是出现在上面三个li的下面而是从顶部开始的呢?在前文中我们提到了,用float会让元素脱离文档流,而我们在li中设置了float,这样导致li脱离了文档流,而ul是靠li撑开的。由于li不在其中,导致ul容器的高度为0。根据文档流中的布局排列规则,box是块级元素那么它就会从上到下进行排列,而它上面ul的高度为0,所以box就会排在它的后面从而被上面三个li所覆盖,而这正是浮动所带来的负面影响。
浮动的负面影响: 浮动元素的高度不计算在父容器的高度之内,这就会导致父容器的后续容器布局和该浮动元素重叠
1.3 清除浮动(意思是清除浮动带来的负面影响,不是消除浮动效果)
在上文中我们了解了浮动所带来的浮动影响,那么我们有没有办法来清除浮动效果呢?这是有的而且还不止一种,下面我们来结合代码效果和上文负面影响的效果一一讲解。下面代码的展示效果的如下:
1.3.1 直接设置父容器高度
顾名思义,通过直接设置父容器高度可以让浮动的负面效果被清除。在上文中我们说到box之所以会被覆盖,是因为ul的高度是0,下面我们来给ul设置一下高度:
<style>
ul{
list-style: none;
margin: 0;
padding: 0;
height: 50px;
}
</style>
1.3.2 在浮动元素的最末尾添加子容器,在子容器上做清除浮动
这时候可能会有人疑惑了,明明是该元素有浮动样式,为什么要在浮动元素末尾加子容器并且在上面做清除浮动呢?
在这里,大家可以简单的理解为:这个过程就类似于函数执行的过程,当定义了float之后,就相当于函数开始执行,而这个末尾的子容器就相当于函数中的return,可以清除浮动的负面影响。
下面我们来看一下代码的例子:
<style>
ul{
list-style: none;
margin: 0;
padding: 0;
}
li{
width: 200px;
height: 50px;
float: left;
}
li:nth-child(1){
background-color: red;
}
li:nth-child(2){
background: yellow;
}
li:nth-child(3){
background-color: green;
}
.box{
width: 500px;
height: 100px;
background-color: blueviolet;
}
.clear{
cleaer: both;
}
</style>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<div class="clear"></div>
</ul>
<div class="box"></div>
</body>
在上面的代码中,我们在ul结束标签的前面定义了一个clear用来清除浮动带来的负面影响
1.3.3 使用伪元素(比较推荐用这个)
在css中伪元素主要用于添加装饰性的效果,例如添加前缀内容、创建边框效果等,除了这些之外,它还可以用来清除浮动所带来的负面影响。下面我们来通过一段代码来展示一下:
<style>
ul{
list-style: none;
margin: 0;
padding: 0;
}
li{
width: 200px;
height: 50px;
float: left;
}
li:nth-child(1){
background-color: red;
}
li:nth-child(2){
background: yellow;
}
li:nth-child(3){
background-color: green;
}
.box{
width: 500px;
height: 100px;
background-color: blueviolet;
}
ul::after{
clear: both;
display: block;/*加了这个才能清除,做到.clear的效果*/
}
</style>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<div class="box"></div>
</body>
ps:用伪类选择器必须加上display: block;才能有清除浮动效果
在上面的效果图中我们可以看到,伪类选择器相当于是在最后一个li的后面添加了一个元素,并且拥有clear属性,这一点就跟上面的方法很像,这种方法是比较方便也比较推荐的。
1.3.4 给后面被影响元素添加clear属性
由于box收到了float的影响,所以我们要给box添加clear属性,我们下面来看代码:
<style>
ul{
list-style: none;
margin: 0;
padding: 0;
}
li{
width: 200px;
height: 50px;
float: left;
}
li:nth-child(1){
background-color: red;
}
li:nth-child(2){
background: yellow;
}
li:nth-child(3){
background-color: green;
}
.box{
width: 500px;
height: 100px;
background-color: blueviolet;
clear: both;
}
</style>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<div class="box"></div>
</body>
效果如同上面的例子。
2. BFC容器
2.1 创建BFC容器的方法
说到容器这个概念,大家都知道它是用来储存东西的,BFC也不例外,它是一个拥有隔离空间的容器。在知道了BFC是什么之后,我们来聊聊它为什么会被创建出来呢,下面我们来看一段代码:
<style>
*{
margin: 0;
padding: 0;
}
.parent{
width: 100vw;
height: 400px;
background-color: blueviolet;
margin-top: 100px;
}
.child{
width: 100vw;
height: 200px;
background-color: rgb(202, 164, 11);
margin-top: 50px;
}
</style>
<body>
<div class="parent">
<div class="child"></div>
</div>
</body>
大家可以看上面代码先想象一下产生的效果是什么样子的,大家想到的可能是下面这个样子:
而实际运行的效果并不是这个样子,下面我们来看看实际运行效果:
而为什么会是这样子呢?这就涉及到了这门语言的一个bug了,在这门语言设计的时候,当我们使用margin-top用来调整元素在页面当中的位置时,会出现父子容器margin重叠问题,效果图如下:
那么为了解决这一问题,官方就设计了BFC用来解决这一问题,那么如何设置BFC容器呢,就是在需要进行隔离的元素style上添加属性即可,下面有几种方法创建BFC容器:
以下几种属性的这几种属性值可以创建BFC容器
- overflow: hidden || auto || overlay || scroll
- 定位(position): absolute || fixed
- display: inline-xxxx(大部分可以) || flex || grid
- display: table || table-xxx
- 浮动(float): right || left
那么我们来试试,将父容器创建为BFC容器试试
<style>
.parent{
width: 100vw;
height: 400px;
background-color: blueviolet;
margin-top: 100px;
overflow: auto;/*将容器变成bfc容器 */
/* position: absolute;将容器变成bfc容器 */
/* display: flex;将容器变成bfc容器 */
/* display: table;将容器变成bfc容器 */
/* float: right;将容器变成bfc */
}
</style>
在添加了 overflow: auto; 属性之后我们可以看到效果是我们所预期的效果,这就是BFC容器的作用。而BFC容器除了解决margin问题,还有一个小彩蛋,BFC也可以清除浮动。
我们继续沿用上面清除浮动所示例的代码,在ul中添加overflow属性:
<style>
ul{
list-style: none;
margin: 0;
padding: 0;
overflow: hidden;/* 定义成bfc容器,使得容器ul拥有了高度不影响box */
}
li{
width: 200px;
height: 50px;
float: left;/*当有多个浮动时,会一字排开*/
}
li:nth-child(1){
background-color: red;
}
li:nth-child(2){
background: yellow;
}
li:nth-child(3){
background-color: green;
}
.box{
width: 500px;
height: 100px;
background-color: blueviolet;
}
</style>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<div class="box"></div>
</body>
我们可以发现将ul变成BFC容器之后,浮动所带来的负面影响也清除了。
2.2 BFC 特征
在经过了前面对BFC的学习后,我们可以总结一下BFC容器拥有下面几个特征:
- bfc 容器时让处于 bfc 内部的元素与外部的元素相互隔离时,使外部元素的定位不会相互影响
- 解决外边距重叠问题
- bfc 容器在计算高度时,会将浮动元素的高度也计算在内,碰巧可以解决浮动的负面影响
谢谢各位的观看,希望能帮到大家理解浮动和BFC,喜欢的话点个赞吧!