position

Baseline 已广泛支持

此特性已相当成熟,可在许多设备和浏览器版本上使用。自 ⁨2015 年 7 月⁩以来,各浏览器均已提供此特性。

position 这个 CSS 属性用于设置一个元素在文档中的定位方式。当元素的 position 值不为 static 时,toprightbottomleft 这类物理属性以及 inset-block-startinset-block-endinset-inline-startinset-inline-end 这类流相对逻辑属性可以用来决定已定位元素的最终位置。

试一试

position: static;
position: relative;
top: 40px;
left: 40px;
position: absolute;
inset-inline-start: 40px;
inset-block-start: 40px;
position: sticky;
top: 20px;
<section class="default-example" id="default-example">
  <div id="example-element-container">
    <p>
      In this demo you can control the <code>position</code> property for the
      yellow box.
    </p>
    <div class="box"></div>
    <div class="box" id="example-element"></div>
    <div class="box"></div>
    <p class="clear">
      To see the effect of <code>sticky</code> positioning, select the
      <code>position: sticky</code> option and scroll this container.
    </p>
    <p>
      The element will scroll along with its container, until it is at the top
      of the container (or reaches the offset specified in <code>top</code>),
      and will then stop scrolling, so it stays visible.
    </p>
    <p>
      The rest of this text is only supplied to make sure the container
      overflows, so as to enable you to scroll it and see the effect.
    </p>
    <hr />
    <p>
      Far out in the uncharted backwaters of the unfashionable end of the
      western spiral arm of the Galaxy lies a small unregarded yellow sun.
      Orbiting this at a distance of roughly ninety-two million miles is an
      utterly insignificant little blue green planet whose ape-descended life
      forms are so amazingly primitive that they still think digital watches are
      a pretty neat idea.
    </p>
  </div>
</section>
section {
  align-items: flex-start;
  overflow: auto;
}

.box {
  background-color: rgb(0 0 255 / 0.2);
  border: 3px solid blue;
  float: left;
  width: 65px;
  height: 65px;
}

.box + .box {
  margin-left: 10px;
}

.clear {
  clear: both;
  padding-top: 1em;
}

#example-element-container {
  position: relative;
  text-align: left;
}

#example-element {
  background-color: yellow;
  border: 3px solid red;
  z-index: 1;
}

语法

css
position: static;
position: relative;
position: absolute;
position: fixed;
position: sticky;

/* Global values */
position: inherit;
position: initial;
position: revert;
position: revert-layer;
position: unset;

static

该元素根据文档的常规流进行定位。toprightbottomleftz-index 属性均无效。这是默认值。

relative

该元素根据文档的常规流进行定位,然后根据 toprightbottomleft 的值,相对于自己进行偏移。该偏移不会影响任何其他元素的位置;因此,页面布局中为该元素保留的空间与 positionstatic 时相同。

z-index 的值不为 auto 时,该值会创建一个新的层叠上下文。它对 table-*-grouptable-rowtable-columntable-celltable-caption 元素的影响是未定义的。

absolute

该元素会脱离常规的文档流,并且在页面布局中不会为其创建空间。该元素相对于其最近的已定位祖先元素(如果有)或初始包含块进行定位。其最终位置由 toprightbottomleft 的值决定。

z-index 的值不为 auto 时,该值会创建一个新的层叠上下文。绝对定位的盒子的外边距不会与其他外边距发生折叠

fixed

该元素会脱离常规的文档流,并且在页面布局中不会为其创建空间。该元素相对于其初始包含块进行定位,对于可视化媒体,该包含块就是视口。其最终位置由 toprightbottomleft 的值决定。

该值总是会创建一个新的层叠上下文。在打印的文档中,该元素会放置在每一页的相同位置。

sticky

该元素根据文档的常规流进行定位,然后根据 toprightbottomleft 的值,相对于其最近的滚动祖先包含块(最近的块级祖先,包括与表格相关的元素)进行偏移。该偏移不会影响任何其他元素的位置。

该值总是会创建一个新的层叠上下文。请注意,粘性元素会“粘”在其最近的具有“滚动机制”(当 overflowhiddenscrollautooverlay 时创建)的祖先上,即使该祖先不是最近的实际滚动祖先。

