A different approach to qualifying CSS position: fixed

April 2020 note: Hi! Just a quick note to say that this post is pretty old, and might contain outdated advice or links. We're keeping it online, but recommend that you check newer posts to see if there's a better approach.

CSS fixed-positioning varies widely in browser support, and it’s quite difficult to test. Unfortunately, unlike many CSS features, when fixed-positioning fails, page content can end up overlapping in ways that inhibits accessibility—never a good thing. Still, fixed positioning is a very desirable feature, particularly when designing for mobile devices, so we’re continually exploring better and more practical ways to approach it. Today we’re making public a new approach, Fixed-fixed, for qualifying fixed-positioning that builds on what we’ve learned.

How it works, in brief

Permalink to 'How it works, in brief'

In our extensive testing for jQuery Mobile and our client work, we discovered a number of complexities in testing fixed-positioning:

First, there are a few known browsers that report false results when running the included feature test (Some Android 2.x builds, and some older versions of Firefox Mobile and Opera Mini and Mobile for example, have reported false positives in our testing). A false negative is generally safer than a false positive, and we would never want to opt a non-supporting browser into this feature. These browser versions are no longer in development, but they are popular, so we know we need to find a solution that will make sure we don’t deliver a broken experience.

Second, we noted an up-front test requires programmatically scrolling the browser window during page load, which we found could sometimes interfere with other scripts running on the page, and generally make for a less-smooth loading sequence.

For these reasons, our approach differs from a typical CSS feature test. Rather than testing immediately, the script waits for the user to scroll, as a physical scroll is required for checking if fixed-positioned elements retain their position properly. Prior to scroll, the script assumes fixed positioning works, adding a class of fixed-supported to the HTML element that can be used to qualify any position:fixed CSS rules. After the scroll, if fixed positioning is deemed unsupported through our feature test, the class is removed, allowing any fixed-positioned elements to safely degrade to a fallback layout that can be specified through rules that do not use that qualifier selector.

A TIP OF THE HAT: The idea behind the feature test portion of this approach was inspired by Kangax’s Position Fixed Test.


Permalink to 'Usage'

To use this technique, just include the JavaScript from the project repo and qualify any position:fixed usage in your stylesheet with a .fixed-supported parent class selector, like so:

.fixed-supported header { position: fixed; }

That class will be present on the HTML element in CSS fixed-supporting browsers. You can apply an initial/degraded layout in browsers that don’t support fixed positioning properly by writing selectors that do not use the .fixed-supported selector.

For an example, you can view and test the project example page .

Hey, help us out!

Permalink to 'Hey, help us out!'

We’re releasing this idea early-on in development because we’re looking for feedback on the concept as well as the code, and we’re also very eager to get some additional testing contributions. There may well be errors to address, and edge cases we’ve yet to find. Please test it out, let us know if you have ideas for improvements, and file issues in the tracker if you find any. With any luck, we hope this will grow into a reliable tool for use in our future projects, and yours.

All blog posts