Skip to content

0x004-理解浮动布局

浮动

浮动元素不同于普通文档流的元素,它们的高度不会加到父元素上。

浮动是为了实现文字围绕浮动元素排列的效果。在段落里浮动图片时,段落的高度并不会增长到能够容纳该图片。也就是说,如果图片比段落文字高,下一段会直接从上一段的文字下面开始,两段文字都会围绕浮动的图片排列。

示例: https://jsfiddle.net/chuangchen/agzteopx/114/

截屏2024-05-24 22.47.45.png

由于浮动元素的高度不会加到父元素上,因此可能有如下问题(示例: https://jsfiddle.net/chuangchen/agzteopx/117/),实际上恰好体现了浮动布局设计的初衷:

截屏2024-05-24 22.54.46.png

清除浮动

清除浮动的解决方法:

1). 使用和浮动配套使用的 clear属性,将一元素放到主容器的末尾。示例 clear:both

  • clear: both声明让该元素移动到浮动元素的下面,而不是侧面
  • clear的值还可以设置为left或者right,这样只会相应地清除向左或者向右浮动的元素。因为空div本身没有浮动,所以容器就会扩展,直到包含它,因此也会包含该div上面的浮动元素

clearfix.png

2). 为了更优雅(不额外增加html标签),可以使用::after伪元素选择器,就可以快速地在DOM中在容器末尾添加一个元素,而不用在HTML里添加标记。
示例代码

css
.clearfix::after {
  display: block;
  /*content的值包含了空格。当然,空字符串("")也能生效,但是在旧版的Opera浏览器中有个隐藏的bug,需要添加一个空格字符才能解决。我倾向于保留这个空格,毕竟它也不容易被用户发现。*/ 
  content: " "; 
  clear:both;
}
.clearfix::after {
  display: block;
  /*content的值包含了空格。当然,空字符串("")也能生效,但是在旧版的Opera浏览器中有个隐藏的bug,需要添加一个空格字符才能解决。我倾向于保留这个空格,毕竟它也不容易被用户发现。*/ 
  content: " "; 
  clear:both;
}

清除浮动带来的容器折叠问题

清除浮动还有个一致性问题没有解决:浮动元素的外边距不会折叠到清除浮动容器的外部,非浮动元素的外边距则会正常折叠。

clear: both;marign-bottom

使用display: table而不是display: block。给::before和::after伪元素都加上这一属性,所有子元素的外边距都会包含在容器的顶部和底部之间。

css
/*让 ::before和::after微元素都显示出来*/
.clearfix::before,
.clearfix::after {
  display: table;
  content: " ";
}
/*只有::after微元素需要清除浮动*/
.clearfix::after {
  clear: both;
}
/*让 ::before和::after微元素都显示出来*/
.clearfix::before,
.clearfix::after {
  display: table;
  content: " ";
}
/*只有::after微元素需要清除浮动*/
.clearfix::after {
  clear: both;
}

在清除浮动时使用display: table能够包含外边距,是因为利用了CSS的一些特性。创建一个display: table元素,也就在元素内隐式创建了一个表格行和一个单元格。因为外边距无法通过单元格元素折叠(参见第3章),所以也无法通过设置了display: table的伪元素折叠。

浮动导致的对齐问题

例如现有浮动盒子1、2、3,浮动盒子3没有按预期换行,原因是盒子2比盒子1矮一些。

如何处理:

  • 清除第奇数个元素的浮动
css
.media {
  float: left;
  width: calc(50% - 1.5em);
  margin-right: 1.5em;
}
.media:nth-child:(odd) {
  clear: left;
}
.media {
  float: left;
  width: calc(50% - 1.5em);
  margin-right: 1.5em;
}
.media:nth-child:(odd) {
  clear: left;
}

BFC

示例代码:

html
<div class="media">
      <img height="80" src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png">
    </div>
    <div class="media-body">
      <h4>
        故事
      </h4>
      <p>当夜幕降临,星光点点,风吹草动。一只小兔子蹦蹦跳跳地穿过田野,尾巴翘翘地在空中摇摆着。眼前的世界充满了神秘和未知,小兔子充满好奇心地探索着前方的道路。它仿佛在追逐着什么,驱使着它勇敢向前。在这个夜晚,小兔子将会经历怎样的冒险呢?让我们拭目以待
      </p>
</div>

// css
.media {
  background: lightgrey;
  float: left;
}
<div class="media">
      <img height="80" src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png">
    </div>
    <div class="media-body">
      <h4>
        故事
      </h4>
      <p>当夜幕降临,星光点点,风吹草动。一只小兔子蹦蹦跳跳地穿过田野,尾巴翘翘地在空中摇摆着。眼前的世界充满了神秘和未知,小兔子充满好奇心地探索着前方的道路。它仿佛在追逐着什么,驱使着它勇敢向前。在这个夜晚,小兔子将会经历怎样的冒险呢?让我们拭目以待
      </p>
</div>

// css
.media {
  background: lightgrey;
  float: left;
}

截屏2024-06-05 09.10.28.png

怎样修改为下图的效果:
截屏2024-06-05 09.10.42.png

这样引入了BFC(块级格式化上下文(block formatting context, BFC):

BFC是网页的一块区域,元素基于这块区域布局。虽然BFC本身是环绕文档流的一部分,但它将内部的内容与外部的上下文隔离开。虽然BFC本身是环绕文档流的一部分,但它将内部的内容与外部的上下文隔离开。BFC外面的元素产生外边距折叠。

(1) 包含了内部所有元素的上下外边距。它们不会跟BFC外面的元素产生外边距折叠
(2) 包含了内部所有的浮动元素。
(3) 不会跟BFC外面的浮动元素重叠

给元素添加以下的任意属性值都会创建BFC

  • float: left或right,不为none即可。
  • overflow:hidden、auto或scroll,不为visible即可。
  • display:inline-block、table-cell、table-caption、flex、inline-flex、grid或inline-grid。拥有这些属性的元素称为块级容器(block container)。
  • position:absolute或position: fixed。

只要给媒体正文创建BFC,网页的布局就会符合预期。通常是给元素设置overflow值——hidden或者auto。 示例:JSFiddle - Code Playground

css
.media-body {
 overflow: auto;  
}
.media-body {
 overflow: auto;  
}