1

去年就看到张鑫旭大神的这篇文章,看了好几遍才看懂。后来再去想其中的一些原理,又忘了。于是打算把它记下来,一来做个备份,二来希望与君共勉。

这里我对文章以自己的理解做了一些精简,完整版的可以去http://www.zhangxinxu.com/wor...这里看

浮动的本质是:包裹性和破坏性

包裹性:换种说法就是让元素inline-block化,例如一个div标签默认宽度是100%显示的,但是一旦设置了float,则100%默认宽度就会变成自适应内部元素的宽度。
其实float就是一个带有方向的display:inline-block属性

破坏性:如果我们要理解浮动的破坏性,我们就要从浮动最原始的意义入手。浮动出现的意义其实只是用来让文字环绕图片而已,仅此而已。
浮动之所以会环绕含有float属性的图片是因为浮动破坏了正常的line boxes
我们先来了解一下line boxes模型。先看下面的一段普通的HTML代码:

<p>这是一行普通的文字,这里有个 <em>em</em> 标签。</p>

代码中的4种boxes(顺序从里到外):

  • inline boxes:

inline boxes不会让内容成块显示,而是排成一行,如果外部含inline属性的标签(span,a,cite等),则属于inline boxes,如果是个光秃秃的文字,则属于匿名inline boxes
  • line boxes:

一个一个的inline boxes组成了line boxes.这是浮动影响布局的关键box类型
  • content area:

content area是一种围绕文字看不见的box.content area的大小与font-size大小相关
  • containing box:

p标签所在的containing box,此box包含了其他的boxes

为什么浮动能使文字环绕图片?

默认情况下,图片与文字混排应该是这个样子:图片与文字基线对齐,图片与文字在同一行上,如下图所示:

上图中,图片为一个inline boxes,两边文字也是inline boxes。由于line boxes的高度是由其内部最高的inline boxes的高度决定的,所以这里的line boxes的高度就是图片的高度

此时图片与文字是同一box类型的元素,是在同一行上的,所以,默认状态下,一张图片只能与一行文字对齐。而要想让一张图片要与多行文字对齐,您唯一能做的就是破坏正常的line boxes模型

含有浮动属性的图片与文字

先看一下图片添加了float:left样式后的表现,见下图:

正常情况下,图片自身就是个inline-boxes,与两侧的文字inline-boxes共同组成了line-boxes,但是一旦图片加入了浮动,情况就完全变了。浮动彻底破坏了图片的inline-boxes特性,至少有一点可以肯定,图片的inline-boxes不存在了

一旦图片失去了inline-boxes特性就无法与inline-boxes的文字排在一行了,就会从line-boxes上脱离出来,跟随自身的方向属性,靠边排列

这个从line boxes上脱离的浮动元素其实就是一个躯体,一个空壳子,表象。因为其没有inline boxes。有人可能会问,没有inline boxes就没有呗,有什么大不了的?非也非也!这个inline boxes很个很重要的概念

为什么inline-boxes很重要?

在目前的CSS的世界中,所有的高度都是有两个CSS模型产生的,一个是盒子模型,对应CSS为”height+padding+margin”,另外一个是line box模型,对应样式为”line-height”。前者的height属性分为明显的height值和隐藏的height值,所谓隐藏的height值是指图片的高度,一旦载入一张图片,其内在的height值就会起作用,即使您看不到”height”这个词

而后者针对于文字等这类inline boxes的元素(图片也属于inline boxes,但其height比line-height作用更凶猛,故其inline boxes高度等于其自身高度,对line-height无反应),inline boxes的高度直接受line-height控制(改变line-height文字拉开或重叠就是这个原因),而真正的高度表现则是由每行众多的inline boxes组成的line boxes(等于内部最高的inline box的高度),而这些line boxes的高度垂直堆叠形成了containing box的高度,也就是我们见到的div或是p标签之类的高度了

所以,对于line box模型的元素而言,没有inline boxes,就没有高度了,而浮动却恰恰做了这么龌龊的事情,其直接将元素的inline boxes也破坏了,于是这些元素也就没有了高度

沿用上面图片的例子。浮动破坏了图片的inline box,产生了两个结果:一是图片无法与文字同行显示,脱离了其原来所在的line box链;二是没有了高度(无inline box -> 无line box -> 无高度)。而这些结果恰恰是文字环绕图片显示所必须的

文字环绕图片显示的原因

这里有个动画,可以很好的帮助我们理解文字环绕图片显示的原因:http://image.zhangxinxu.com/f...

动画所演示的关键点其实就是上面的一系列分析与讲解,即“包裹与破坏”!包裹是让标签占据的空间水平收缩,破坏是破坏的inline box。正如上面讲解的,inline boxes是高度形成的基础,浮动破坏了inline boxes也就没有高度可言了。正是由于浮动元素没有了inline boxes,没有了inline boxes高度,才能让其他inline boxes元素重新整合,环绕浮动元素排列

我们现在假设浮动没有破坏inline boxes,那么虽然图片会靠左显示,但是其会与文字形成新的高度包络线(同类聚合),且只能与一行文字形成line box,无法实现文字环绕效果,所以浮动破坏inline boxes是必须的

浮动(float) vs 绝对定位(absolute)

了解了浮动之后,我们来对比一下绝对定位

与浮动元素一样,绝对定位元素也具有"包裹性"和"破坏性",并适用于任何元素,那么他们之间有什么区别呢?

使用float脱离文档流时,其他盒子会无视这个元素,但其他盒子内的文本依然会为这个元素让出位置,环绕在周围。

而对于使用absolute脱离文档流的元素,其他盒子与其他盒子内的文本都会无视它。

而这造成的显示上的差异就是:文档流中的文字实体不会与浮动元素重叠,而会与绝对定位元素重叠。这就是文字环绕显示的重要原因之一:虽然图片实际占据的高度为0,但是由于其宽度实体存在(包裹性),同样是content area实体的文字不会与之重叠(外部的容器盒子containing box(p,div,ul,li)会重叠),这就好比篮球场上站了个植物人,虽然其几乎不可能得分,运球之类,但是他的实体在那里,它可以阻挡同一水平空间上的同一类型的个体(即人)直接穿过去,要通过,得绕道。但是其无法阻挡整个球队的向前推进

观后感

每次看这篇文章都有不同的感悟,张鑫旭大神对很多问题的理解非常深刻和独到,很欣赏他的文章。这篇文章中还有好几个知识点需要深入理解,比如css行高line-height的一些深入理解及应用absolute的深入理解系列,我会找个时间整理一下,有兴趣的伙伴也可以去看下


Change
225 声望15 粉丝

从不知道到知道,从知道到理解,从理解到深入探索,这是个有趣的过程