Skip to main content

定位

包含块

盒子模型中决定元素尺寸的属性、绝对定位和固定定位的偏移值,当我们对其赋予百分比值时,这些值的计算值,就是通过元素的包含块计算得来。

包含块的作用

包含块主要是为百分比单位 % 服务的,很多人认为百分比单位就是相对于其父元素属性来计算,这并不完全正确,准确来说是相对于该元素的 包含块 来计算,盒子模型中决定 元素尺寸 的属性、绝对定位固定定位 的偏移值,当我们对其赋予百分比值时,这些值的计算值,就是通过元素的 包含块 计算得来。主要就是如下属性:

  1. 要计算 width, left, right, padding, margin 这些属性由包含块的 width 属性的值来计算它的百分值
  2. 要计算 height topbottom 中的百分值,是通过包含块的 height 的值。如果包含块的 height 值会根据它的内容变化,而且包含块的 position 属性的值被赋予 relativestatic ,那么,这些值的计算值为 auto

小结如下:

  • width、height、min-width、max-width、min-height、max-height,百分比单位由包含块对应属性进行计算
  • margin、padding,百分比单位由包含块的 width 进行计算
  • left、right、top、bottom,百分比单位的水平偏移量由包含块的 width 进行计算,垂直偏移量由包含块的 height 进行计算

另外,包含块还是 absolutefixed 定位的参照物。

确定包含块

如何确定一个元素的包含块?其完全取决于该元素的 position 属性:

  1. 对于 staicrelativesticky 定位的元素,它的包含块默认为最近的 祖先块元素

  2. 对于 absolute 定位的元素,它的包含块为最近的 position 值不是 static 的祖先元素

  3. 对于 fixed 定位的元素,它的包含块通常情况下就是 视口,这里也涉及了连续媒体和分页媒体的概念,和打印页面有关

  4. 如果 position 属性是 absolutefixed,包含块也可能是由满足以下条件的最近父级元素的内边距区的边缘组成的:

    1. transformperspective 的值不是 none
    2. will-change 的值是 transformperspective
    3. filter 的值不是 nonewill-change 的值是 filter(只在 Firefox 下生效).
    4. contain 的值是 paint (例如: contain: paint;)

position 属性

其作用是指定一个元素在文档中的定位方式。

具有如下五种取值:

  • static 默认值,元素在标准文档流中的定位
  • absolute 绝对定位,元素会被移出正常文档流
  • relative 相对定位
  • fixed 固定定位,元素会被移出正常文档流
  • sticky 粘性定位
important
  • 任何元素(块级/行内)都可以使用 position
  • 只有将盒子的定位设置为非 static 才能使用 top, right, bottom, left 和 z-index 属性
  • 关于 top, right, bottom, left 都是以盒子的左上角作为 "质点"

static

该定位为所有元素的默认定位,使用 标准文档流,此时 top, right, bottom, left 和 z-index 属性无效。

relative

相对定位,其特点如下:

  • 盒子偏移时,是相对于 自身原来位置 的左上角作为参照系
  • 不会使元素脱离标准文档流,不管元素如何移动,其原来占据的空间依旧是处于标准文档流中的
  • 设置了相对定位的元素,可以给绝对定位当参照系

absolute

绝对定位,其特点如下:

  • 盒子偏移时,是相对于 最近的设置了非 static 定位的祖先元素左上角 作为参照系
  • 如果祖先元素都为 static 定位,那么就相对于 html,即整个页面的左上角
  • 设置了绝对定位的元素会脱离文档流,不会为元素预留空间
important

一般来说,是把需要当作参照系的祖先元素设置为 relative 定位,因为这样不会改变祖先元素的文档流。

绝对定位的 "参照系" 与 "质点"

首先明确,参照系和质点都是一个点,参照系的作用是给定位盒子当作参考:

  • 无论参考盒子是否具有 margin 和 padding,参照系一定位于参考盒子 border 以内的左上角
  • 参考盒子的 padding 会影响定位盒子初始的 left、top

定位盒子的质点表示的就是整个盒子 left、right、top、bottom 的位置,质点是位于 定位盒子占据空间大小的左上角,所以质点是不一定存在于定位盒子的 border 以内的。我们看下面的例子:

<div class="father">
<div class="child"></div>
</div>

这里我们把 father 设置为相对定位,child 设置为绝对定位,给 father 加一个 margin 和 padding:

.father {
width: 500px;
height: 500px;
margin: 50px;
padding: 30px;
border: 50px solid;

position: relative;

.child {
width: 100px;
height: 100px;
border: solid;

position: absolute;
}
}

pic.sm

此时因为它的 margin 为 0,所以绝对定位元素是以边框以外的左上角作为 "质点",,此时它的 left 和 right 实际上等于 30px,因为受到了参考元素 padding 的影响。

下面我们直接声明 left: 0, top: 0,就会让绝对定位盒子回到 (0, 0) 的位置了:

.child {
width: 100px;
height: 100px;
border: solid;

left: 0;
top: 0;

position: absolute;
}

pic.sm

fixed

固定定位,其特点如下:

  • 一般情况下参照系位于整个 视口 的左上角
  • 当元素祖先的 transform, perspectivefilter 属性非 none 时,参照系会由 视口 变为该祖先元素(因为包含块变了)
  • 固定定位的盒子会脱离标准文档流,并不会为元素预留空间
  • 页面滚动时,盒子不会随着滚动,而是固定在视口中,一般页面的广告弹窗就是固定定位
  • 会创建新的层叠上下文

sticky

粘性定位,其特点如下:

  • 粘性盒子的参照物是最近的 祖先滚动元素(有滚动条的元素)

  • 粘性盒子的偏移量可以理解为与 参照物 的最小限度距离:

    • 当参照物滚动时,粘性盒子会跟着滚动,达到偏移量限度后就会停止滚动(防止粘性盒子滚出视口)
  • 粘性盒子不会脱离文档流,会为元素预留空间

  • 会创建新的层叠上下文

这个定位一般用于导航栏。

CodePen

Reference