当前位置: 首页 > Web前端 > CSS

重塑你的CSS世界观——漂浮恶魔float

时间:2023-03-30 13:19:45 CSS

为什么要写系列文章《重塑你的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:
然而,当你运行代码的时候,看到的效果是这样的:然后你的心情就崩溃了:遇到事情不要慌张,先让我们分析一下,浮动元素的包含块是什么。正确的?没错,就是.container的contentedge,所以虽然有点不对,但还是浮在里面。那么下一步就是确定当前行。让我们恢复原来的布局,去掉.left和.right的浮动属性。这时候就会出现“三线”。首先,我们让.left浮动。在.container的内容边界“第一行”中,.middle开始向上移动到“第一行”,因为它脱离了文档流。这时,由于.middle向上移动,.right元素也向上移动到“第二行”,然后让它浮动。此时.right的浮动范围在.container的内容边界内,浮动的当前行为“第二行”,所以出现.right元素下落浮动的效果,因为它的“当前行””是“第二排”,居然没有倒下!我们如何解决它?很简单,让.left和.right如果“在同一行”就好了。这意味着什么?.left浮动的当前行是“第一行”,因为它不在文档流中,后面的元素会向上移动一行,所以我们可以让.right紧跟在.left之后。.left浮动后,.右边会到“第一行”,此时浮动会在“第一行”的右边。然后因为.right也脱离了文档流,.middle也被上移到了“第一行”,具体代码如下:Left中然后运行之后就是我们一开始想要的效果:相信你有看完明白了很多,下面结合下面代码的运行效果来测试一下你是否真正理解了。提示:标题中的文字已经超出了.title我是三级标题moreif你可以想象下图的效果说明你已经看懂了。如果还是不行,请回到上一篇文章继续阅读。下面用上面用到的套路来分析一下这个现象。首先,确认.more元素的包含块是.title元素的内容边界。那么,因为内容太长,宽度不够,此时就变成了两行显示,而.more元素在“第二行”,所以它的当前行是“第二行”。添加浮动属性后,.title元素内容边界内的“第二行”向右浮动,形成我们所见。如果想让.more元素无论标题内容多长都浮动在右边,只需要将.more元素的代码放在.title元素的最前面即可,即:更多我是三级标题这时候的效果就是我们想要的。重叠区域不允许渲染“内容”,而linebox实现文字换行的盒子的“捕捉位置”,其实就是浮动的本质,只是经常被我们遗忘,主要是因为文字换行effect主要影响浮动元素的以下元素。由于这部分规范中的定义比较晦涩,以下内容是我在阅读《CSS世界》时根据自己的理解得出的。如果您想查看规范原文,可以访问此链接。首先,由于浮动,浮动元素和跟随元素之间存在一定的重叠区域,这一点大家都知道,但是如果要让内容包围起来,重叠区域是不能有内容的。注意content、text、svg、pictures等替换元素全部替换。被视为“内容”,它基本上是一个内联或行块元素。不管是inline还是inline-block元素,都会生成一个“linebox”,重叠区域不允许出现“content”,所以可以转换成重叠区域的“linebox”需要“粘贴”在浮动元素浮动方向的相反方向的一侧就可以了,也就是说,如果一个元素向左浮动,那么重叠区域中跟在该元素后面的“行框”就需要“粘”到浮动元素的右侧,反之亦然。我们看一段代码:我是匿名内联框的文字,我是inlinebox的文字,如果文字很长,会出现babalabala的效果。填个字数,哈哥。我们用蓝色背景高亮了第一行文字,我们可以看到浮动元素边上的“行框”卡片的效果,然后注意重叠区域无法渲染“content”,背景色不属于“content”,所以我们可以看到绿色背景色甚至覆盖了重叠区域。这时候可能有大佬要问了,重叠区域是在浮动元素上面还是下面的元素?答案是:浮动元素在最上面。下面加一段代码验证一下:.float{background-color:yellow;}效果如下:综上所述,当一个元素要浮动时,需要以下步骤:脱离文档流;在“includeblock”和“currentline”范围内按浮动方向浮动;受浮动影响的元素不允许在与浮动元素重叠的区域渲染“内容”,受浮动影响的元素内部的行框被“卡住”以实现文本换行;