备注: 对于需要粘性定位的轴,至少需要将一个inset 属性(topinset-block-startrightinset-inline-end 等)设置为非 auto 的值。如果某个轴的两个 inset 属性都设置为 auto,那么在该轴上,sticky 的行为将与 relative 相同。

描述

定位的类型

  • 已定位元素(positioned element)是指其计算后position 值为 relativeabsolutefixedsticky 的元素。(换句话说,就是除了 static 之外的任何值。)
  • 相对定位元素(relatively positioned element)是指其计算后position 值为 relative 的元素。topbottom 属性指定了其相对于常规位置的垂直偏移;leftright 属性指定了水平偏移。
  • 绝对定位元素(absolutely positioned element)是指其计算后position 值为 absolutefixed 的元素。toprightbottomleft 属性指定了其相对于元素包含块边缘的偏移。(包含块是该元素定位所参照的祖先。)如果元素有外边距,它们会加到偏移量上。该元素会为其内容建立一个新的块格式化上下文(BFC)。
  • 粘性定位元素(stickily positioned element)是指其计算后position 值为 sticky 的元素。它被视为相对定位,直到其包含块在其流根(或其滚动的容器)内越过指定的阈值(例如将 top 设置为非 auto 的值),此时它被视为“粘住”,直到遇到其包含块的对边。

大多数情况下,将 heightwidth 设置为 auto 的绝对定位元素会根据其内容调整大小。然而,非替换的绝对定位元素可以通过同时指定 topbottom 并将 height 留空(即 auto)来填充可用的垂直空间。同样,它们也可以通过同时指定 leftright 并将 width 留为 auto 来填充可用的水平空间。

除了刚才描述的情况(绝对定位元素填充可用空间)之外:

  • 如果同时指定了 topbottom(技术上讲,都不是 auto),top 优先。
  • 如果同时指定了 leftright,当 directionltr(如英语、水平书写的日语等)时,left 优先;当 directionrtl(如波斯语、阿拉伯语、希伯来语等)时,right 优先。

无障碍

确保使用 absolutefixed 定位的元素在页面放大以增加文本大小时不会遮挡其他内容。

性能与可访问性

滚动包含 fixedsticky 内容的元素可能会导致性能和可访问性问题。当用户滚动时,浏览器必须在新的位置重绘粘性或固定内容。根据需要重绘的内容、浏览器性能和设备处理速度,浏览器可能无法以 60 帧/秒的速度管理重绘。这种情况可能导致卡顿,更重要的是,会给有敏感性问题的人带来可访问性方面的担忧。一种解决方案是在定位的元素上添加 will-change: transform,以在其自己的图层上渲染元素,从而提高重绘速度,进而改善性能和可访问性。

正式定义

初始值static
应用于所有元素
继承性
计算值同指定值
动画类型离散
创建层叠上下文

正式语法

position = 
static |
relative |
absolute |
sticky |
fixed |
<running()>

<running()> =
running( <custom-ident> )

示例

相对定位

相对定位的元素会从其在文档中的常规位置偏移一定的量,但这个偏移不会影响其他元素。在下面的示例中,请注意其他元素的放置方式,就好像“Two”仍然占据其常规位置的空间一样。

HTML

html
<div class="box" id="one">One</div>
<div class="box" id="two">Two</div>
<div class="box" id="three">Three</div>
<div class="box" id="four">Four</div>

CSS

css
* {
  box-sizing: border-box;
}

.box {
  display: inline-block;
  width: 100px;
  height: 100px;
  background: red;
  color: white;
}

#two {
  position: relative;
  top: 20px;
  left: 20px;
  background: blue;
}

绝对定位

相对定位的元素保留在文档的常规流中。相比之下,绝对定位的元素会脱离常规流;因此,其他元素的定位就好像它不存在一样。绝对定位的元素是相对于其最近的已定位祖先(即,最近的非 static 祖先)进行定位的。如果不存在已定位的祖先,它将相对于 ICB(初始包含块)进行定位,即文档根元素的包含块。

HTML

html
<h1>Absolute positioning</h1>

