为什么要写系列文章《重塑你的CSS世界观》自从我开始工作以来一直在写JavaScript,我几乎不接触CSS,通常都是别人写界面,然后我来了开发javascript逻辑代码,导致严重偏科,而css又很弱,于是决定重新学习css,从打css2的基础开始。最近,我开始阅读一本关于CSS的书。这本书叫做《CSS世界》。由CSS大师张新旭编写,质量非常有保证。这本书几乎完全颠覆了我对CSS的认知,几乎等于重塑了我的CSS世界观。曰:学而不思则亡,思而不学则亡。所以我决定结合我从这本书中学到的知识和我看到的一些文档来总结一下,以备将来复习和使用,所以文章中的见解也可能是错误的。不追求完全正确,但希望能作为一种方法论来指导后续的CSS开发。如有错误,请指正。漂浮的本质是什么?浮动的本质是实现文字环绕效果——《CSS世界》第6章流量破坏与保护熟悉张新旭老师的这句话应该在他的博客和一些视频教程中听过。可能和我的一样,乍一看觉得自己懂了,后来就不当真了,然后在使用float的时候还是错误百出。撇开我们前端开发者的身份不谈,我们站在一个普通用户的角度来思考一下,我们会在哪些场景下使用文字环绕效果。相信很多人都用过Word这个软件。我们在编辑图文信息的时候,希望文字可以围绕图片排列,也就是文字环绕,也就是从图片1到图片2:
图片1图2从普通用户的角度来看,实现文字换行的步骤还是一样的。让我们想想作为一个普通用户如何实现这个效果。为了方便起见,我在这里定义了一些词汇,将下面的内容称为文本和段落,需要包围的图片称为目标元素。首先我们把两者简化一下,分成两块,如图:所谓包围,就是把两个块重叠在一起,目标元素悬浮在重叠区域上方,重叠区域不能有followingcontent内容,如图:所以要让followingcontent包围目标元素,我们需要做如下步骤:使followingcontent的顶部上升到与target元素的顶部相同的高度;后面的内容和目标元素的重叠区域不能有文字,非重叠区域按照原来的排版方式。如何漂浮?浮出文档流本来是为了达到文字环绕的效果。经过上面的讨论,我们意识到浮动元素的顶部和下面的元素应该上升到同一水平线。在文档流中,如果浮动元素和跟随元素都是div元素,默认都占一行。所以我们需要让浮动元素脱离文档流。这时,下面的元素可以根据文档流的要求向上移动,从而达到视觉重叠的效果。并且由于浮动元素脱离了文档流,如果父元素没有指定高度或者有其他元素撑起来,所谓浮动元素的父元素高度就会塌陷。确定“包含块”并将其浮动在“当前行”中。在分析原理之前,我们先来看一段代码,想象一下它的渲染结果
我是一段文字漂浮 在这时间,你想象的结果可能是这样的:但实际运行效果是这样的:为什么会这样?让我们从CSS标准中寻找答案。W3C的CSS标准文档中关于浮动的描述中有这样一段话:一个浮动的盒子向左或向右移动,直到其外边缘接触到包含块边缘或另一个浮动的外边缘翻译成中文是:a浮动框会向左或向右移动,直到它的外边框接触到包含块的边框或另一个浮动框的外边框。OK,先抛开多个浮动元素的情况,我们只考虑一个浮动元素的情况。注意到上面引用的文本中突出显示的词了吗?包含块(containingblock),没错,刚才我们想象的代码运行的渲染效果和实际浏览器运行的效果是我们没有实现包含块(containingblock),或者识别错了floating元素的包含块,而这个包含块就是元素浮动的参考位置!什么是收容块?如何判断一个元素的包含块?在W3CCSS标准文档中对包含块的描述中,有这样一段话:元素的box(es)的位置和大小有时是相对于某个矩形计算的,翻译成中文称为元素的包含块是:元素的(生成的)框的位置和大小有时是根据特定的矩形计算的,称为元素的包含块。标准也给出了如何确定一个元素的包含块的定义,因为英文比较长,比较难读,这里我放一个中文的定义:根元素所在的包含块是一个矩形,叫做初始包含块。对于连续媒体,大小取自视口大小并固定在画布的开头;对于分页媒体,它是页面区域。初始包含块的“方向”属性与根元素的相同。对于其他元素,如果元素的位置是'relative'或'static',则包含块由其最近的块容器祖先框的内容边缘形成如果元素具有'position:fixed',则包含块由连续媒体的视口或分页媒体的页面区域如果元素有'position:absolute',则包含块由'absolute'、'relative'或'fixed'的最近'position'建立建立如下:如果祖先是内联元素,则包含块是围绕为该元素生成的第一个和最后一个内联框的填充框的边界框。在CSS2.1中,如果内联元素被跨行分割,那么包含块是未定义的否则,包含块由这个祖先的填充边界形成如果没有这样的祖先,则包含块是初始包含块根据上面关于包含块的定义,我们可以发现.float元素符合第2条,那么它的包含块就是.boxdiv的内容边界。注意这里是内容边界(contentedge),不是整个盒子,所以不包括padding和border,margin。先看一张关于盒子模型的图:W3C的CSS规范是这样定义contentedge的:contentedge包围着由盒子的宽高给定的矩形,这往往取决于元素渲染的内容四个contentedges定义了盒子的内容框。翻译成中文就是:内容边界包围由框的宽高表示的矩形,通常取决于元素的渲染内容。4个内容边界定义了盒子(contentbox)的内容框,所以如果我们给.box类添加一个10px的padding,.box{padding:10px;}浮动元素是靠着包含块浮动的,并且在这次的containingblock只是.box元素的内容区域,不包含padding,所以就出现了,浮动元素和.box元素box的距离,效果如下:OK,怎么可以我们仅通过调整CSS就可以达到我们的目的?你脑海中想象的渲染效果呢?答案是让.textspan元素成为.float元素的包含块,让内联级元素成为块级元素,只需要加一句display:inline-block或display:block,这里我们也要为了让.text元素保持Inline,所以我们加上:.text{display:inline-block;}这个时候的效果就是我们一开始想要的。在“当前行”浮动的W3CCSS标准规范中对浮动的定义,开头有这样一句话:浮动是在当前行上向左或向右移动的盒子。翻译成中文就是:floating(box)是在当前行上向左或向右移动的盒子。请注意当前行的高亮字,你必须理解当前行,如果包含块决定了浮动元素的浮动范围,那么当前行(currentline)决定了浮动范围到哪个垂直位置漂浮。同样,我们通过一个小场景来理解当前这一行的重要性。想象一下,您收到了一个任务,要实现一个三列布局。无论左右栏的宽度如何变化,中间栏的宽度必须是自适应的。Color):如果你聪明的话,可能已经想到了一种方法,让左右两列浮动,中间一列的左右边距值设为auto,这样中间一列就可以自定了改编。没错,你觉得很机智,然后按照设计图的设想,从左到右写了三个div: