什么是定位
定位允许你从正常的文档流布局中取出元素,并使它们具有不同的行为,例如放在另一个元素的上面,或者始终保持在浏览器视窗内的同一位置。
翻看我们前面的文档流文档,我们已经介绍过,正常的元素是会按照块级元素和内联元素的特性进行依次排列,而如果想要将一个元素放在另一个元素上,或者将一个元素固定显示在页面的某些位置,正常文档流是实现不了的,需要借助定位来实现。
定位有哪几种形式
我们在实际开发的过程中,常用到的定位有以下几种形式
- 静态定位
- 相对定位
- 绝对定位
- 固定定位
- sticky定位
定位的详细介绍
静态定位
静态定位是浏览器默认的定位方式。也意味着是按照正常文档流的方式排列元素的。设不设置对于页面来说没有任何变化。
用法
position: static;
相对定位
相对定位和静态定位非常相似,占据正常的文档流中,只是你还可以修改它的最终位置,包括让它与页面上的其他元素重叠。但是静态定位是不能这样的。
用法
position: relative;
如何只是单独设置这一个属性也是没有任何变化的,需要借助top, bottom, left, right属性来对位置进行设置,这样才可以实现定位的效果。 需要特别注意的是,相对定位是相对元素自身之前的位置进行定位,这四个位置属性也是针对原来的位置来移动的。
<div class='test-wrap'>
<!-- 定位展示 -->
<div class="first-box">我是第一个盒子</div>
<div class="second-box">我是第二个盒子</div>
<div class="third-box">我是第三个盒子</div>
</div>
.test-wrap {
color: #fff;
padding: 0px 30px;
.first-box {
height: 100px;
background: lightblue;
}
.second-box {
height: 100px;
background: lightpink;
position: relative;
top: 30px;
left: 30px;
}
.third-box {
height: 100px;
background: lightgoldenrodyellow;
}
}
在设置相对定位之前效果是这样的
在设置相对定位之效果是这样的
绝对定位
绝对定位与静态定位是非常不同的,它会脱离文档流,而且也会脱离文本流,从下面的例子也可以看出来。
用法
position: absolute;
还是上面的例子,即使只设置了这一行代码,页面也是有变化的,因为绝对定位会脱离文档流,因此你看到的效果是这样的。
.second-box {
height: 100px;
background: lightpink;
position: absolute;
}
绝对定位也可以搭配定位属性top, bottom, left, right一起使用,从而更精确地定位元素的位置。
.second-box {
height: 100px;
background: lightpink;
position: absolute;
top: 40px;
left: 20px;
}
小结
绝对定位是相对于最近的不是static的父元素来进行定位的,如果没有找到的话,就根据body来进行定位。 如果仅仅只是设置了position: absolute;而没有设置位置方向的偏移量的话,那么表现就是脱离文档流和文本流,如果两个都设置的话,才会是上面那种相对某个元素的定位。
固定定位
固定定位的工作方式和绝对定位完全相同,因此也经常把固定定位看成是稍微特殊一点的绝对定位。它和绝对定位之间的唯一区别就是固定定位是相对于浏览器窗口本身。
用法
position: fixed;
如果仅仅只设置这一行代码,而没有设置方向偏移量的话,那么它的表现和只设置position: absolute是完全一样的,脱离文档流和文本流。
再设置一下偏移量
.second-box {
height: 100px;
background: lightpink;
position: fixed;
top: 0;
}
给第一个元素设置上面的外边距,第二个元素设置固定定位
.first-box {
height: 100px;
background: lightblue;
margin-top: 50px;
}
.second-box {
height: 100px;
background: lightpink;
position: fixed;
top: 0;
}
效果如下: 第二个盒子固定,出现一个滚动条
定位的上下文
通俗地理解定位的上下文,就是元素的定位是相对于哪个元素来进行定位的,这里就会涉及到定位的上下文。在理解定位的上下文之前,我们先来理解一下概念----包含块。
包含块
一个元素的包含块会影响到它的尺寸和位置。比如,width, height, padding, margin设置百分比时,绝对定位元素(display: absolute;和display: fixed)的偏移量设置百分比时,这些都是根据它的包含块来计算的。那么,怎么来确定元素的包含块呢?
包含块的确定
- 如果position属性为static,relative, sticky,包含块可能由离他最近的祖先块元素(比如说 inline-block, block 或 list-item 元素)的内容区的边缘组成,也可能会创建格式化上下文(比如说 a table container, flex container, grid container, 或者是 the block container 自身)。
- 如果position属性为absolute, 包含块就是由它的最近的position不是static的祖先元素(也就是值为fixed, absolute, relative 或 sticky)的内容区的边缘组成。
- 如果position属性为fixed, 在连续媒体的情况下包含块是viewport, 在分页媒体的情况下包含块是分页区域。
- 如果position属性为absolute或fixed, 包含块也可能是由满足以下条件的最近的父元素的内容区的边缘组成。
- transform或perspective的值不是none
- will-change 的值是 transform 或 perspective
- filter 的值不是 none 或 will-change 的值是 filter(只在 Firefox 下生效).
- contain 的值是 paint (例如: contain: paint;)
第四种情况用的比较少,了解一下,到时候遇到的时候再重点关注一下。
根据包含块计算百分比
- 要计算 height top 及 bottom 中的百分值,是通过包含块的 height 的值。如果包含块的 height 值会根据它的内容变化,而且包含块的 position 属性的值被赋予 relative 或 static ,那么,这些值的计算值为 auto。
- 要计算 width, left, right, padding, margin 这些属性由包含块的 width 属性的值来计算它的百分值。
理解了包含块之后,我们就知道了定位的上下文等同于元素的包含块啦。但是如果所有的元素都没有显示地定义position的话,相当于是它的所有的祖先元素的position都是static, 那么绝对定位就会被包含在初始块容器中。也就是元素,那么它的定位上下文就相当于是body。
z-index
z-index属性设定了一个定位元素及其后代元素或flex项目的z-order. 当元素之间重叠的时候,z-index较大的元素会覆盖较小的元素在上层进行显示。
网页也有一个 z 轴:一条从屏幕表面到你的脸(或者在屏幕前面你喜欢的任何其他东西)的虚线。z-index 值影响定位元素位于该轴上的位置;正值将它们移动到堆栈上方,负值将它们向下移动到堆栈中。默认情况下,定位的元素都具有 z-index 为 auto,实际上为 0。
语法
/* 字符值 */
z-index: auto;
/* 整数值 */
z-index: 0;
z-index: 3;
z-index: 289;
z-index: -1;/* 使用负值降低优先级 */
/* 全局值 */
z-index: inherit;
z-index: initial;
z-index: unset;
设置为auto:盒子不会创建一个新的本地堆叠上下文。在当前堆叠上下文中生成的盒子的堆叠层级和父级盒子相同。
设置为整数值:整数值生成的盒子在当前堆叠上下文中的堆叠层级。此盒子也会创建一个堆叠层级为0的本地堆叠上下文。这意味着后代元素的z-indexes不与此元素的外部元素的z-indexes进行对比。 上面这点也正好解释了为什么我们给某个元素的z-index的值设置特别大的时候却没有展示在最上层,就是因为当前元素的父元素的堆叠层级太低。
position: sticky
相比其他定位方式,这个定位属性值比较新一些。它基本上是相对位置和固定位置的混合体,允许被定位元素表现得像相对定位一样,直到滚动到某个阈值点(例如距离视口10px)为止,此后它就变得固定了。也被称为粘性定位,用于吸顶布局中。比如:使导航栏随页面滚动直到特定点,然后粘在页面顶部。
用法
position: sticky;
仅仅设置这一行代码是没有任何作用的,页面没有任何变化,必须搭配位置方向偏移量来使用。
position: sticky;
top: 0px;
常见的标题吸顶
<div class='test-wrap'>
<!-- 定位展示 -->
<article>
<section>
<h4>新闻标题1</h4>
<content>内容1,巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉。。。。。。。</content>
<footer>评论1</footer>
</section>
<section>
<h4>新闻标题2</h4>
<content>内容2,巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉。。。。。。。</content>
<footer>评论2</footer>
</section>
<section>
<h4>新闻标题3</h4>
<content>内容3,巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉。。。。。。。</content>
<footer>评论3</footer>
</section>
<section>
<h4>新闻标题4</h4>
<content>内容4,巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉巴拉。。。。。。。</content>
<footer>评论4</footer>
</section>
</article>
</div>
.test-wrap {
height: 200px;
overflow: auto;
h4 {
background-color: lightblue;
position: sticky;
top: 0;
}
}