以文本方式查看主题 - ╋艺 镇╋ (http://zyzsky.com/bbs/index.asp) -- ┣◇网站建设&Web语言 (http://zyzsky.com/bbs/list.asp?boardid=4) ---- CSS float浮动的深入研究、详解及拓展(一) (http://zyzsky.com/bbs/dispbbs.asp?boardid=4&id=3293) |
-- 作者:admin -- 发布时间:2011/12/20 11:15:57 -- CSS float浮动的深入研究、详解及拓展(一) by zhangxinxu from http://www.zhangxinxu.com 概念目录
一、引言你我看待事物的方式不同,价值取向也不同,因为我们有着不同的世界观,价值观。这种世界观的差异不仅仅体现在实际的生活中,也反映在代码上。你我看待代码的方式,或者说是代码在我们情感层面的位置是不一样的,我这里说的是情感层面,与逻辑无关,与算法无关(虽然算法受情感影响)。这种看待代码的方式是我们在不断学习与工作的过程中积累出来的,是在潜意识层面逐渐积累起来的,一切悄然而至,不知不觉。当我们积累到一定阶段后,会突然发现,关于代码,我们已经形成了自己的世界观和属于自己的准则。回到我刚提到的“情感层面”,这个词也可以用“感性思维”来代替。通常而言,程序-代码属于很理性很逻辑的东西,与感性-情感这类词搭不上边,但是CSS例外。CSS也属于代码范畴,而且是一种伟大的代码,其有别于C,JAVA之类程序语言——没有算法,没有复杂的逻辑。于是,CSS有了先天的优势可以渗入一些感性的情感化的东西。正如我上面提及的,大多数情况下,这种渗入是无意识的(除非有人直接表露——就像我现在所做的),并且是个体差异明显的(因为是专属于自己的情感化的东西)。弗洛伊德将人格划分为无意识、前意识和意识,我发现代码的情感化思维形成正是走的从无意识到前意识到意识的路线,所以我个人认为:情感化的代码也属于人格的一部分。于是,有了“CSS-情感化代码-人格”这一微妙的关系。 我不清楚他人是如何看待CSS的,CSS的这些属性在他们心中是个什么东西,他们到底赋予了多少自身的情感(或人格或品性或特质等)在这些代码身上,他们是否已经意识到这些CSS属性身上正一点一点地融入他们情感化的一些东西。但我清楚自己,在这些CSS的属性身上添加了很多个人的色彩,这种情感化的东西可以说让我更好的理解CSS,我想这不难理解,举个例子:假设你将每个CSS属性看做是你的孩子,每个孩子有着不同的性格,随着学习你会挖掘到更多的一些性格,这就好比母亲看着自己的孩子一点点长大,到了一定的程度就会把自己的孩子的性格摸得一清二楚,管教也就从容了。当然,我并没有对CSS所有的属性都有很清晰的情感化的理解,我用CSS才几年啊,我要学的还有很多。但是,对于CSS中常用的float属性,我还是有些感觉的,这也是本文的主旨所在。本文将会从我的一些感性的认识的角度讲解CSS float属性。所以,这里,你会看到别样的技术文章。 二、浮动的情感化认识我对浮动感性化的认识:浮动就是一个变态,魔鬼,自私自利且影响他人的混球。我讨厌浮动。 三、浮动的原始意义是什么?我们使用float浮动做了很多其本职工作以外的事情,于是我们会混淆,我们会回看不清float真正的面目。浮动真正的意义在哪里呢?要知道这个问题的答案很简单,假设现在CSS中没有浮动(float)属性,那么会变成一个什么样子。我们会发现,目前流行采用浮动方法实现的无论是分栏布局,还是列表排列我们都可以用其他一些CSS属性(不考虑table)代替实现,唯一一个实现不了的就是“文字环绕图片”,我是想不出来能有什么方法可以让文字环绕图片显示。好,这个替代不了的作用才是float真正的意义所在。此作用类似于word中的版式,很基础的原始的作用:例如左边这张word截图就含有左浮动属性(float:left),这才是浮动应该做的事情。这是非常重要的结论,这是深入理解浮动属性的基础,我们后面探讨的一些浮动相关的问题都可以由这里引申出来,所以,请记住,浮动出现的意义其实只是用来让文字环绕图片而已,仅此而已。而我们目前用浮动实现页面布局本不是浮动该干的事情。 四、浮动的本质是什么?我将浮动的本质定义为“包裹与破坏”! 1.
浮动的“包裹性” display:inline-block某种意义上的作用就是包裹(wrap),而浮动也有类似的效果。举个常见例子,或许您有实现宽度自适应按钮的经验,实现宽度自适应的关键就是要让按钮的大小自适应于文字的个数,这就需要按钮要自动包裹在文字的外面。我们用什么方法实现呢?一就是display:inline-block;二就是float。例如我们要实现新浪博客中的“发表文章”之类的宽度自适应按钮(如下图): 背景图片为: display:inline-block方法 CSS代码如下: .btn1{display:inline-block; background:url(http://www.zhangxinxu.com/study/image/sina_gray_btn.png) no-repeat left top; padding-left:3px; color:#000000; font-size:12px; text-decoration:none;} .btn1 cite{display:block; line-height:26px; padding:0 13px 0 10px; background:url(http://www.zhangxinxu.com/study/image/sina_gray_btn.png) no-repeat right top;} HTML代码如下: <a href="javascript:void(0);" class="btn1"><cite>inline-block方法</cite></a> 结果如下图: float:left方法 CSS代码如下: .btn1{float:left; background:url(http://www.zhangxinxu.com/study/image/sina_gray_btn.png) no-repeat left top; padding-left:3px; color:#000000; font-size:12px; text-decoration:none;} .btn1 cite{display:block; line-height:26px; padding:0 13px 0 10px; background:url(http://www.zhangxinxu.com/study/image/sina_gray_btn.png) no-repeat right top;} HTML代码如下: <a href="javascript:void(0);" class="btn1"><cite>float方法</cite></a> 结果如下图: 您可以狠狠地点击这里:按钮宽度自适应demo 上面这个例子旨在说明浮动属性(无论是左浮动还是右浮动)某种意义上而言与display:inline-block属性的作用是一模一样的,所以类似于 2.
浮动的“破坏性” 所以,只要您弄明白了为什么文字会环绕含浮动属性的图片,您就会知道我所说的浮动的“破坏性”是什么意思了。//下面这部分内容是本文核心,多个人观点,我尽量表述清楚。您若有兴趣,可以放慢在这里的阅读速度。 先说结论:文字之所以会环绕含有float属性的图片时因为浮动破坏了正常的line boxes。 这里有必要先讲讲line boxes模型。先看下面一段普通的HTML代码: <p>这是一行普通的文字,这里有个 <em>em</em> 标签。</p> 这段HTML代码涉及到4种boxes: 2、然后就是inline boxes,如下图标注, 3、line boxes,见下图的标注: 4、content area,见下图标注: 正常的图文混排 含有浮动属性的图片与文字 这个从line boxes上脱离的浮动元素其实就是一个躯体,一个空壳子,表象。因为其没有inline boxes。有人可能会问,没有inline boxes就没有呗,有什么大不了的?非也非也!这个inline boxes很个很重要的概念。我曾在“css行高line-height的一些深入理解及应用”一文中提到过高度的本质,这里有必要再讲一遍。 在目前的CSS的世界中,所有的高度都是有两个CSS模型产生的,一个是box盒状模型,对应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也破坏了,于是这些元素也就没有了高度。 我们所处的这个世界时需要坏人来维持平衡的。武侠世界里不是常有要消灭某个超牛叉的大魔头时,会有人修炼魔功与之抗衡嘛。浮动似乎就是这样的一个角色,在网页最初的时候就是显示一些图片的文字啊什么的,所需要的布局也就那么几个,其中之一就是文字环绕图片显示了,可是怎么实现这样的效果呢?聪明的CSS开发者就创造了一个修炼“魔功”的float属性,其作用就是破坏line boxes模型好让文字环绕图片显示,最后实现了吗?确实实现了。还记得我多次说到的浮动的意义吗——只是用来让文字环绕图片而已,而要实现这个就需要用到浮动的“破坏性”。 沿用上面图片的例子。浮动破坏了图片的inline box,产生了两个结果:一是图片无法与文字同行显示,脱离了其原来所在的line box链;二是没有了高度(无inline box -> 无line box -> 无高度)。而这些结果恰恰是文字环绕图片显示所必须的。 文字环绕图片显示的原因 动画所演示的关键点其实就是上面的一系列分析与讲解,即“包裹与破坏”!包裹是让标签占据的空间水平收缩,破坏是破坏的inline box。正如上面讲解的,inline boxes是高度形成的基础,浮动破坏了inline boxes也就没有高度可言了。真是由于浮动元素没有了inline boxes,没有了inline boxes高度,才能让其他inline boxes元素重新整合,环绕浮动元素排列。 我们现在假设浮动没有破坏inline boxes,那么虽然图片会靠左显示,但是其会与文字形成新的高度包络线(同类聚合),且只能与一行文字形成line box,无法实现文字环绕效果,所以浮动破坏inline boxes是必须的。 我们可以拿浮动元素与绝对定位元素做对比或许可以帮助理解。与浮动元素一样,绝对定位元素也具有“包裹性”,此“包裹性”适用于任何元素。那么,浮动元素与绝对定位元素的差别在哪里呢?我觉得最主要的差别在于:绝对定位的元素脱离了文档流,而浮动元素依旧在文档流中;而这造成的显示上的差异就是:同处于文档流中的文字实体不会与浮动元素重叠,而会与绝对定位元素重叠。这就是文字环绕显示的重要原因之一:虽然图片实际占据的高度为0,但是由于其宽度实体存在(包裹性),同样是content
area 实体的文字不会与之重叠(外部的容器盒子containing
box(p,div,ul,li)会重叠),这就好比篮球场上站了个植物人,虽然其几乎不可能得分,运球之类,但是他的实体在那里,它可以阻挡同一水平空间上的同一类型的个体(即人)直接穿过去,要通过,得绕道。但是其无法阻挡整个球队的向前推进。见下图(firebug显示截图): 简短的小结 (未完待续…) 本文内容多个人心得总结,如果不同观点,欢迎反驳,欢迎交流,您可以通过评论或去这里进行提问交流。 |
-- 作者:admin -- 发布时间:2011/12/20 13:43:03 -- CSS float浮动的深入研究、详解及拓展(二) by zhangxinxu from http://www.zhangxinxu.com 接上回… 五、浮动的非本职工作浮动的本职工作是让匿名inline boxes性质的文字环绕图片显示,而其他所有用浮动实现的效果都不是浮动应该做的事情,我称之为“非本职工作”。 或许我们并没有过多的深思,把一些实际上不是浮动该干的事情当作“这必须用浮动来实现”。举个常见的例子,列表显示,见下面的图,截自淘宝新版首页: 我可以确信,浮动这个属性诞生的那天压根没有想到自己会要做这样的事情,本来它以为自己就让文字环绕显示就OK了,功德圆满了,结果,在web2.0的时代,其却在页面布局中被滥用。可能有人会反驳,你何处此言,有何证据? 我们只要静下心来好好想想浮动的本质,实现的原理,就可以知道为什么浮动本不应该用来对页面进行布局。还记得上一部分所说的浮动的本质吗?即“包裹与破坏”。我们可以用这个(“包裹与破坏”)解释为什么浮动可以让li这类block水平的元素水平排列。 单个无浮动的li元素 看下面的HTML代码:
<ul style="width:440px;"> <li style="border:4px solid #ff6633; background:#ffffc0;"><img src="../image/border.png" /></li> </ul> 结果如下图(截自Firefox浏览器,无其他样式干扰,下同): 这里的li元素为什么会有高度?如果您认真读过前半部分内容关于line boxes模型与高度的关系的内容,应该知道,由于图片没有应用float属性,其本身有一个正常的inline box,这个inline box高度等于图片的height,在这行元素中,图片这个inline box的高度最高,于是传递给了line box,line box是个真正意义上的高度,直接作用于containing box(就是这里的li元素,使li元素有一个高度)。理解了这个您就会明白为什么要是这里的图片添加了float属性,li高度会塌陷了:浮动破坏了inline box。这个后面会详细讲解。 这里的li没有添加float属性,可以见到li宽度100%自适应于父ul标签。一切显得那么的和谐! 单个左浮动的li元素 看下面的HTML代码:
<ul style="width:440px;"> <li style="border:4px solid #ff6633; background:#ffffc0; float:left;"><img src="../image/border.png" /></li> </ul> 结果如下图: 相比上面而言,这里多了个 浮动的“包裹性”让元素变成类似于inline box的元素,而浮动的“破坏性”正是破坏inline box元素的,这其中岂不有矛盾。其实非也,对于block水平的这类块状元素需要先让其变成类似效果的内联元素,然后再破坏之,实乃先诱拐再奸杀的生动实例啊! 又是我反复提到的,浮动破坏了inline box,也就是破坏了高度,所以这里含有浮动属性的li元素实际上是没有高度的。所以呢,要是后面还有同样的li标签的话,就会水平对齐排列的。如下: 多个左浮动的li元素 看下面的HTML代码:
<ul style="width:440px;"> <li style="border:4px solid #ff6633; background:#ffffc0; float:left;"><img src="../image/border.png" /></li> <li style="border:4px solid #ff6633; background:#ffffc0; float:left;"><img src="../image/border.png" /></li> </ul> 结果如下图: 左浮动的li元素和无浮动的li元素 看下面的HTML代码:
<ul style="width:440px;"> <li style="border:4px solid #ff6633; background:#ffffc0; float:left;"><img src="../image/border.png" /></li> <li style="border:4px solid #ff6633; background:#ffffc0;"><img src="../image/border.png" /></li> </ul> 结果如下图: 后面一个li无float属性,直接无视前面的float li元素,宽度100%显示,而且与float属性的li同一水平线排列,为何?因为浮动破坏了li的实际高度(原因我讲得太多次了),只是图片是个实体,无法与同样实体的同一文档流的图片重合,所以图片靠在一起。 六、证据1. 首要证据 前文是着重分析了浮动的“本职工作”:文字环绕显示;本文着重分析了浮动的“非本职工作”:列表布局;两者都是用的同样的原理解释的,那么有什么证据可以证明“页面布局”不是浮动的“本职工作”呢。答案关键字就是:高度塌陷。 我在多个地方浓墨重彩的讲浮动与高度的关系,浮动使高度塌陷的原因,自己都觉得唠叨的太多了,这里不再讲。直接讲些实际的东西。 您是否发现,浮动布局会让父标签高度缺失,但是实现文字环绕图片效果的时候父标签无需清除浮动。还是上面的例子,我们看看多li元素浮动时ul标签高度在哪里,我们可以给ul加个边框属性做测试,测试代码如下: <ul style="width:440px; border-top:4px solid #a0b3d6; border-bottom:4px solid #34538b;"> <li style="border:4px solid #ff6633; background:#ffffc0; float:left;"><img src="../image/border.png" /></li> <li style="border:4px solid #ff6633; background:#ffffc0; float:left;"><img src="../image/border.png" /></li> </ul> 结果如下图: 上图显示ul高度为0,这是必然的,正常的,应该的。您要是在IE下看到ul有高度,认为这是Firefox等浏览器有问题就错了,您把ul的width属性去掉,看看,会发现IE下ul高度也为0, 这是IE的layout作祟。至于为什么ul高度为0,我前面很多地方都已经讲了,不再说了。但是,从中我们可以看到,浮动本不是用来列表布局的,而是用来使元素环绕显示的,因为元素环绕(例如文字),其自身是含有inline boxes高度的,这是inline水平的元素形成高度的基础,所以,虽然浮动元素没有高度,但是其周围环绕的元素是有高度的,只要环绕元素比浮动元素高度高,父标签无高度的问题自然也就没有了,但是纯粹一堆浮动元素会有高度吗?没有。所以浮动元素塌陷的问题根本就不是浏览器的bug,而是我们没有正确地深入地了解浮动,是我们自己使用不当,因为浮动本不应该用在这里的。 2. 其他证据 为什么说浮动的本职工作不是页面布局而应该是是元素环绕呢。还有其他些证据。
历史 CSS刚诞生的时候,那时候的网页还是表格布局的时代,能显示几张图片就不错了,复杂的列表显示,布局啊这些概念还是很淡薄的,浮动出现的意义就是让文字能够环绕图片显示而已,就如word般。
现象 Google是目前互联网领域的老大,技术很牛叉,毋庸置疑,但是,当我发现它所有的页面几乎都是表格布局的时候,很诧异;还有twitter,也是表格布局的;
为什么这些顶尖的web网站使用表格布局,而不跟随潮流呢,起初我是百思不得其解。现在,我是明白了,这么做是有他的道理的,难道要用一堆浮动的元素去布局吗?这不是浮动该干的事情。而且,浮动是个很不好惹的魔鬼。 七、浮动是个魔鬼、混球浮动的存在就是个破坏。浮动效果的实现就是先破坏自身(挥刀自宫),然后影响别人。页面中只要出现一个浮动,势必有其他元素受其影响。这是开发和维护中的一个定时炸蛋(敏感词)。我们想想浮动的意义,只是让文字环绕图片显示而已,所以其必须破坏自身模型和高度。但是,不知道幸运还是不幸,浮动的这种置之死地而后生的特性居然可以让元素布局,加上其表面意思很好理解,兼容性还不错,使用方便,于是在舍弃了table布局的这个web时代里,浮动成为当前页面布局的主流。想想,真是一件可怕的事情。 有些人可能没有意识到浮动其实是个很糟糕的东西,是CSS中的一个魔鬼。为什么,或许因为用浮动布局页面发现还行,即使偶尔出现些小bug,打打补丁也可以解决。或许是因为没有体会到非浮动元素和浮动元素在开发和维护上所消耗的成本精力的差别。有些人可能知道浮动这个属性能不用就不用,但是由于找不到更好的替代方法,所以还是有很多地方使用了浮动布局,例如选项卡,列表显示等。 理论上而言,除了浮动的环绕效果之外,我们使用浮动做的其他工作都可以使用别的CSS属性实现,而且大部分情况是比浮动的效果好:首先没有了清楚浮动一说,二是有关浮动的一堆bug也不会出现,三是元素间独立了,不会像浮动一样改变一个会影响其他。但是,考虑到大多数人对CSS掌握的程度,以及浏览器的一些兼容性问题等,很多时候,我们不得不使用看上去使用方面但潜在问题较大的浮动属性。所以,有关浮动的一些特性的研究还是很有必要的,这就是下面的重点。 八、解决高度塌陷的问题 – 清除浮动CSS中有个讨论较多的话题就是如何清除浮动,清除浮动其实就一个目的,就是解决高度塌陷的问题。为什么会高度塌陷?什么时候会高度塌陷?塌陷原因是:元素含有浮动属性 – 破坏inline box – 破坏line box高度 – 没有高度 – 塌陷。什么时候会塌陷:当标签里面的元素只要样子没有实际高度时会塌陷。所以呢,并不是只要有浮动元素就会坍塌,就要清除的,CSS水平高低衡量的标准之一就是改用什么样式就用什么样式,不多用也不少用。 下面就来讲讲如何清除浮动,zxx:写到这儿,一下子轻松了。 1. 投机取巧法 就是直接一个
<div
style="clear:both;"></div> 放到当作最后一个子标签放到父标签那儿,此方法屡试不爽,兼容性强,使用方便,是初学时使用的上佳之选。但是我从来不用,因为我看到的是个巨大的浪费,浪费了一个标签,而且只能使用一次,我个人是无法容忍的,所以这个方法不推荐。而且有时候一不留神中间多了个空格会产生一段空白高度的。2. overflow + zoom方法 更多文章:http://www.zhangxinxu.com/wordpress/ 本文地址:http://www.zhangxinxu.com/wordpress/?p=594 .fix{overflow:hidden; zoom:1;} 此方法优点在于代码简洁,涵盖所有浏览器,可谓不错的选择啊。不过也是有问题的,就是这个overflow:hidden;是个小炸蛋,要是里面的元素要是想来个margin负值定位或是负的绝对定位,岂不是直接被裁掉了,所以此方法是有不小的局限性的。我一般不用这个方法,只是有时候顺便去除浮动时用用。 3. after + zoom方法 先来简单讲讲after,所谓after,就是指标签的最后一个子元素的后面。于是呢,我们可以用CSS代码生成一个具有clear属性的元素,其中的关键样式就是content了。或许您从网上看到的content里面的内容是”.”一个点,我了很多次,貌似随便写什么东西都没有问题,比如
content:\'clear
both\'; 没问题,或是content:\'张鑫旭\' 也是ok的。于是有:.fix{zoom:1;} .fix:after{display:block; content:\'clear\'; clear:both; line-height:0; visibility:hidden;} 这里的line-height:0写成height:0也是可以的。此方法可以说是综合起来最好的方法了,我都是用这个样式清除浮动的,不会影响任何其他样式,通用性强,覆盖面广,我很推荐哦。 九、float与JavaScriptJavaScript可以改变CSS的属性,其他些属性还好,但是这个float值得一说,为何呢,因为float貌似是JavaScript中的一个关键字,不能使用 IE浏览器:
obj.style.styleFloat = "left"; 其他浏览器: obj.style.cssFloat = "left"; 十、最后的总结其实原本是想通过深入分析浮动的前世今生,本质意义来揭示其丑陋的真面目的,可能是在文字表达上还欠火候,总觉得表达的有些凌乱,估计很轻松就知道我在说什么的人较少,本来是篇很有技术含量的文章,但是在表现上做的不够好,可能是内容太多,自己想要表达的内容太多,于是反而有些混乱。所以,最后其实很多东西没有继续详细展开讲解,例如清除浮动的本质是什么?浮动产生一系列bug的根本原因是什么?浮动布局更好的替代方案是什么?因为内容已经够多够乱的了,所以我决定这些内容留到以后,思路清晰的时候再表述出来。 本文可以说是有别于目前绝大多数关于浮动的文章,我没有讲浮动的使用实例啊之类的东西,也没有去分析浮动的一些特性,仅仅从最根本的地方分析浮动,我想这个比单纯的讲解几个浮动的应用作用更深远。而且还有一点,本文其实某种程度上是批判浮动的,希望开发者尽可能的少使用浮动,少使用浮动去做些其实并不是浮动应该做的事情。所以要是花功夫讲浮动的应用的话就是搬石头砸自己的脚。 本文很多理论的东西,多是自己张鑫旭的个人见解,所以实际上有些认识可能是不准确的,欢迎有不同观点的同行们反驳,也欢迎交流(通过评论或是去这里进行提问交流)。 原创文章,转载请注明来自张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com] [此贴子已经被作者于2011-12-20 13:43:37编辑过]
|