浮动float

float的意思是浮动, 主要用于实现文字环绕图片

浮动

浮动元素会向左/右移动, 直到它的外边缘碰到包含框或另一个浮动框的边框为止.

float有四种值

  • none : 默认值, 不浮动
  • right: 向右浮动
  • left : 向左浮动
  • inherit: 继承父元素的float值, IE不支持

根据常规流和格式化上下文的特性, 浮动框脱离常规流(normal flow), 它会影响到内联框的排列, 但不会影响到块级框.

这是因为, 在布局浮动元素时, 一旦普通流中出现了浮动元素, 一个框盒首先根据常规流来布局, 然后脱离常规流, 向左/右移动. 这导致沿着它边上的文本content都将"浮动". 即, 其它盒子看不到被float的盒子, 但其它盒子中的文本却能看到它.

# 高度塌陷

浮动有一个很大的副作用, 就是当浮动框高度超出容器框的时候, 容器不会自动升高来闭合浮动元素, 这被称为容器的高度塌陷现象.

# 浮动卡住

其它元素在预期外, 受到浮动的影响, 被浮动元素卡住. 或一行内浮动元素放不下, 换行后, 被高度不一致的元素卡住.

清除浮动 / 闭合浮动

很多人都已经习惯称之为清除浮动, 但是确切地来说是不准确的.

  • 清除浮动: 对应的单词是 clear, 对应CSS中的属性是 clear: left | right | both | none
  • 闭合浮动:更确切的含义是使浮动元素闭合, 从而减少浮动带来的影响. 这一概念与BFC有关.

闭合浮动正是为了解决高度塌陷问题的, 单单清除浮动还不足够.

# 最佳实践 | after法

.clearfix:after {
  content:" ";
  display:block;
  visibility:hidden;
  height:0;
  clear:both;
}
.clearfix { *zoom:1; }
  • ::after是伪元素, 它只对块级元素有效.
  • display:block, 使生成的元素以块级元素显示, 占满剩余空间
  • visibility:hidden, 隐藏content
  • height:0, 避免生成内容破坏原有布局的高度
  • zoom:1, 触发IE的hasLayout, 后者相当于是IE中的BFC机制

这本质上是一个空div法的变形, 但更符合语义和结构.

以下是可选的改进

## 避免margin重叠

即再添加一个:before, 其样式设置与:after一致.
当该容器中的内部元素float创建了BFC, 内部元素的margin-top就会和上一个盒子的margin-bottom叠加

## 零宽度空格

.clearfix:before, .clearfix:after {
  content:"/200B";
  display:block;
  height:0;
  clear:both;
}
.clearfix { *zoom:1; }
  • content:"/200B", Unicode字符里中的零宽度空格, 也就是U+200B, 这个字符本身是不可见的, 相当于设置了visibility:hidden

这个改进只是少写几行代码而已. 但也许可能在某些页面下, 并不支持内嵌的CSS使用Unicode字符,所以并不总是安全的.

## Bootstrap

Bootstrap采用了Nicolas Gallagher的方案.

.cf:before, .cf:after {
  content:" ";
  display:table;
}
.cf:after { clear:both; }
.cf { *zoom:1; }

bs中的less源码为

.clearfix() {
  &:before,
  &:after {
    content: " ";
    display: table;
  }
  &:after {
    clear: both;
  }
}

# 空div法

在浮动元素末尾添加一个空div, 设置其为clear: both

  • 优点: 通俗易懂, 容易掌握
  • 缺点: 添加了太多无意义的空标签, 有违结构与表现的分离的原则, 在后期维护中将是噩梦.

# br法

在浮动元素末尾添加一个br, 设置br的clear:all

  • 优点: 比空标签方式语义稍强, 代码量较少
  • 缺点: 同样有违结构与表现的分离, 不推荐使用

以下几个办法都是在试图触发BFC

# 父元素也设置浮动

  • 优点: 不存在结构和语义化问题, 代码量极少
  • 缺点: 使得与父元素相邻的元素的布局会受到影响, 不可能一直浮动到body, 不推荐使用

# 父元素设置display:table

  • 优点: 结构语义化完全正确, 代码量极少
  • 缺点: 盒模型属性已经改变, 由此造成的一系列问题, 得不偿失, 不推荐使用

# overflow法

通过设置父元素overflow值设置为hidden; 在IE6中还需要触发 hasLayout , 例如 zoom:1

  • 优点: 不存在结构和语义化问题, 代码量极少
  • 缺点: 内容增多时候容易造成不会自动换行导致内容被隐藏掉, 无法显示需要溢出的元素; 04年POPO就发现overflow:hidden会导致中键失效

或者设置为overflow:auto

  • 缺点: 多个嵌套后, firefox某些情况会造成内容全选; IE中 mouseover 造成宽度改变时会出现最外层模块有滚动条等, firefox早期版本会无故产生focus等

References

Todo

  • 补齐代码
  • 演示一下margin重叠问题