CSS 中浮动的工作原理如下
您还想了解有关花车的哪些信息?
封面照片由 JANUPRASAD 通过 Unsplash 拍摄。
还有人记得以前用浮动布局的年代吗?以前我们得赤脚在雪地里爬坡写 CSS,真是上天入地。现在的年轻人都用弹性盒子和网格了……
无论如何,浮动对于非大规模布局仍然很有用。即使你最终不想在新应用中使用它们,你最终也可能会维护一个对浮动使用繁琐方法的旧版应用。了解浮动的基本工作原理在各种情况下都会派上用场。
另外,浮动是 CSS 的一大痛点。很多人遇到过这种情况:应用浮动后,页面上的所有内容突然移动(而且不知道为什么)。今天就让我们一起克服这个难题吧。
那么,让我们立即开始探究花车的奥秘吧。
基础知识
浮动最擅长的就是让文本围绕其他元素流动。在这方面,浮动绝对是模拟打印布局的最佳方式。
发生的事情很简单:
- 浮动元素被放置在原本的位置
- 它被从正常的文档流中移除,并被推到尽可能靠左或靠右的位置
- 在其之后的元素将围绕浮动元素排列
我可以浮动中心吗?
不行。我知道这很酷,但根本没用。
我猜你会如何实现这个文字加猫图的版本。你会如何巧妙地将文字拆分?目前没有什么好办法。这可能就是它从未实现的原因。
浮动元素不属于正常的文档流?所以它就像“position: absolute”一样?
position: absolute
不完全是。具有(或类似属性)的元素会完全从文档流中移除。绝对定位的元素通常会位于其他邻近元素的上方或下方,因为它们会相互忽略。
当一个元素浮动时,它并不完全处于正常的文档流中,但它确实与其他元素相互作用;它们遵循特殊的定位规则,主要是它们会围绕它进行排列。
浮标不想太大
未明确设置大小的浮动元素会“缩小以适应”position: absolute
其内容——也就是说,它只会占用所需的宽度。如果浮动元素中的内容不多,它就不会太大;如果内容很多,它就会变大。您可能之前在和position: fixed
元素中见过类似的行为。
预测花车的去向
当您在玩 Jabberwocky 示例时,您是否碰巧发现了类似的东西?
人们倾向于避免使用浮动的原因之一是它们看起来难以预测。如果一系列高度不同的浮动溢出了行,会发生什么?
让我们看一下浮动元素如何定位的规范:
[...] 当一个元素浮动时,它会脱离文档的正常流(尽管它仍然是文档的一部分)。它会向左或向右移动,直到接触到其包含框或另一个浮动元素的边缘。
所以,当某个元素适合我们的宽度时,一切正常。当它不适合时,它会向下浮动一段时间,直到碰到它想要停止的边缘——它的父容器的边缘,或者另一个浮动元素。
为什么最后一个没有向上移动来填补那个可怕的空白?
浮动元素永远不会将自己定位在 HTML 顺序中位于其前面的元素之上。
然而,它会牢记这一限制,尝试尽可能高地“漂浮”。
边距、盒子模型和 HTML 顺序
在基本示例中,您是否对此感到困扰?
这里我们需要一个margin。如果你随机选择一个元素,大概有三分之一的概率能猜出该将 margin 应用于哪个元素。虽然感觉随机猜测是 CSS 的精髓,但还是让我们试着理解一下浮动在这里的作用。
#1 - 如果你给外层容器添加 margin-left 属性,就会出现这种情况#container
——它只会把所有内容往右推。这并不能真正解决浮动框导致文本边缘过硬的问题。大概没人试过用这种方法修复浮动,除非是在凌晨 3 点,绝望地哭泣。(谁没经历过这种事?)
#2 - 你可能真的尝试过——将 应用于margin-left
文本本身。然而,文本的边距是基于文本的“盒子”——如果没有浮动元素,文本就会位于那里。(你可以想象在浮动元素“下方”有一个边距。)
文本本身仍然像之前一样围绕浮动元素流动,但相对于其父元素,它保留了一定的外边距。margin 属性无法为文本添加“之字形”外边距,并且文本必须与其父元素保持一定的距离,而外边距代表了文本与浮动元素之间的距离,因此,仅与浮动元素保持距离是不行的。
#3 - 外边距会添加到实际的浮动元素上,从而扩展其浮动框。文本将围绕整个浮动框流动,包括外边距。因此,添加margin-right
到左侧浮动的猫形框和margin-left
右侧浮动的猫形框会给文本留出一些空间。
总结一下 -在浮动元素上放置边距会导致其他东西流动到组合浮动框的周围,包括任何边距。
我们在这里要表达的想法是 - 页面上的其他内容围绕浮动内容移动,而不是浮动内容围绕页面上的其他内容移动。
我们还可以将浮动元素堆叠在一起!浮动元素会很好地挨着其他浮动元素,并且文本会围绕它们流动。
需要注意的是,浮动元素在 HTML 中的放置顺序非常重要。如有疑问,请优先考虑浮动元素。假设您是浏览器,并且正在按“顺序”读取 HTML 内容——您肯定想知道浮动元素首先位于何处,这样就不必重新绘制之后必须围绕浮动元素流动的所有元素。
清除浮动
具有该属性的元素clear
描述了该元素如何与附近的浮动元素交互。您可以为浮动元素和非浮动元素添加 clear 属性。
clear 属性意味着:我不希望在这个方向上靠近我的任何浮动!
由于在页面上推动其他元素是不礼貌的,因此,如果附近有冲突的浮动元素,则具有清除属性的元素会向下移动。可以认为清除元素在社交上是尴尬的,并且会避免冲突。
浮动不会像你想象的那样占用空间
如果你以前使用过浮点数,你可能会发现自己处于这种情况:
#container
包含所有浮动元素(且仅包含浮动元素)的已折叠。这是因为浮动元素会将其从正常文档流中移除,并且其周围的容器不会创建新的块格式化上下文。
还记得我上面说过吗:
它被从正常的文档流中移除,并被推到尽可能靠左或靠右的位置
“从文档流中删除”在这里具有含义和技术后果!
根据 CSS 的规则,容器的高度由其“在正常文档流内”的所有内容决定。然而,我们也可以将容器设置为“块格式化上下文”——有点像页面内的迷你布局——这样容器就需要将自己视为一个迷你文档,它会拉伸以适应其所有内容,即使是超出文档流的内容。
我们需要做一些令人信服的事情来让容器伸展以适应我们的浮子,但要知道我们有选择。
一些可能的解决方案:
1. 创建一个位于浮动元素之后的元素
这是clearfix-type-one
上面提到的解决方案。这也是“老派”的 Clearfix。
我们现在知道,容器会拉伸以适应其流内的所有元素,而浮动元素不在其流内。因此,我们需要一个非浮动元素,放置在浮动元素之后。我们可以使用以下属性clear
来实现:
<div id="container">
<img class="floaty-left" src="https://placekitten.com/100/200">
<img class="floaty-left" src="https://placekitten.com/100/100">
<img class="floaty-left" src="https://placekitten.com/160/200">
<img class="floaty-left" src="https://placekitten.com/100/120">
<div style="clear: both;"> </div>
</div>
这将导致容器向下延伸至我们清除的 div。
但是,该元素会有一些自身的高度(因为它应该包含一些文本),所以我们可以添加类似的代码,height: 0
以确保它在继续应用清除固定效果的同时不会影响容器的高度。多年来,我见过其他实现此目的的方法,例如使用max-height
,甚至font-size: 0
。¯\_(ツ)_/¯
由于这仅用于显示并且不具有语义,我们也可以将其移动到应用于容器的::after
伪元素。
这就是我们最终得到如下结果的方式:
// the "basic" clearfix with after
&.clearfix-type-one {
background-color: #644;
&::after {
content: " ";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
}
这还可以进一步完善;网上有很多类似的解决方案。例如,Nicholas Gallagher 于 2011 年提出的 micro clearfix。这类 Clearfix 解决方案往往具有出色的跨浏览器支持,因为它们已经存在了近十年。
2. 使用overflow: hidden
创建新的块格式化上下文
(从技术上讲,您可以使用任何不可见的溢出值,但隐藏值往往是效果最好的值。请给我一点时间来解释一下……)
这是clearfix-type-two
上面提到的解决方案。摘自MDN 文档:
块格式化上下文包含创建它的元素内的所有内容。
因此,强制父容器形成一个新的块格式化上下文会强制其扩展,因为它必须完全包含其所有子容器。而且这只需要一个属性就能完成,那么为什么这不是最佳解决方案呢?为什么它只是列表中三个方案中的第二个呢?
嗯……你用的是overflow: hidden
。这并非没有后果;你得处理一个除了自身之外什么都不显示的容器。如果我们还想给某些元素添加彩虹阴影,而这些元素会被裁剪掉,或者在容器外放置绝对定位的闪光效果,那该怎么办?如果只是为了清除浮动元素而去掉这些元素,那就太疯狂了。
你能想象这是多么可笑的事情。
还记得我之前说过,你可以使用任何不可见的溢出值吗?好吧,想象一下,如果overflow: scroll
在侧面创建滚动条,那看起来会有多糟糕。真是让人头疼。
3. 使用display: flow-root
创建新的块格式化上下文
这就是clearfix-type-three
上面笔中的解决方案。
与上述解决方案不同,此方案旨在在固有层面上发挥作用,而非“黑客攻击”。规范如下:
该元素生成一个块容器框,并使用流式布局来布局其内容。它始终会为其内容建立一个新的块格式化上下文。
所以这基本上和 做了同样的事情overflow: hidden
,但没有副作用。✨
这听起来正是我们想要的!它未被使用的原因是跨浏览器支持——目前几乎 30% 的设备不支持它,Safari 和 IE/Edge 一如既往地是问题所在。
您还想了解有关花车的哪些信息?
页脚照片由 Cristina Gottardi 在 Unsplash 上拍摄。