盒子模型有三种主要类型:block
,inline
,inline-block
。我们回顾一下三者的特性,请问如何让两个盒子既可以设置宽高,又能在同一行摆放?
block
类型的盒子,会独占一行;inline
类型的盒子不能设置宽度;好像只有inline-block
满足要求了。但是inline-block
有一个缺点,基于inline-block
在同一行摆放的盒子,会有固定的间隙,且无法通过修改外边距消除:示例:
在示例中,我们将三个div设为了inline-block
,并且使它们的外边距为0。可是最后我们的盒子依然有间隙,此时就需要使用浮动了。
我们先展示一下浮动的效果:
可以看到,我们不仅将块级元素直接放在了同一行,而且它们之间没有间隙。
float属性用于创建浮动框,被浮动的元素会被移到一边,直到触及边缘,或者触及到另一个浮动元素的边缘。
属性值:
属性值 | 描述 |
---|---|
none | 元素不浮动(默认值) |
left | 元素向左浮动 |
right | 元素向右浮动 |
浮动的基本使用其实非常简单,无非就是向左浮动还是向右浮动。
向左浮动:
三个小盒子依次挨着浏览器的左侧
对比一下两张图片,有一个小细节,三个盒子的顺序反转了,这是为什么?
首先,我们的代码从上往下的顺序是蓝,粉,黄。浮动会根据代码顺序,依次进行浮动,什么意思呢?
对于左浮动:
由于蓝色盒子在代码最上方,于是蓝色盒子第一个靠向左边,贴紧了浏览器左边;
当轮到粉色盒子时,它第二个浮动,于是它会向左靠近,直到遇到蓝色盒子的边缘;
当轮到黄色盒子时,它第三个浮动,于是它会向左靠近,直到遇到粉色盒子的边缘;
最后从左到右就是蓝,粉,黄。
对于右浮动:
由于蓝色盒子在代码最上方,于是蓝色盒子第一个靠向右边,贴紧了浏览器右边;
当轮到粉色盒子时,它第二个浮动,于是它会向右靠近,直到遇到蓝色盒子的边缘;
当轮到黄色盒子时,它第三个浮动,于是它会向右靠近,直到遇到粉色盒子的边缘;
最后从左到右就是黄,粉,蓝。
我们也可以对不同盒子设置不同方向的浮动:
设置左浮动的盒子就靠着左边,设置右浮动的盒子就靠着右边了。
以上就是浮动的基本用法,是不是效果很好?
但是其也会带来不少麻烦,本博客只有1/4讲解浮动的使用,剩下的3/4就是讲解如何处理浮动带来的麻烦了。
所谓的标准流,就是标签按照规定好的默认方式排列,即遵循以下规则:
1.块级元素会独占一行,从上向下顺序排列
2.行内元素会按照顺序,从左向右排列,碰到父级元素边缘则自动换行
我们在之前学到的布局方式,就是标准流布局,这也是最基本的布局方式。
被设置了浮动的元素,会脱离标准流,按照浮动的规则排列。
由于浮动的元素脱离了标准流,它不会占用标准流的位置
首先,我们有三个盒子,它们目前都没有设置浮动,都处于标准流中,接下来我们对蓝色和粉色盒子设置浮动:
可以看到,最终效果并不是单纯的蓝色盒子与粉色盒子向左侧浮动,而黄色盒子的布局也受到了影响。
在这个布局中,蓝色盒子与粉色盒子脱离了标准流,而黄色盒子依然处于标准流中。此时蓝色盒子与粉色盒子不会保留其原先在标准流中的位置,所以黄色盒子就跑到了它们的下面,看起来就好像蓝色和粉色盒子浮起来了。这就是脱标。
浮动的盒子只会影响浮动盒子后面的标准流,不会影响前面的标准流
这句话又是啥意思?我们依然用案例来解释:
请注意:上面的粉色盒子是设置了浮动的!
为什么我们的粉色的盒子设置了浮动和没设置浮动的位置一样呢?
这是因为,蓝色盒子处于标准流中,虽然粉色盒子脱标了,但是其无法影响到其上方的标准流。
这也就是我们的影响范围导致的结果,虽然粉色盒子脱标后,其按照浮动规则排列,向左侧靠,直到遇到了浏览器的边缘。
而蓝色盒子是标准流中的块级元素,具有独占一行的属性,由于粉色盒子无法影响到其上方的标准流,所以最后其按照标准流独占一行。
我们在把黄色盒子加回来:
可以看到,由于黄色盒子是粉色盒子后面的元素,它会被粉色盒子的浮动影响,最后到了粉色盒子的下方。这也证明了粉色盒子确实浮动了。
最后我提一个问题:如果我现在在黄色盒子下方加一个浮动的绿色盒子,请问它会出现在粉色盒子的右侧,还是黄色盒子的下方?
答案是黄色盒子的下方,一样的规则:
由于黄色盒子是标准流,而绿色盒子为浮动,绿色盒子的浮动无法影响到其上方的标准流,所以绿色盒子会在黄色盒子下方按照浮动规则排列。
所以在一个范围内,要浮动就最好全部浮动,避免带来标准流与浮动的错乱,这种堆叠关系完全可以依靠盒子里面嵌套盒子来完成,而不是依靠脱标的特性。
我们浮动的目的,是让盒子遵循浮动的规则并排排列,而不是为了让其他元素跑到它下面!
我们先依靠一个案例来引入问题:
现在我们有一个大盒子father,以及四个小盒子,四个小盒子全部浮动,目前效果是这样的:
接下来我们去掉father的高:
我们可以看到,父级元素的高度没有了,只剩下一个宽度600px的边框。
浮动的盒子,由于其脱标的特性,相当于父级盒子中不存在这些浮动的盒子,导致无法撑开父级元素的高度。
你会说,那我们直接给父亲高度不就好了,但是很多时候,我们父亲的高度是不确定的,比如这是一个淘宝的商品栏目,当我需要添加商品的时候,还要去再设置一次高度,这不是很麻烦吗?
我们理想中的状态是:子级盒子可以依照浮动的规则排列,但是又能撑开标准流中父级元素的高度。
想要达到这个效果,就需要清除浮动。
clear是CSS的一个属性值,其用于清除浮动对自身的影响。
属性值:
属性值 | 效果 |
---|---|
none | 允许周围有浮动元素(默认值) |
left | 自身必须低于所有左浮动元素 |
right | 自身必须低于所有右浮动元 |
both | 自身必须低于所有左浮动或右浮动元素 |
通过案例来讲解规则:
现在我们有一个左浮动的蓝色盒子,右浮动的粉色盒子,以及标准流中的黄色盒子。
接下来我们对黄色盒子设置clear: left
:
我们的黄色盒子出现在了蓝色盒子的下方,因为蓝色盒子是左浮动的,黄色盒子设置了clear: left
后,就会低于所有左浮动元素,这里就是低于蓝色盒子。
那么我们改成clear: right
会咋样?
那么黄色盒子就会低于所有右浮动元素,也就是低于粉色盒子了:
可以看到,黄色盒子此时就低于粉色盒子的下方了。
那么clear: both
就是,既要低于左浮动盒子,也要低于右浮动盒子:
在上图中,黄色盒子要同时低于左右浮动的盒子,所以不论是粉色盒子低了,还是蓝色盒子低了,黄色盒子都要往下走。
讲了这么多,我们的最终目的还是要让浮动的盒子把标准流的父亲撑开。
在上面的案例中,有一个非常非常非常重要的点,那就是黄色盒子处于标准流中!!!
这说明了,黄色盒子是可以撑开父亲高度的!
那么我们回到最初的案例:
现在我们在前四个浮动盒子的末尾加上一个10×10的小盒子,并设置clear: both
,此时小盒子就会低于所有盒子:
可以看到,我们的父亲盒子被撑开了!!!
这就是clear清除浮动的基本原理!
其实我们刚刚最后的案例,就是额外标签法。
刚刚只是为了方便大家理解,我们为最后一个div设置了10×10的大小。但是其实这个div可以没有大小,但是依然存在:
通过这种方式,我们就可以得到一个盒子,其没有大小,又真实存在,而且出现在所有浮动盒子的下方,最后撑开了父亲的高度。
刚刚那个方法有一个小毛病,就是我们每一个父亲盒子都要去写一个这样的尾部盒子,会略有些繁琐。在此我们可以利用:after伪元素,它是一个不存在于文档树中的元素,但是真实存在于页面中,它的用法不具体展开讲解伪元素本身的用法,而是讲解伪元素在此处的用法。
其功能就是,在一个盒子的最末尾添加一个元素。
其最终效果也是相当于在箭头指向处添加了一个看不见,又真实存在的元素。
它的使用比较方便,只需要在父级元素调用clearfix
这个类即可,不需要再写额外的标签了。
代码:
<style>
.clearfix:after {
content: "";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
style>
双伪元素和:after伪元素是基本一致的,只是额外加了一个:before伪元素。
其最终效果相当于在父级盒子的头尾各自存在一个看不见的元素,撑开了父亲的高度。
代码:
<style>
.clearfix:before,
.clearfix:after {
content: "";
display: table;
}
.clearfix:after {
clear: both;
}
style>
BFC(Block Formatting Context),块级格式化上下文,它规定了内部的块级元素的布局方式,默认情况下只有根元素(即body)一个块级上下文。
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素;外面的元素也不会影响到容器里面的子元素;
计算BFC的高度时,浮动元素也参与计算。
首先我们要知道怎样创建BFC,一个BFC可以被显式触发,只需满足以下条件之一:
float的值不为none;
overflow的值不为visible;
position的值为fixed / absolute;
display的值为table-cell / table-caption / inline-block / flex / inline-flex。
其实刚刚的内容你看不太懂也没关系,只需要记住我高亮标注的那句话:BFC是会把浮动元素当作自己的内容的。
另外,你也需要知道,我刚刚列举的,哪些情况下元素会变成BFC。
现在我们只需要将父级元素变成BFC,我们的浮动元素的大小就会被计算进去,父级元素自然就会被撑开了。
在以把父亲撑开为目的情况下,我们最常使用的是overflow,只需对父级元素添加一个overflow属性,且属性值不为visible,那么其大小就会被撑开了,我们平常使用的属性值为hidden:
这就是最后一种清除浮动的方式了。