<p>
  I am a basic block level element. My adjacent block level elements sit on new
  lines below me.
</p>

<p class="positioned">
  By default we span 100% of the width of our parent element, and we are as tall
  as our child content. Our total width and height is our content + padding +
  border width/height.
</p>

<p>
  We are separated by our margins. Because of margin collapsing, we are
  separated by the width of one of our margins, not both.
</p>

<p>
  inline elements <span>like this one</span> and <span>this one</span> sit on
  the same line as one another, and adjacent text nodes, if there is space on
  the same line. Overflowing inline elements
  <span>wrap onto a new line if possible — like this one containing text</span>,
  or just go on to a new line if not, much like this image will do:
  <img src="https://mdn.github.io/shared-assets/images/examples/long.jpg" />
</p>

CSS

css
* {
  box-sizing: border-box;
}

body {
  width: 500px;
  margin: 0 auto;
}

p {
  background: aqua;
  border: 3px solid blue;
  padding: 10px;
  margin: 10px;
}

span {
  background: red;
  border: 1px solid black;
}

.positioned {
  position: absolute;
  background: yellow;
  inset-block-start: 30px;
  inset-inline-start: 30px;
}

结果

固定定位

固定定位与绝对定位类似,不同之处在于元素的包含块是由视口建立的初始包含块,除非任何祖先的 transformperspectivefilter 属性被设置为非 none 的值(请参阅固定定位包含块),这会导致该祖先取代元素包含块的位置。这可以用来创建一个“浮动”元素,无论如何滚动,它都保持在相同的位置。在下面的示例中,盒子“One”被固定在距离页面顶部 80 像素和左侧 10 像素的位置。即使在滚动之后,它相对于视口的位置也保持不变。此外,当 will-change 属性设置为 transform 时,也会建立一个新的包含块。

HTML

html
<div class="outer">
  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam congue tortor
    eget pulvinar lobortis. Vestibulum ante ipsum primis in faucibus orci luctus
    et ultrices posuere cubilia Curae; Nam ac dolor augue. Pellentesque mi mi,
    laoreet et dolor sit amet, ultrices varius risus. Nam vitae iaculis elit.
    Aliquam mollis interdum libero. Sed sodales placerat egestas. Vestibulum ut
    arcu aliquam purus viverra dictum vel sit amet mi. Duis nisl mauris, aliquam
    sit amet luctus eget, dapibus in enim. Sed velit augue, pretium a sem
    aliquam, congue porttitor tortor. Sed tempor nisl a lorem consequat, id
    maximus erat aliquet. Sed sagittis porta libero sed condimentum. Aliquam
    finibus lectus nec ante congue rutrum. Curabitur quam quam, accumsan id
    ultrices ultrices, tempor et tellus.
  </p>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam congue tortor
    eget pulvinar lobortis. Vestibulum ante ipsum primis in faucibus orci luctus
    et ultrices posuere cubilia Curae; Nam ac dolor augue. Pellentesque mi mi,
    laoreet et dolor sit amet, ultrices varius risus. Nam vitae iaculis elit.
    Aliquam mollis interdum libero. Sed sodales placerat egestas. Vestibulum ut
    arcu aliquam purus viverra dictum vel sit amet mi. Duis nisl mauris, aliquam
    sit amet luctus eget, dapibus in enim. Sed velit augue, pretium a sem
    aliquam, congue porttitor tortor. Sed tempor nisl a lorem consequat, id
    maximus erat aliquet. Sed sagittis porta libero sed condimentum. Aliquam
    finibus lectus nec ante congue rutrum. Curabitur quam quam, accumsan id
    ultrices ultrices, tempor et tellus.
  </p>
  <div class="box" id="one">One</div>
</div>

CSS

css
* {
  box-sizing: border-box;
}

.box {
  width: 100px;
  height: 100px;
  background: red;
  color: white;
}

#one {
  position: fixed;
  top: 80px;
  left: 10px;
  background: blue;
}

.outer {
  width: 500px;
  height: 300px;
  overflow: scroll;
  padding-left: 150px;
}

结果

粘性定位

