定位
定位允许您将元素从正常的文档流中取出,并使其表现出不同的行为,例如,彼此叠加或始终保持在浏览器视口内的相同位置。本文介绍了不同的position
值以及如何使用它们。
我们希望您在本地计算机上完成以下练习。如果可能,请从我们的 GitHub 仓库中获取0_basic-flow.html
的副本(此处查看源代码),并将其作为起点。
介绍定位
定位允许我们通过覆盖正常的文档流来产生有趣的结果。如果您想稍微更改一些盒子的位置,使其偏离默认的流位置,以营造出略带古怪、破旧的感觉,该怎么办?定位就是您的工具。或者,如果您想创建一个 UI 元素,使其浮动在页面其他部分的顶部,并且/或者始终位于浏览器窗口内的相同位置,无论页面滚动多少,该怎么办?定位使这种布局工作成为可能。
您可以对 HTML 元素应用多种不同类型的定位。要使特定类型的定位对元素生效,我们使用position
属性。
静态定位
要查看这一点(并为将来的部分设置示例),首先在 HTML 中的第二个<p>
中添加一个名为 positioned
的class
静态定位是每个元素都具有的默认值。它只是意味着“将元素放置到文档流中的正常位置——这里没有什么特别之处”。
<p class="positioned">…</p>
现在将以下规则添加到 CSS 的底部
.positioned {
position: static;
background: yellow;
}
如果保存并刷新,您将看不到任何差异,除了更新了第二段的背景颜色。这很好——正如我们之前所说,静态定位是默认行为!
注意:您可以在1_static-positioning.html
(查看源代码)处查看此示例。
相对定位
介绍 top、bottom、left 和 right
top
、bottom
、left
和right
与position
一起使用,以精确指定将定位元素移动到哪里。要尝试此操作,请将以下声明添加到 CSS 中的.positioned
规则中
top: 30px;
left: 30px;
注意:这些属性的值可以采用您合理期望的任何单位:像素、毫米、rem、% 等。
如果您现在保存并刷新,您将得到类似于以下的结果
很酷,是吗?好的,这可能不是您期望的结果。如果我们指定了top和left,为什么它会移动到底部和右侧?这可能看起来违反直觉。您需要将其视为一种无形的力量,它会推动定位框的指定边,使其向相反方向移动。例如,如果您指定top: 30px;
,则就像一股力会推动框的顶部,导致它向下移动 30px。
注意:您可以在2_relative-positioning.html
(查看源代码)处查看此示例。
绝对定位
绝对定位会带来截然不同的结果。
设置 position: absolute
让我们尝试如下更改代码中的 position 声明
position: absolute;
如果您现在保存并刷新,您应该会看到如下所示的内容
首先,请注意,文档流中定位元素应该存在的间隙不再存在——第一个和第三个元素已经合在一起,就像它不再存在一样!好吧,从某种意义上说,这是真的。绝对定位的元素不再存在于正常的文档流中。相反,它位于自己的图层上,与其他所有内容分离。这非常有用:这意味着我们可以创建独立的 UI 功能,这些功能不会干扰页面上其他元素的布局。例如,弹出信息框、控制菜单、悬停面板、可以在页面上任何位置拖放的 UI 功能等等。
其次,请注意元素的位置已更改。这是因为top
、bottom
、left
和right
在绝对定位中具有不同的行为。它们不是根据元素在正常文档流中的相对位置来定位元素,而是指定元素距包含元素各边的距离。因此,在本例中,我们说绝对定位的元素应位于“包含元素”顶部 30px 处和左侧 30px 处。(在本例中,“包含元素”是初始包含块。有关更多信息,请参阅下面的部分)
注意:如果需要,您可以使用top
、bottom
、left
和right
来调整元素的大小。尝试在您的定位元素上设置top: 0; bottom: 0; left: 0; right: 0;
和margin: 0;
,看看会发生什么!之后再放回去……
注意:是的,边距仍然会影响定位元素。但是,边距折叠不会。
注意:您可以在3_absolute-positioning.html
(查看源代码)处查看此示例。
定位上下文
绝对定位元素的“包含元素”是哪个元素?这在很大程度上取决于定位元素的祖先元素的 position 属性(请参阅确定包含块)。
如果祖先元素的 position 属性没有明确定义,则默认情况下所有祖先元素都将具有静态位置。其结果是绝对定位的元素将包含在初始包含块中。初始包含块具有视口的大小,也是包含<html>
元素的块。换句话说,绝对定位的元素将显示在<html>
元素之外,并相对于初始视口进行定位。
定位元素嵌套在 HTML 源代码中的<body>
中,但在最终布局中,它距页面顶部和左侧边缘 30px。我们可以更改定位上下文,即绝对定位元素相对于哪个元素进行定位。这是通过在元素的某个祖先元素上设置定位来完成的:在它嵌套其中的某个元素上(您不能将其相对于它未嵌套其中的元素进行定位)。要查看这一点,请将以下声明添加到您的body
规则中
position: relative;
这应该会产生以下结果
定位元素现在相对于<body>
元素进行定位。
注意:您可以在4_positioning-context.html
(查看源代码)处查看此示例。
介绍 z-index
所有这些绝对定位都很有趣,但我们还没有考虑另一个功能。当元素开始重叠时,是什么决定了哪些元素出现在其他元素之上,哪些元素出现在其他元素之下?在我们到目前为止看到的示例中,我们只有一个定位上下文中的定位元素,并且它出现在顶部,因为定位元素优先于非定位元素。那么当我们有多个时呢?
尝试将以下内容添加到您的 CSS 中,使第一段也成为绝对定位的
p:nth-of-type(1) {
position: absolute;
background: lime;
top: 10px;
right: 30px;
}
此时,您将看到第一段被着色为青柠色,移出了文档流,并稍微向上移动了一些。它也堆叠在原始的.positioned
段落下方,这两个段落重叠的地方。这是因为.positioned
段落是源顺序中的第二个段落,并且源顺序中较后的定位元素优先于源顺序中较早的定位元素。
您可以更改堆叠顺序吗?是的,您可以通过使用z-index
属性来实现。“z-index”是指 z 轴。您可能还记得课程中前面的一些内容,我们讨论过网页使用水平(x 轴)和垂直(y 轴)坐标来计算背景图像和阴影偏移等内容的位置。对于从左到右运行的语言,(0,0) 位于页面(或元素)的左上角,x 轴和 y 轴分别向右和向下延伸页面。
网页也有 z 轴:一条假想的线,从屏幕表面朝向您的脸部(或您喜欢放在屏幕前面的任何其他东西)。z-index
值会影响定位元素在此轴上的位置;正值将它们向上移动到堆栈中,负值将它们向下移动到堆栈中。默认情况下,所有定位元素的z-index
都为auto
,实际上为 0。
要更改堆叠顺序,请尝试将以下声明添加到您的p:nth-of-type(1)
规则中
z-index: 1;
您现在应该看到青柠色的段落位于顶部
请注意,z-index
仅接受无单位的索引值;您不能指定希望一个元素在 Z 轴上向上移动 23 像素——它不这样工作。较高的值将位于较低值之上,使用什么值由您决定。使用 2 或 3 的值将与使用 300 或 40000 的值产生相同的效果。
注意:您可以在 5_z-index.html
(查看源代码) 中查看此内容的示例。
固定定位
现在让我们来看一下固定定位。它的工作原理与绝对定位完全相同,但有一个关键区别:绝对定位将元素相对于其最近的已定位祖先(如果没有则为初始包含块)固定在适当位置,而固定定位通常将元素相对于视口可见部分固定在适当位置。(如果元素的祖先之一是固定包含块,因为其 transform 属性 的值不是 none,则会出现例外情况。)这意味着您可以创建有用的固定在适当位置的 UI 项目,例如始终可见的持久导航菜单,无论页面滚动多少。
让我们构建一个简单的示例来说明我们的意思。首先,从您的 CSS 中删除现有的 p:nth-of-type(1)
和 .positioned
规则。
现在更新 body
规则以删除 position: relative;
声明并添加一个固定高度,如下所示
body {
width: 500px;
height: 1400px;
margin: 0 auto;
}
现在,我们将为 h1 元素添加 position: fixed;
并将其置于视口顶部。将以下规则添加到您的 CSS 中
h1 {
position: fixed;
top: 0;
width: 500px;
margin-top: 0;
background: white;
padding: 10px;
}
需要 top: 0;
使其粘贴到屏幕顶部。我们为标题赋予与内容列相同的宽度,然后赋予白色背景以及一些填充和边距,以便内容不会在其下方可见。
如果保存并刷新,您将看到标题保持固定的有趣效果——内容似乎向上滚动并在其下方消失。但是请注意,某些内容最初是如何在标题下被裁剪的。这是因为已定位的标题不再出现在文档流中,因此其余内容向上移动到顶部。我们可以通过将所有段落向下移动一点来改进这一点。我们可以通过在第一个段落上设置一些顶部边距来实现。现在添加此内容
p:nth-of-type(1) {
margin-top: 60px;
}
您现在应该可以看到完成的示例
注意:您可以在 6_fixed-positioning.html
(查看源代码) 中查看此内容的示例。
粘性定位
还有另一个可用的位置值称为 position: sticky
,它比其他值更新一些。这基本上是相对定位和固定定位的混合体。它允许已定位的元素像相对定位一样工作,直到滚动到某个阈值(例如,距视口顶部 10px),然后它会变成固定定位。
基本示例
例如,可以使用粘性定位使导航栏随着页面滚动,直到某个点,然后粘贴到页面顶部。
.positioned {
position: sticky;
top: 30px;
left: 30px;
}
滚动索引
position: sticky
的一个有趣且常见的用法是创建一个滚动索引页面,其中不同的标题在到达时会粘贴到页面顶部。此类示例的标记可能如下所示
<h1>Sticky positioning</h1>
<dl>
<dt>A</dt>
<dd>Apple</dd>
<dd>Ant</dd>
<dd>Altimeter</dd>
<dd>Airplane</dd>
<dt>B</dt>
<dd>Bird</dd>
<dd>Buzzard</dd>
<dd>Bee</dd>
<dd>Banana</dd>
<dd>Beanstalk</dd>
<dt>C</dt>
<dd>Calculator</dd>
<dd>Cane</dd>
<dd>Camera</dd>
<dd>Camel</dd>
<dt>D</dt>
<dd>Duck</dd>
<dd>Dime</dd>
<dd>Dipstick</dd>
<dd>Drone</dd>
<dt>E</dt>
<dd>Egg</dd>
<dd>Elephant</dd>
<dd>Egret</dd>
</dl>
CSS 可能如下所示。在正常流中,<dt>
元素将与内容一起滚动。当我们向 <dt>
元素添加 position: sticky
以及 top
值为 0 时,支持的浏览器会在标题到达该位置时将其粘贴到视口顶部。然后,每个后续标题在向上滚动到该位置时将替换上一个标题。
dt {
background-color: black;
color: white;
padding: 10px;
position: sticky;
top: 0;
left: 0;
margin: 1em 0;
}
粘性元素相对于具有“滚动机制”的最近祖先而言是“粘性”的,这由其祖先的 overflow 属性决定。
注意:您可以在 7_sticky-positioning.html
(查看源代码) 中查看此示例。
测试你的技能!
您已阅读完本文,但您还记得最重要的信息吗?在继续之前,您可以找到一些进一步的测试来验证您是否保留了这些信息——请参阅 测试您的技能:定位。
总结
我相信您玩基本定位玩得很开心。虽然它不是用于整个布局的理想方法,但它适合许多特定的目标。