css中各类position的区别

6 min read,created at 2024-07-21
css前端position

基本介绍

position主要有5种,位置的确定要靠方向css top left bottom right以及z-index层高。

  • static默认值,方向css和层高css属性均无效
  • relative相对定位,方向css是相比于原来位置的移动,例如top: 10px是原来static位置往下移动10px。如果是百分比top: 10%是相对于父元素的高度的百分比,这一点很重要。
  • fixed固定视图位置,方向css是相对于视图的位置,例如top: 10px始终位于可见范围距离最上方10px的位置。
  • sticky粘性定位,与fixed类似,方向css是相对于视图的位置,不同的是sticky的方向偏移量是最小偏移的概念。例如top: 10px是指最小位于可见范围距离最上方10px的位置。如果当前位置在距离上方超过10px,那么就在当前位置不动,当小于10px的时候,才会固定在10px。
  • absolute绝对定位,方向css是相对于最近的非static祖先元素的移动,例如top: 10px是相对于最近的非static祖先元素往下移动10px。注意相对定位和绝对定位是相比dom元素的偏移,而非视图。
  • z-index越大越靠上,相同写在后面的靠上;
  • relativeabsolute是相对于dom元素偏移,fixedsticky是相对视图偏移;
  • relativeabsolute的偏移百分比是unstatic parent的百分比,fixedsticky则是视图的;
  • relativesticky元素会保持原来dom元素的空间,fixedabsolute不占用空间;

relative与translate

以下两种样式获得的效果是一样的,相对定位在原来基础上偏移(10px,10px)和直接平移(10px,10px)位置一致,并且两者都会占用原来dom元素的空间,可以说是完全一样。

.a {
    position: relative;
    top: 10px;
    left: 10px;
}

.b {
    translate: 10px 10px;
}

有区别的是其他移动单位,百分比top: 10%,在relative中是相对于父元素的高度,在translate中是相对于自身的高度。例如想要让一个元素位于屏幕中央:

.center {
    posiition: fixed;
    top: 50%;
    left: 50%;
    translate: -50%, -50%;
    /* transform: translate(-50%, -50%); */
}

absolute与unstatic父元素

上面提到absolute与非static的父元素密切相关,但是给的demo中父元素是static,所以最后兜底是按照整个html来算的绝对位置,下面简单的例子展示了absolute相对于非static parent的位置。

<h1>这是absolute相对于非static parent的例子</h1>
<div style="position: relative; height: 300px; background: #ccc">
      <h1>这是absolute相对于非static parent的例子</h1>
      <div style="position: absolute; top: 10px; left: 10px; background: #f00">
        距离父元素左上角10px
      </div>
</div>

img

在这个例子中,parent div采用了relative,因为没有方向css,所以和static的位置是一样的,但给子元素的absolute提供了定位锚点,所以不能忽略的。

sticky与flex

粘性定位最常见的例子就是侧边栏,例如我的这个博客的右侧目录栏就是sticky的。侧边栏的布局通常都是和内容部分左右布局,并且大概率使用了flex布局。

例如布局可能是这样的:

.title {
    width: 100%;
    font-size: 2rem;
}
.container {
    display: flex;
}
.content {
    width: 80%;
    height: 3000px;// 模拟很长的文章
}
.sider {
    width: 20%;
    position: sticky;
    top: 2px;
}
<head>
    <div class="title">这是文章标题</div>
</head>
<main>
    <div class="container">
        <div class="content">这是文章内容</div>
        <div class="sider">
            <ul>
                <li>这是目录1</li>
                <li>这是目录2</li>
                <li>这是目录3</li>
                <li>这是目录4</li>
            </ul>
        </div>
    </div>
</main>

我们对sider使用了粘性位置,但是实际会发现并没有生效,这是一个常见的问题,非常有代表性:

img

他的本质是因为,flex布局下每个元素默认会被拉伸,因为默认align-items: stretch,所以sider的高度也是3000像素,如下图.

img

需要修改,对齐为start对齐,即靠上对齐,如下。或者也可以修改.sider自己的对齐方式.sider {align-self: flex-start;}

.container {
    display: flex;
    align-items: flex-start;
}

img