我真的懂position了吗?
前言
近期笔者在面试的时候,突然注意到一个问题,前端的知识体系比较驳杂,没有说特别系统性的学习,就拿个我自己举个例子,学习前端知识
一开始可能从视频->文档->博客
,这样其实很多东西被我们遗漏。很多知识其实是零零散散的补充
。这样就导致一些概念
会缺失。
在我近期的面试中我就遇到一个几个问题
-
relative根据什么进行定位的?
-
absolute根据什么进行定位的?
如果祖先元素没有relative根据什么定位?
-
fixed根据什么定位?
这几个题目其实很简单,大家都知道根据什么进行定位,但是如果描述起来可能不尽人意。
后来我进行了了解才知道了一些底层的知识
,仿佛打开了新世界
,原来还有这么多概念我们不知道的
例如以下概念,我做前端开发两三年了还是第一次听到
-
包含块、最初包含块
-
position
是根据最近祖先元素的relative进行定位的吗
? 这个答案只答对了部分标准答案是:
根据最近非static的块级祖先元素
但又有特殊情况(下面会讲解到),是不是很震惊 -
粘性布局sticky 有了解吗,这个属性一直很容易被忽略掉
几个让我错不及防的面试题
以下几个问题确实是笔者近期
,面试中遇到的问题,平时很难注意到的几个细节。拿出来给大家分享一下
relative根据什么进行定位的?
relative(我的理解)
:是根据自身原来的位置
进行偏移
relative(引用自mdn文档)
: 该关键字下,元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)。position:relative 对 table-*-group, table-row, table-column, table-cell, table-caption 元素无效。
absolute根据什么进行定位的?
absolute
:根据最近非Static定位的祖先元素
进行偏移,如果没有则根据最初包含块(又或者理解为html元素)
进行偏移
我原来一直以为absolute
是以relative
进行定位了,没想到是非Static
来看一个例子:
如果是fixed
的盒子absolute
也会根据它进行定位吗? 如果是的情况,absolute岂不是也有fixed
的效果
代码如下:
css
<div class="box1">
<div class="box2"></div>
</div>
.box1 {
position: fixed;
background: red;
width: 100px;
height: 100px;
left: 50px;
}
.box2 {
position: absolute;
background: yellow;
width: 100px;
height: 100px;
left: 50px;
}
答案是肯定的,当absolute
根据fixed
去定位,同样也有固定的
效果,因为absolute
要根据fixed
元素进行偏移
fixed根据什么定位?
fixed
:是根据当前的视图窗口(即屏幕视口(viewport))
进行定位
div的高度会受到font-size的影响吗?
答案是:不会的,因为指定了高度了,如果height
为auto
,那么就会影响
auto的情况
:
div的高度会受到line-height的影响吗?
line-height
与font-size一样,当div
设置固定的高度的时候,就是固定多大
什么是包含块?
是不是第一次听到这个概念,做前端两年了第一次听到这个词
。
那么什么是包含块呢
,引用MDN的概念
包含块就是这个元素最近的祖先块元素的内容区域,但也不是总是这样。
简单理解:通常的情况下,包含块就是元素父元素的内容区
,但是有的情况下不是。这句话可以这样子理解
那么什么情况下不是呢?
当我们使用position
的时候包含块
可能会发生改变,下面分为四种情况
-
positon值为
static、relative、sticky
的元素,包含块可能由它的最近的祖先块元素这个情况可以直接理解为,
包含块
就是当前元素的父元素内容区域(这里需要注意的是父元素必须是块元素)
例如:以下代码,显然label的高度和宽度分别是
250px
、50px
css<div class="box"> <p class="label">这是一个p标签</p> </div> .box { width: 500px; background: deepskyblue; height: 100px; } .label { width: 50%; height: 50%; background: red; }
结果也如我们所预料的。那么如果设置
box的display为inline
呢。cssbody { height: 1000px; } .box { width: 500px; background: deepskyblue; height: 100px; display: inline; } .label { width: 50%; height: 50%; background: red; }
这里因为把
box
设置为了inline
此时已经不是块元素
,所以label的宽度会基于祖先的块元素
,label
标签网上找box
不是块元素,继续找body
是块元素,那么宽度就基于body
的50%进行计算,最后得出我们的结果。 -
positon值为
absolute
,包含块就是由它的最近的 position 的值不是static
,这个上面已经解释过了 -
position值为
fixed
,在连续媒体的情况下 (continuous media) 包含块是 viewport ,在分页媒体 (paged media) 下的情况下包含块是分页区域 (page area),简单理解当前视图窗口
-
如果 position 属性是
absolute
或fixed
包含块也可能是由满足以下条件的最近父级元素的内边距区的边缘组成的:transform
或perspective
的值不是none
will-change
的值是transform
或perspective
filter
的值不是none
或will-change
的值是filter
(只在 Firefox 下生效)。contain
的值是paint
(例如:contain: paint;
)backdrop-filter
的值不是none
(例如:backdrop-filter: blur(10px);
)
这个可以理解为,如果说当前元素position:
absolute
、fixed
的时候,那么他的父元素,包含了1-5其中的任意一条
,那么这个元素就会根据这个父元素进行偏移
例如:如下结构,按理说应该是
针对box进行绝对定位
,但是因为box1设置了transform属性
,所以对根据box1
进行绝对定位
css<div class="box"> <div class="box1"> <div class="box2"></div> </div> </div> .box { width: 100%; height: 100%; position: relative; } .box1 { background: red; width: 100px; height: 100px; left: 50px; transform: rotate(0deg); padding-top: 100px; } .box2 { position: absolute; background: yellow; width: 100px; height: 100px; left: 50px; top: 0px; }
结果如下:从图中可以看到,
box2
并没有根据box
的relative
进行绝对定位,而是根据box1
粘性布局 postion:sticky
粘性布局 position: sticky
上次在面试的时候,被问到这个问题,突然蒙了,粘性布局有这个东西吗?
在面试官的提醒下我才记起来sticky
的属性,这个属性在很容易被忽略掉,对于position
,我们常用的属性主要有:relative、absolute、fixed、static
,那么接下就来认识一下sticky
。
position: sticky
粘性定位是相对定位和固定定位的结合体
,这句话比较拗口,可以这样理解,当我们设置条件不满足
的时候,它是相对定位
,当条件满足时它是固定定位
。
应用场景通常是用来制作移动端的吸顶效果
。
什么是吸顶效果?
例如:以下,当我们内容超过屏幕的时候,向下滚动,希望顶部的分类栏
,无论滚动到哪里都可以看到的,那么我们通常会采取两种解决方式
- fixed 这个可能是我们最常用
- 另外一种方式就是sticky
那么接下我们来看一下fixed方式
实现的效果:
css
.tabs {
width: 100%;
display: flex;
height: 30px;
position: fixed;
top: 40px; /* 这里的top值是顶部标题的高度 */
}
那么如果是stcky的效果呢
:
css
.tabs {
width: 100%;
display: flex;
height: 30px;
position: sticky;
top: 40px;
}
显示sticky
也可以实现一样的效果,这不是跟fixed
一样吗?
那我要使用fixed
,干嘛还要去了解sticky
?
来看看这种情况
如果是采用fixed
,那么此时我的元素可能会被覆盖掉,如果不想被覆盖,那么也只能设置fixed
属性
如果设置完,此时这个内容
就已经变成固定定位了
无论什么时候都会固定在顶部
了
效果如下
:
如果是sticky
的话显然,还是可以满足
使用sticky
的时候需要注意:
- sticky仅能在父元素中生效
- 父元素不能为
- 必须执行top、bottom、left、right其中任意一个值,sticky才会生效,不然就是相对定位
- 低版本IE不兼容