Proposal: position:fixed elements should form new stacking contexts

TL;DR: position:fixed elements should establish a new stacking context.
 Web compat issue is minimal and a problem even if we do nothing due to
"mobile" browsers.

Consider the following testcase:
http://webstuff.nfshost.com/tests/fixpos.html.  On this page there are two
copies of a very similar DOM structure that is something like this:

div.container
 div.green
 div.pink
 div.fixed
  div.orange

with styles:

.container { position:absolute; }
.green { position:relative; z-index: 1; }
.pink { position:relative: z-index: 3; }
.fixed { position:fixed; }
.orange { position:relative; z-index: 2; }

and a second copy that is identical except for the addition of opacity:
0.99; to div.fixed.

In the first copy, the elements green, pink, and orange are all in the
stacking context of container and thus the displayed order is (from back to
front) green, orange, pink.  In the second, the opacity property on the
fixed div establishes a new stacking context that displays "below" the
positive z-indexed children of container and so the final displayed order
is orange, green, pink.  Try scrolling up and down a few times on the test
page to get a feel for how it behaves (div.fixed is blue on the test page
to make it easier to see).  This behavior is spec'd reasonably well in
http://www.w3.org/TR/CSS2/zindex.html and there is strong interoperability
across desktop browsers - the rendering of this simple testcase is
identical in my testing of Google Chrome, Safari, Firefox, Opera, and IE9.
 However, the situation on mobile is not so consistent.

On touch-based devices, responsiveness to touch events and in particular
scrolling is essential to providing a good user experience.  Users really
notice if the page is "behind" their finger.  As a result, browsers go to
great lengths to provide a good scrolling experience.  A big part of this
is decomposing a web page into portions that move when the page scrolls and
portions that do not, then moving these portions relative to each other on
a dedicated thread.  Stacking contexts render atomically so a page can
always be divided into the stuff "behind" the stacking context, the
stacking context's content, and the stuff "above" the stacking context
(with the minor wrinkle that the background of an element appears "below"
its negative z-index children).  Elements that are position:fixed but do
not form a stacking context are difficult - the browser would like to
separate out the parts that do not scroll with the page, but that may
include elements that participate in z-index lists of stacking contexts
outside the position:fixed subtree.  It would be at least in theory
possible to detangle this situation, but the complexity is daunting and as
far as I know nobody has attempted this yet.

As a result, in MobileSafari on iOS 5+ and the most recent Android browser
position:fixed elements establish a new stacking context.  As a result, the
two test cases in http://webstuff.nfshost.com/tests/fixpos.html render
identically to each other.  Firefox on Android appears to render the same
way as desktop Firefox, and scrolling is quite janky.  Chrome on Android
Beta does something more complicated on this page that results in a
desktop-like rendering, but I consider that a bug (hey, it's Beta) and
intend to bring its behavior in line with MobileSafari.  I do not have
access to any Windows Phone devices, but I'm curious what its browser does.

This was an incompatible change in rendering for the browsers that have
adopted the non-desktop behavior.  Our experience in the Google-produced
browsers on Android is that there were a very small number of compatibility
issues noticed (less than 5, including some unreleased Google properties
not yet part of the public web).  Anecdotally I understand that Apple ran
in to exactly one broken website when they made this change for the iOS 5
browser.  There are some other situations that render differently besides
the test case I've constructed, but they all fall in to the bucket of
things that I consider "weird" no matter how they are rendered.  We've also
received a few bug reports on the desktop Chrome browser where authors
believed that position:fixed elements were supposed to form a stacking
context and were surprised that adding a transform changed the z-ordering
of the page.

This is a fairly niche area, but I think the current situation is
untenable.  The same implementation concerns that apply to the current set
of mobile browsers apply to the next generation of "desktop" browsers -
consider things like Win8 devices with touchscreens, larger tablets with
external keyboards, etc.  New content that is developed for and tested on
browsers like MobileSafari may render differently on desktop browsers.  I
think this divergence in behavior is bad for the web platform - even within
the "same" browser there are different behaviors on different devices, and
as an implementor I'll have to pick somewhat arbitrarily what a given
webpage gets.

I think the best option is to specify that position:fixed elements always
establish a new stacking context and have all browsers change to this
behavior as quickly as possible.  Based on Apple's and our experiences on
mobile browsers, the web compatibility impact of this change should be
quite minimal.  In fact, I expect that this change in behavior will be
considered a bug fix by at least some authors as the currently-specified
behavior is quite strange in most cases.

The next best option, and one I consider fairly difficult, would be to say
that we really do want the currently-specified behavior everywhere and
modify the current round of mobile browsers to do this.  This would be
quite difficult (I'm not sure if it's possible) and given the adoption of
the browsers with the currently divergent behavior won't really help all
that much with the web compatibility issue.

The absolute worst option would be to do nothing or to put this proposal in
some procedural limbo.  Mobile browsers and pages designed for mobile
browsers are only going to grow in popularity so the divergence in behavior
is going to grow more prevalent over time.

I am particularly interested in what non-WebKit browser vendors feel about
this issue.

- James

Received on Monday, 14 May 2012 02:31:34 UTC