The limits of @supports

@supports may be very useful, but it can only tell you so much, especially in the case of browsers that will return true, technically supporting the feature, but having a buggy implementation. This is a case where we can often assume too much about a browser based on a reductive test that isn’t guaranteed to tell us what we think it does. PPK explains:

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

Code language: CSS

@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.

[…]

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.

Code language: CSS

@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:

Code language: CSS

@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.