基本介绍
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越大越靠上,相同写在后面的靠上;relative和absolute是相对于dom元素偏移,fixed和sticky是相对视图偏移;relative和absolute的偏移百分比是unstatic parent的百分比,fixed和sticky则是视图的;relative和sticky元素会保持原来dom元素的空间,fixed与absolute不占用空间;
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>

在这个例子中,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使用了粘性位置,但是实际会发现并没有生效,这是一个常见的问题,非常有代表性:

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

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