問題:fixed元素被另一個fixed元素包含的時候在chrome下fixed子元素的定位會受到父元素的影響。
demo(http://jsbin.com/qumah/1):
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JS Bin</title> <style> .fixed { position: fixed; left:0; top:20px; width:200px; height:200px; background:#fee; } .fixed-child { width:150px; height:150px; background: #fcc; top:40px; right: 20px; left: auto; z-index: 100; } .absolute { position: absolute; right: 20px; width:100px; height:100px; background:#f11; } </style> </head> <body> <div class="fixed">fixed position<div class="fixed fixed-child">fixed child position</div></div> <div class="absolute">absolute position</div> </body> </html>
IE(IE8-IE11效果一致,IE7沒有測試,IE6不支持fixed元素)下效果:
chrome下效果:
firefox下效果:
Safari下效果:
解釋:層疊關系是受層疊上下文影響的。文檔中的層疊上下文由滿足以下任意一個條件的元素形成:
- 根元素 (HTML),
- 絕對(absolute)定位或相對(relative)定位且z-index值不為"auto",
- z-index不為“auto”的flex列表,
- 元素的
opacity
屬性值小於1. (參考 the specification for opacity), transform屬性值不為“none”,
mix-blend-mode屬性值不為“normal”,
isolation屬性值為“isolate”,
- 在mobile WebKit 和 Chrome 22+內核的瀏覽器中,
position: fixed
總是創建一個新的層疊上下文, 即使z-index的值是"auto" (See this post), - will-change屬性值為上述屬性名,即使屬性值不直接為上述屬性名(例如:all)--參見:https://dev.opera.com/articles/css-will-change-property/
參考來源:The stacking context - MDN
每個層疊上下文都有如下的層疊級別組成(顯示順序從后到前):
- 父級層疊上下文的背景和邊框;
- 層疊級別為負值的層疊上下文(越小越在下);
- 非行內、非定位的子元素;
- 非定位的浮動子元素和它們的內容;
- 行內非定位子元素;
- 'z-index:auto' 的定位子元素,和任何 'z-index:0' 的層級上下文;
- 層疊級別為正值的層疊上下文(越大越在上)。
參考來源:RM8015: IE6 IE7 IE8(Q) 中定位元素 'z-index' 為默認值在某些情況下會產生新的層疊上下文
結論:在chrome22+的瀏覽器中,position為fixed總是會創建新的重疊上下文,所以子fixed元素在此時會以父fixed元素為層疊上下文,子元素的層疊關系會受到父元素的影響。而在非chrome瀏覽器下子fixed元素並不會創建新的層疊上下文,fixed元素的層疊上下文為最近的層疊上下文。
因此,我們應該盡量避免出現fixed元素相互嵌套的問題。如果必須有嵌套的情況,建議修改fixed父元素的z-index值來修正在chrome下fixed子元素的層疊問題。
題外話:
對於opacity小於1的元素也會產生層疊上下文的問題,可能很多人都不知道。但是規范里面是明文規定的:
Since an element with opacity less than 1 is composited from a single offscreen image, content outside of it cannot be layered in z-order between pieces of content inside of it. For the same reason, implementations must create a new stacking context for any element with opacity less than 1. If an element with opacity less than 1 is not positioned, implementations must paint the layer it creates, within its parent stacking context, at the same stacking order that would be used if it were a positioned element with ‘
z-index: 0
’ and ‘opacity: 1
’. If an element with opacity less than 1 is positioned, the ‘z-index
’ property applies as described in [CSS21], except that ‘auto
’ is treated as ‘0
’ since a new stacking context is always created. See section 9.9 andAppendix E of [CSS21] for more information on stacking contexts. The rules in this paragraph do not apply to SVG elements, since SVG has its own rendering model ([SVG11], Chapter 3). ---摘自《CSS Color Module Level 3》
簡單來說:
- opacity值小於1的元素會創建新的層疊上下文
- opacity值小於1的元素的層疊級別相當於z-index:0的定位元素。此時設置z-index會失效,除非該元素同時為定位元素
- opacity值小於1的元素如果同時為定位元素時,則該元素將同時具有定位元素和opacity小於1元素的特性之和。換句話說,就是z-index等於“auto”時會被當成z-index等於“0”時創建新的層疊上下文
參考文章:
https://developer.mozilla.org/zh-CN/docs/Web/CSS/Understanding_z-index/The_stacking_context
http://www.w3.org/TR/CSS21/visuren.html#z-index
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index