清理
虽然浮动可以便于页面布局, 但同时会产生一些问题, 也就是常说的副作用浮动元素最常见的缺陷是: 父元素的高度塌陷和影响兄弟元素的位置
首先, 看看父元素的高度塌陷假设有一个容器, 其中两个子元素, 一个子元素向左浮动, 一个子元素向右浮动代码如下:
- .wrapper {border: 2px dashed #ccc;}
- .wrapper > p {
- width: 80px;
- height: 60px;
- border: 1px dashed #444;
- }
- .floatL {
- float: left;
- }
- .floatR {
- float: right;
- }
- box1
- box2
上述容器 wrapper 的高度为 auto, 且只包含浮动元素由于浮动元素脱离了文档流, 因此, 容器 wrapper 就相当于一个空标签, 其高度就会塌陷为零, 使得浮动元素溢出到容器外面如图 529 所示:
图 5-29 浮动导致容器高度塌陷
这种塌陷会影响甚至破坏布局, 如果父元素没有边框, 也不包含任何可见背景, 这个问题就很难被注意到, 但它却是一个很重要的问题
再来看看浮动元素如何影响兄弟元素的位置当容器的高度为 auto, 且只包含浮动元素时, 如果浮动元素的高度不相同, 而剩余空间足够容纳后面的元素时, 后面的元素就会上跳到剩余的空间代码如下:
- .wrapper {
- border: 2px dashed #ccc;
- }
- main {
- float: left;
- }
- aside {
- float: right;
- }
- footer {
- float: left;
- }
- main
- aside
- footer
上述的布局为两栏布局, 主栏向左浮动, 侧栏向右浮动, 并且侧栏的高度小于主栏的高度页脚便会上跳到侧栏的剩余空间如图 530 所示:
DB2tSqy9jJz8z4"height="136" lazyload="/uploadfile/Collfiles/20180222/20180222091355174.png" width="408" />
图 5-30 浮动使相邻元素上跳
很显然, 无论是高度塌陷, 还是影响兄弟元素的位置, 都不是使用浮动的目的浮动只是为了改变元素的布局, 却造成了不必要的影响因此, 需要清除浮动带来的影响
CSS 中, 把清除浮动影响所进行的处理, 叫做清理浮动 (或清除浮动) 一般有两种处理思路: 使用 clear 属性和让容器创建一个 BFC
每种思路中都包含多种方法, 但并不是每一种方法都尽善尽美, 接下来简单介绍这些方法的原理及适用场合, 可以根据实际情况, 选择合适的方法
使用 clear 属性
CSS 中的 clear 属性, 用来规定在元素的哪一侧不允许出现浮动元素, 可选值有 none | left | right | both, 默认值为 none, 表示不清除, 左右两侧均允许出现浮动元素 left 表示清除左侧, 在左侧不允许出现浮动元素; right 表示清除右侧, 在右侧不允许出现浮动元素; both 表示清除两侧, 左右两侧均不允许出现浮动元素
1)使用带 clear 属性的空元素
这也是 W3C 推荐使用的方法, 首先在 CSS 中定义一个清理的 class, 然后在浮动元素的后面, 使用一个空元素
或
如:
- .clear {
- clear: both;
- }
- box1
- box2
这种方法的优点是简单代码少浏览器兼容性好但是, 需要添加无语义的 html 元素, 违背了表现和内容相分离的原则, 代码不够优雅, 增加了后期维护的难度
2)借用邻接元素处理
什么都不做, 给浮动元素后面的那个元素添加 clear 属性假如在浮动元素后面有一个 p 元素, 可以为 p 元素添加 clear 属性, 来间接清除浮动如:
box1
box2
如果你很明确的知道接下来的元素是什么, 这个方法很不错, 它不需要 hack, 不添加额外的元素但是, 使用这种方法, 必须确保浮动元素后面确实有元素如果没有元素, 巧妇难为无米之炊, 也没有办法
3)使用 CSS 的 :after 伪元素
结合 :after 伪元素 (注意这不是伪类, 而是伪元素, 代表一个元素之后最近的元素) 和触发布局的 IE hack, 可以完美兼容当前各大主流浏览器
给包含浮动元素的容器添加一个 clearfix 的 class, 然后给这个 class 添加一个 :after 伪元素, 在元素末尾添加一个看不见的块元素, 让这个块元素来清除浮动
- .clearfix:after {
- content: ".";
- clear: both;
- display: block;
- height: 0;
- visibility: hidden;
- }
- box1
- box2
通过 CSS 伪元素, 在容器的末尾, 插入一个点 ".", 然后通过 height 和 visbility 属性使其不可见, 再为插入的点设置 clear 属性来清除浮动, 其原理跟上述两种方法类似
事实上, 上述方法插入任何内容, 都可以清除浮动当然, 如果插入一个空格的话, 就不必设置 height 和 visbility 属性, 代码会跟简洁如:
- .clearfix:after {
- content: "";
- clear: both;
- display: block;
- }
需要注意的是, 由于 IE7 及以下的版本不支持 :after 伪元素, 因此还需要为 .clearfix 设置 width 或 height 或 zoom 等一系列属性, 来触发布局 (即, 使 IE 私有属性 hasLayout 的值为 true) 如:
- .clearfix {
- *zoom: 1;
- }
在这些属性值中, zoom 用于设置元素的缩放比例, 取值 1 就会使用元素的实际尺寸因此, 使用 zoom: 1 既可以触发布局, 又不会对元素造成其他影响, 相对而言比较安全
让容器创建 BFC
可以利用 BFC 特性, 来清除浮动准确的讲, 说清除浮动不太合适, 应该说是让容器创建一个 BFC, 来包含浮动元素可以为容器设置以下属性, 来创建一个新的 BFC, 间接实现清除浮动的效果:
- float: left | right
- position: absolute | fixed
- overflow: hidden | auto | scroll
- display: inline-block | table-cell | table | flex | inline-flex
虽然设置上述属性都可以创建 BFC, 实现清除浮动的效果, 但是, floatpositiondisplay 属性可能会影响整体布局因此, 最常用的还是设置 overflow 属性
1)让容器浮动
让容器浮动后, 容器就会创建一个新的 BFC, 使它可以包含浮动元素计算 BFC 的高度时, 浮动子元素也参与计算因此, 容器的高度就表现正常, 其他框的位置也就正常了
- .wrapper {
- float: left;
- border: 2px dashed #ccc;
- }
让容器浮动后, 容器的高度确实没有塌陷, 但是, 容器的宽度可能会发生变化, 因为浮动元素的宽度是有其内容决定的(显式设置 width 属性者除外), 这可能会影响整体布局
2)为容器添加 position 属性
如果为容器设置 position: absolute 或 position: fixed, 容器就会创建一个新的 BFC, 使它可以包含浮动元素
- .wrapper {
- position: absolute;
- border: 2px dashed #ccc;
- }
另外, 由于 IE7 及以下的版本不支持 BFC, 还需要触发布局设置 position: absolute,IE6 和 IE7 都可以触发布局但是, IE6 不支持 position: fixed, 还需要为容器设置 zoom: 1, 来触发布局
3)为容器添加 overflow 属性
如果为容器设置 overflow: hidden 或 overflow: auto, 容器就会创建一个新的 BFC, 使它可以包含浮动元素
- .wrapper {
- overflow: hidden;
- border: 2px dashed #ccc;
- }
另外, 由于 IE7 及以下的版本不支持 BFC, 还需要触发布局在 IE7 中, 把 overflow 属性设置为 visible 之外的值, 就可以触发布局, IE6 则不行因此, 在 IE6 中, 可以为容器设置 zoom: 1, 来触发布局
这个方法不需要额外元素, 有着较好的语义性, 也比较简单但是, 需要要记住, overflow 属性不是为清除浮动而定义的, 注意不要隐藏了不该隐藏的内容或触发了不必要的滚动条
说明: BFC 与 hasLayout
从表现上来说, hasLayout 跟 BFC 的功能很相似, 只是 hasLayout 自身存在很多问题, 导致了 IE6-7 中的一系列 bug
既然 hasLayout 有着跟 BFC 相似的功能, 而 IE7 及以下的版本不支持 BFC 因此, 为了避免不同浏览器下的表现差异, 在实际开发中, 需要创建 BFC 的元素, 同时也要触发 hasLayout
事实上, 在实际开发中, 很多莫名其妙的问题, 都是由此产生的当然同样地, 如果一个元素没有创建 BFC, 也要尽量保证它没有触发 hasLayout
来源: https://www.2cto.com/kf/201802/722806.html