Positioning

 

定位使您可以将元素从常规文档布局流程中移出,并使其行为有所不同. 例如,彼此并排放置,或始终保留在浏览器视口内的同一位置. 本文介绍了不同的position值,以及如何使用它们.

Prerequisites: HTML基础知识(研究HTML简介 ),以及有关CSS如何工作的想法(研究CSS简介 ).
Objective: 了解CSS定位的工作原理.

如果可能的话,我们希望您能在本地计算机上进行练习—从我们的GitHub存储库( 此处源代码 )中获取0_basic-flow.html的副本, 0_basic-flow.html其用作起点.

Introducing positioning

定位的整个想法是使我们能够覆盖上述基本文档流行为,以产生有趣的效果. 如果要从默认布局流位置稍微改变布局中某些框的位置,以给人一种古怪而痛苦的感觉,该怎么办? 定位是您的工具. 或者,如果您要创建一个UI元素,该UI元素浮在页面其他部分的顶部,并且/或者无论页面滚动了多少,总是位于浏览器窗口内的同一位置? 定位使这种布局工作成为可能.

您可以对HTML元素实施多种不同类型的定位. 为了使特定类型的定位在元素上处于活动状态,我们使用position属性.

Static positioning

静态定位是每个元素都会获得的默认位置-只是意味着"将元素放入文档布局流程中的正常位置-在这里看不到什么特别之处".

为了说明这一点,并为以后的部分设置示例,请首先在HTML的第二个<p>中添加一个positioned class

<p class="positioned"> ... </p>

现在,将以下规则添加到CSS的底部:

.positioned {
  position: static;
  background: yellow;
}

如果现在保存并刷新,除了第二段的更新背景色之外,您将看不到任何区别. 很好-正如我们之前所说,静态定位是默认行为!

注意 :此时您可以在1_static-positioning.html 看到示例( 请参见源代码 ).

Relative positioning

相对定位是我们要研究的第一种定位类型. 这与静态定位非常相似,不同之处在于,一旦定位的元素在常规布局流程中占据了位置,则可以修改其最终位置,包括使其与页面上的其他元素重叠. 继续更新代码中的position声明:

position: relative;

如果在此阶段保存并刷新,则根本看不到结果有任何变化. 那么如何修改元素的位置呢? 您需要使用topbottomleftright属性,我们将在下一节中对其进行说明.

Introducing top, bottom, left, and right

topbottomleftrightposition一起使用,以精确指定将定位的元素移动到的位置. 要尝试此操作,请将以下声明添加到CSS中的.positioned规则:

top: 30px;
left: 30px;

注意 :这些属性的值可以采用您在逻辑上期望的任何单位 -像素,毫米,单位,%等.

如果现在保存并刷新,将会得到类似以下的结果:

酷吧? 好的,所以这可能不是您所期望的-如果我们指定顶部和左侧,为什么它会移到底部和右侧? 最初听起来不合逻辑,但这只是相对定位起作用的方式-您需要考虑一种不可见的力,该力会推动已定位盒子的指定一侧,并朝相反方向移动. 因此,例如,如果您指定top: 30px; ,则用力推箱子的顶部,使其向下移动30px.

注意 :此时您可以在2_relative-positioning.html 看到示例( 请参见源代码 ).

Absolute positioning

绝对定位带来了截然不同的结果. 让我们尝试如下更改位置声明:

position: absolute;

如果现在保存并刷新,您将看到类似以下内容:

首先,请注意,已定位元素在文档流中应该位于的间隙不再存在-第一和第三元素已经闭合在一起,就像不再存在一样! 好吧,在某种程度上,这是事实. 常规文档布局流程中不再存在绝对定位的元素. 取而代之的是,它位于与其他所有内容分开的自己的图层上. 这非常有用:这意味着我们可以创建独立的UI功能,而不会干扰页面上其他元素的位置. 例如,弹出信息框和控制菜单; 翻转面板; 可以在页面上任意位置拖放的UI功能; 等等...

其次,请注意元素的位置已更改-这是因为topbottomleftright行为与绝对定位不同. 他们没有指定元素应该移动的方向,而是指定了元素与每个包含元素的侧面之间的距离. 因此,在这种情况下,我们说的是绝对定位的元素应位于"包含元素"顶部的30px处,而距左边的30px处.

注意 :如果需要,可以使用topbottomleftright来调整元素的大小. 尝试设置top: 0; bottom: 0; left: 0; right: 0; top: 0; bottom: 0; left: 0; right: 0;margin: 0; 在您定位的元素上,看看会发生什么! 之后再放回去...

注意 :是的,边距仍然会影响定位的元素. 但是,保证金不会崩溃.

注意 :此时,您可以在3_absolute-positioning.html 看到示例( 请参见源代码 ).

Positioning contexts

绝对定位的元素的"包含元素"是哪个元素? 这在很大程度上取决于所定位元素的祖先的位置属性(请参阅识别包含块 ).

如果没有祖先元素具有明确定义的position属性,则默认情况下,所有祖先元素都将具有静态位置. 这样的结果是,绝对定位的元素将包含在初始包含块中 . 初始包含块具有视口的尺寸,也是包含<html>元素的块. 简而言之,绝对定位的元素将包含在<html>元素之外,并相对于初始视口定位.

被定位的元素嵌套在HTML源代码的<body>内,但在最终布局中,它与页面边缘的顶部和左侧相距30px. 我们可以更改定位上下文 -绝对定位的元素相对于哪个元素定位. 这是通过将元素的祖先上的位置设置为-嵌套在其中的元素之一来实现的(您不能相对于未嵌套在其中的元素来定位它). 为了证明这一点,请在您的body规则中添加以下声明:

position: relative;

这应该得到以下结果:

现在,已定位元素相对于<body>元素位于.

Note: You can see the example at this point live at 4_positioning-context.html (see source code).

Introducing z-index

所有这些绝对定位都是很有趣的,但是我们还没有考虑另一件事-当元素开始重叠时,是什么决定哪些元素出现在其他元素之上? 在到目前为止的示例中,由于定位元素胜过未定位元素,因此在定位上下文中只有一个定位元素,它出现在顶部. 当我们有一个以上的时候呢?

尝试将以下内容添加到CSS中,以使第一段也绝对定位:

p:nth-of-type(1) {
  position: absolute;
  background: lime;
  top: 10px;
  right: 30px;
}

此时,您将看到第一段为彩色的石灰,从文档流中移出,并从原始位置移到了上方. 它也堆叠在原始.positioned段落下面,两者重叠. 这是因为.positioned段落是源顺序中的第二段,并且源顺序中较后的定位元素会胜过源顺序中较早的定位元素.

您可以更改堆叠顺序吗? 是的,您可以使用z-index属性. " z索引"是对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上实时查看示例( 请参阅源代码 ).

Fixed positioning

现在让我们看一下固定位置. 它的工作方式与绝对定位完全相同,但有一个关键的区别:绝对定位将元素固定在相对于其最接近的祖先的位置(如果没有,则为文档的根元素,即<html>元素) , 固定位置会将元素固定在相对于浏览器视口本身的位置. 这意味着您可以创建固定在位的有用的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

还有另一个可用的位置值称为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;
}

注意 :您可以在7_sticky-positioning.html实时查看此示例( 请参阅源代码 ).

Test your skills!

You've reached the end of this article, but can you remember the most important information? You can find some further tests to verify that you've retained this information before you move on — see Test your skills: Positioning.

Summary

我相信您在基本定位方面玩得很开心; 虽然这不是您要用于整个布局的一种方法,但是您可以看到有许多适合的任务.

See also

In this module