下面的 CSS 规则将 ID 为 one 的元素设置为相对定位,直到视口滚动到该元素距离顶部 10 像素的位置。超过该阈值后,该元素将被固定在距离顶部 10 像素的位置。

css
#one {
  position: sticky;
  top: 10px;
}

带有粘性标题的列表

粘性定位的一个常见用途是按字母顺序排列的列表中的标题。标题“B”会出现在以“A”开头的项目下方,直到它们被滚动出屏幕。标题“B”不会随其他内容一起滑出屏幕,而是会固定在视口的顶部,直到所有“B”项都滚动出屏幕,此时它将被标题“C”覆盖,依此类推。

你必须使用 toprightbottomleft 中的至少一个来指定一个阈值,才能使粘性定位按预期工作。否则,它将与相对定位无法区分。

HTML
html
<dl>
  <div>
    <dt>A</dt>
    <dd>Andrew W.K.</dd>
    <dd>Apparat</dd>
    <dd>Arcade Fire</dd>
    <dd>At The Drive-In</dd>
    <dd>Aziz Ansari</dd>
  </div>
  <div>
    <dt>C</dt>
    <dd>Chromeo</dd>
    <dd>Common</dd>
    <dd>Converge</dd>
    <dd>Crystal Castles</dd>
    <dd>Cursive</dd>
  </div>
  <div>
    <dt>E</dt>
    <dd>Explosions In The Sky</dd>
  </div>
  <div>
    <dt>T</dt>
    <dd>Ted Leo &amp; The Pharmacists</dd>
    <dd>T-Pain</dd>
    <dd>Thrice</dd>
    <dd>TV On The Radio</dd>
    <dd>Two Gallants</dd>
  </div>
</dl>
CSS
css
* {
  box-sizing: border-box;
}

dl > div {
  background: white;
  padding-top: 24px;
}

dt {
  background: #b8c1c8;
  border-bottom: 1px solid #989ea4;
  border-top: 1px solid #717d85;
  color: white;
  font:
    bold 18px/21px "Helvetica",
    "Arial",
    sans-serif;
  margin: 0;
  padding: 2px 0 0 12px;
  position: -webkit-sticky;
  position: sticky;
  top: -1px;
}

dd {
  font:
    bold 20px/45px "Helvetica",
    "Arial",
    sans-serif;
  margin: 0;
  padding-left: 12px;
  white-space: nowrap;
}

dd + dd {
  border-top: 1px solid #cccccc;
}
结果

设置了所有内边距边界的粘性定位

以下示例演示了当所有内边距边界都设置时元素的行为。在这里,我们在一个段落中有两个灯泡表情符号。灯泡使用粘性定位,内边距边界被指定为距离顶部 50 像素,右侧 100 像素,底部 50 像素,左侧 50 像素。父级 div 元素上的灰色背景标记了内边距区域。

HTML
html
Use scrollbars to put the light bulbs(💡) in the right place in the following
text:
<div>
  <p>
    The representation of an idea by a light bulb(<span class="bulb">💡</span>)
    is a commonly used metaphor that symbolizes the moment of inspiration or the
    birth of a new idea. The association between a light bulb and an idea can be
    traced back to the invention of the incandescent light bulb(<span
      class="bulb"
      >💡</span
    >) by Thomas Edison in the late 19th century. The light bulb is a powerful
    symbol because it represents illumination, clarity, and the sudden
    brightening of one's thoughts or understanding. When someone has an idea, it
    is often described as a light bulb turning on in their mind, signifying a
    moment of insight or creativity. The image of a light bulb also suggests the
    idea of energy, power, and the potential for growth and development.
  </p>
</div>
CSS
css
.bulb {
  position: sticky;
  inset: 50px 100px;
}

div {
  /* mark area defined by the inset boundaries using gray color */
  background: linear-gradient(#99999999, #99999999) 100px 50px / 192px 100px
    no-repeat;
}
结果

当你将两个灯泡都放在它们正确的位置时,你会注意到它们在内边距区域内是相对定位的。当你将它们移出内边距区域时,它们会被固定(粘性定位)到该方向的内边距边界。

规范

规范
CSS 定位布局模块第 3 级
# position-property

浏览器兼容性

另见