position:fixed失效探索

背景

近期遇到一个问题,当使用React Drawer 抽屉时,抽屉中position:fixed不表现为基于可视窗口定位,而是基于该抽屉进行定位,很好奇这种设定,于是基于该内容进行了一些探索。

探索过程

  1. React Drawer实现方式为transform
  2. position:fixed的祖先元素为transform时,定位容器由视口改为该祖先。
  3. 不仅仅在transform中position:fixed失效,在所有堆叠上下文(Stacking Context)均会导致position:fixed失效。【MDN理论】
  4. 并非所有堆叠上下文(Stacking Context)下position:fixed都失效,仅在:
    • transform 属性值不为 none 的元素
    • perspective 值不为 none 的元素
    • will-change 中指定了任意 CSS 属性
    • filter 不为 none
    • 设置了 transform-style: preserve-3d 的元素
  5. 不同浏览器的表现也不同,以上五种情况仅在Chrome中表现该特性

堆叠上下文(Stacking Context)

堆叠上下文(Stacking Context):堆叠上下文是 HTML 元素的三维概念,这些 HTML 元素在一条假想的相对于面向(电脑屏幕的)视窗或者网页的用户的 z 轴上延伸,HTML 元素依据其自身属性按照优先级顺序占用层叠上下文的空间。

如何创建堆叠上下文:

  • 根元素 (HTML)
  • z-index 值不为 "auto"的 绝对/相对定位,
  • 一个 z-index 值不为 "auto"的 flex 项目 (flex item),即:父元素 display: flex|inline-flex,
  • opacity 属性值小于 1 的元素(参考 the specification for opacity),
  • transform 属性值不为 "none"的元素,
  • mix-blend-mode 属性值不为 "normal"的元素,
  • filter值不为“none”的元素,
  • perspective值不为“none”的元素,
  • isolation 属性被设置为 "isolate"的元素,
  • position: fixed
  • 在 will-change 中指定了任意 CSS 属性,即便你没有直接指定这些属性的值
  • -webkit-overflow-scrolling 属性被设置 "touch"的元素

结论

Chrome中问题结论:

在Chrome(Blink内核)中,position:fixed在:

  • 祖先元素为transform 属性值不为 none 的元素
  • perspective 值不为 none 的元素
  • will-change 中指定了任意 CSS
  • filter 不为 none
  • 设置了 transform-style: preserve-3d 的元素

情况下,定位容器由视口改为该祖先。

不同浏览器position:fixed表现:

CSS Chrome Safari(Mac) FireFox
z-index 值不为 "auto"的 绝对/相对定位
一个 z-index 值不为 "auto"的 flex 项目 (flex item)
opacity 属性值小于 1 的元素
transform 属性值不为 "none"的元素 失效 失效 失效
mix-blend-mode 属性值不为 "normal"的元素
filter值不为“none”的元素 失效 失效
perspective值不为“none”的元素 失效 失效
isolation 属性被设置为 "isolate"的元素
position: fixed
在 will-change 中指定了任意 CSS 属性 失效 失效
-webkit-overflow-scrolling 属性被设置 "touch"的元素
设置了 transform-style: preserve-3d 的元素 失效 失效

position:fixed不同表现(在不同浏览器中打开) DEMO

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章