浅析父元素设置transform时子元素position:fixed失效的问题
今天遇到一个现象,设置了 position:fixed; 但是发现其行为却随文档流滚动,而不是相对于 viewport 固定在某处,所以查了一下,发现是个知识点。
一、现象背景
我理解的fixed元素是这样的:摘自 CSS布局基础
固定定位与absolute定位类型类似,但它的相对移动的坐标是视图(屏幕内的网页窗口)本身。
由于视图本身是固定的,它不会随浏览器窗口的滚动条滚动而变化,除非你在屏幕中移动浏览器窗口的屏幕位置,或改变浏览器窗口的显示大小,因此固定定位的元素会始终位于浏览器窗口内视图的某个位置,不会受文档流动影响,这与background-attachment:fixed;属性功能相同。
但是在《CSS为什么这么难学》这篇文章中,作者提到了一个“黑魔法”:如何让fixed元素不再以viewport为定位参考对象,而是以父容器为参考对象。这下我算是get到了一个技能。
为什么fixed元素的父元素加了transform就会以父元素为参考对象?
详细的 demo 如下:
<div class='parent'>
parent
<div class="txt-box">text</div>
<div class='fixed'>fixed</div>
</div>
.parent{
width: 200px;
height: 300px;
background: yellow;
transform: scale(1);
overflow: auto;
}
.fixed {
position: fixed;
width: 100%;
left: 0;
top: 0;
background: red;
}
.txt-box{
height: 1000px;
}
查看这个demo发现,我们在父元素设置了transform: scale(1);
这个属性,然后其子元素便以父元素为参考对象了,而且不再固定在某个地方,而是会随着文档流的流动而流动。
二、问题解析
这是为什么呢?答案在设置了transform
属性的元素上,在W3c文档上transform属性,文档的定义翻译如下:
1、
对于布局受CSS盒子模型控制的元素,transform属性不会影响transformed元素周围的内容流。
但是,溢出区域的范围将会考虑上transform元素。这种行为类似于元素通过相对定位发生偏移时的情况。
因此,如果overflow属性的值是`scroll`或`auto`的,滚动条将显示为需要看到在可见区域外转换的内容。
2、
对于布局受CSS盒子模型控制的元素,除了配置为`none`之外,其他的`transform`属性值都会创建堆栈上下文。
绘制的实现必须在其父栈上下文中它所创建的层中,如果它是带有“z-index: 0”的定位元素,则使用相同的堆叠顺序。
如果一个带有`transform`的元素还配置了`position`属性,那么“z-index”属性将按照[CSS2](https://www.w3.org/TR/css-transforms-1/#biblio-css2)描述的被应用,除非“auto”被视为“0”,因为会创建新的堆栈上下文。
3、
对于布局受CSS盒子模型控制的元素,除了配置为`none`之外,其他的`transform`属性值都将导致元素成为一个包含块,而其固定定位的后代元素都是以此object作为他们的包含块。
4、
根元素的[Fixed Backgrounds](https://www.w3.org/TR/css3-background/#fixed0)会受到该元素上配置的transform属性的影响。
对于受transform影响的所有其他元素(例如,对它们应用transform属性,或者对它们的任何祖先元素应用transform属性), `background-attachment`属性值为`fixed`的元素会被当做它好像有配置`scroll`属性一样。其他`background-attachment`的计算值不受影响。
在这段介绍中我们发现transform
会对fixed
属性造成影响,具体表现可以看上面的那个demo。
简单来说就是:应用了transform属性的元素会导致该元素形成一个新的包含块,然后其后代元素如果有fixed定位的属性,那么其元素将会以该父元素作为包含块,从而有了之前我们看到的现象。
1、在 w3c 中对 position: fixed 的[定义](https://www.w3.org/TR/css-position/#fixed-pos)如下:
Fixed positioning is similar to absolute positioning.
The only difference is that for a fixed positioned box,
the containing block is established by the viewport.
大概意思就是,fixed 元素的块级格式上下文 Block Formatting Context(BFC) 由 viewport 创建,也就是fixed 元素的 BFC 包含在根元素的 BFC 里。那以上 demo 的表现就说不过去了。为什么呢?谷歌一下,原来是父元素的 transform 在捣乱。
再看看 w3c 对 transform 的[定义]():
For elements whose layout is governed by the CSS box model, any value other than none
for
the transform property also causes the element to establish a containing block
for
all descendants.
Its padding box will be used to layout
for
all of its absolute-position descendants, fixed-position descendants, and descendant fixed background attachments.
大概意思就是,transform 属性使元素创建了新的 BFC,所有的子元素都被包含在这个新的 BFC 内。那么设置了 position: fixed 的子元素 BFC 被包含在了 transform 元素的 BFC 里。
BFC 和定位有什么关系呢,继续翻 w3c,有段关于 BFC 的[定义](https://www.w3.org/TR/css-position/#def-cb):
The position and size of an element’s box(es) are sometimes computed relative to a certain rectangle, called the containing block of the element.
元素的位置和尺寸是相对于一个确定的 BFC 计算的。所以 demo 展示的 fixed 元素位置是根据它所在的 BFC 计算的。
除了上述说的,我还发现了另外两个特征:
1、fixed元素不在固定在某个位置,失去了fixed元素特有的性质
2、fixed元素不会脱离文档流,但是top等属性依然可用。可以看例子中的top属性,配置了top:10px;整个文档流都往下走10px。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
2018-07-06 绝对定位常见误区:position:absolute相对于谁定位、及当溢出时怎么隐藏
2018-07-06 vue嵌套路由总结
2018-07-06 Springboot读取自定义配置文件的几种方法