The limits of @supports

Yesterday I talked about background-attachment and its confusing mobile compatibility patterns. Today I’ll talk about the ulterior motive I had for this retest: Conditional Rules support, which basically amounts to @supports.

I’m working on an automated issue-raising system for Sevenval, and part of the purpose is figuring out if CSS is going to work in all, most, some, or no browsers by collating data from caniuse, StatCounter, and recommendations from me. This requires me to do quite a few tests and retests in order to come to decent recommendations (yay!).

I decided to start with Backgrounds and Borders because it’s on Sevenval’s list, and because I thought it would be a good test case for @supports, which is also on the list.

I already knew that background-attachment works pretty badly on mobile browsers, and wondered if that fact is reflected in @supports. Before determining that I needed to retest background-attachment itself.

Now that I’ve done that I can draw my conclusions: no, background-attachment issues are not reflected in @supports. That’s understandable, but it still limits the usefulness of @supports. I suspect that this won’t come as a huge surprise to most of my readers, but now we have solid evidence to base this opinion on.

background-attachment

If a mobile browser doesn’t support background-attachment: fixed in practice, what happens when you do this?

@supports(background-attachment: fixed) {
	// CSS
}

Does it return false because the mobile browser doesn’t support it? Or does it return true because its desktop version supports it? With my background-attachment test data in hand I could now answer this question.

All mobile browsers return true for both fixed and local. Only 3 out of 23 browsers speak the truth here. See the test case and the inevitable table for more details.

We need to make some distinctions. If Chrome 51, with its bug, says it supports background-attachment: local I tend to agree with it. It’s clear that the engineers intended Chrome to support local. Sure, it has a bug, and it would be great if @supports also keeps track of bugs, but that’s too much to ask.

It becomes trickier when we take a look at fixed. Chrome on Android just doesn’t support it (with one partial exception: the Ubuntu 35. Don’t ask me why.) Still, @supports claims that it does. A case can be made that this is a bug.

Also, Chrome 34 and below do not support fixed or local, but @supports claims support for both. This is a very similar case.

Still, the crucial bit of information is that @supports returns true if the browser’s CSS parser accepts the value as valid and legal. Apparently Chrome on Android’s CSS parser does that for background-attachment: fixed, since the Chrome on Android engineers copied the desktop CSS parser and did not change it to reject values they decided not to support.

I can see why they did so. Still, it raises questions about the usefulness of @supports for detailed queries such as this one.

transition-property: nonsense

But wait, we’re not done yet. I also tested the transition-property declaration and found that some browsers claim to support transition-property: nonsense. Try the test case if you don’t believe me.

Now at first sight this seems weird. Why would a browser claim to support this? I was confused.

Then Tab Atkins provided an explanation. It turns out that CSS parsers allow any value in the specific case of transition-property in order to keep the door open for future CSS declarations.

Suppose a future browser would actually support the nonsense declaration, and you’d use something like transition-property: width,nonsense. Older browsers, who don’t support nonsense, should still be able to transition width. That’s why they accept (and ignore) the nonsense — and since the CSS parser does so, @supports also does so.

So this is weird but understandable.

The limits of @support

Still, although these two oddities can be explained, I’m forced to wonder about the limits of @supports. What’s clear from these tests is that @supports is only useful when you’re detecting entire CSS modules such as flexbox. So the check below makes sense.

@supports (display: flex) {
	// flexbox layout
}

@supports not(display: flex) {
	// float layout
}

This example is likely safe. If a browser decides to support flexbox, display: flex is the first item on the agenda, so detecting it makes perfect sense. (It’s theoretically possible, though, that a browser fakes display: flex support in order to end up on the right side of some support detects. But as far as I know this is not the case today.)

On the other hand, if a browser has flaky support for, I don’t know, justify-content, a more precise check like this may or may not work, depending on how the CSS parser is written:

@supports (justify-content: space-around) {
	// may or may not fire correctly in case
	// of a browser bug
}

So this example is unsafe. Don’t use @supports for such detailed compatibility questions.

What to do?

Although we now understand why @supports is only useful on a high level, the question remains whether we should do anything about it, and, if so, what.

The only possibly useful idea I’ve had so far is adding a quick test page to all browsers that is executed when that browser starts up. For instance, in the case of background-attachment: local it could contain a test to see if it’s actually supported right here right now in this particular browser, and store the results in some sort of internal table that informs @supports (or its successor).

This thought comes naturally to me right now because I’ve written a script for Sevenval that runs a few detections like this, although they’re performed when a user enters a site, and not when she starts up the browser. The principle is pretty much the same, though.

I have no clue how much work it would be to produce them and keep them up to date. Still, Tab Atkins thought it was an interesting idea, so I’m assuming it’s not technically impossible.

Also, these pages would have to have some ways of emulating user behaviour that should not find their way into regular web pages. I’m especially thinking of automatic zooming. Some tests need zoom, but we should definitely not add script-based zooming to real web pages or advertisers will use it on their content within about 30 seconds.

Even if the initial test pages turn out not to be a good idea it could be we find better ways of measuring more detailed support levels. But should we? Or is @supports as it works now good enough?

This is the blog of Peter-Paul Koch, mobile platform strategist, consultant, and trainer. You can also follow him on Twitter.
Atom RSS

I’m around at the following conferences:

(Data from Lanyrd)

Categories:

Monthlies: