What the hell’s up with @media not?

Currently I’m working on a media query test suite, and I’ve run into one of those weird things: the proper syntax of @media not.

Note that I’m only interested in the @media syntax. I cannot use the rest because I can’t fit it into my test suite.

I’m currently working on a test for binary media queries such as touch, script, grid, and a few others. These are just meant to tell you if the browser is in a touch environment, supports JavaScript, or is on a terminal-type screen. Now touch and script don’t work (yet), but grid does.

Test it here: the grid media query is supported but returns false in all browsers. That’s because normal browsers are not on a terminal-type grid screen. This is all as it should be.

I’m using these media queries

@media (grid: 0) {styles}
@media (grid: 1) {styles}

They work in all browsers: all of them properly report that they support the grid media query, and that its value is 0.

Still, I’d prefer to do this:

@media (grid) {styles}
@media not (grid) {styles}

Tough luck: the second media query does not work. At all. In any browser whatsoever.




But wait, it gets worse. What I eventually want to do is use this media query to test bare support for grid:

@media (grid),not (grid) {styles}

The styles would be applied if grid is either true or false; if grid is supported, in other words.

This does not work in IE10, Firefox, Safari, and Opera. It works, however, in Chrome. You know you’re in for a world of pain if the WebKit-based browsers disagree with each other. You know it’s going to be even worse when they disagree on desktop.

Here is a test page where you can see for yourself. I also tried (not grid) instead of not (grid), but that doesn’t work, either.

What the HELL is going on? What is the proper syntax of @media not (grid)? Why is the last example supported by Chrome, but not any of the other browsers?


Update: OK, some light in the darkness. The reason that Chrome supports the last test is that it runs WebKit 537, contrary to Safari, which runs 536. 537 is thus slightly better than 536, but still not nearly good enough.

Second update: It was the brackets. @media not (grid) does not work; @media not grid does.

Final update: A test page for all these complicated differences.

This is the blog of Peter-Paul Koch, web developer, consultant, and trainer. You can also follow him on Twitter or Mastodon.
Atom RSS

If you like this blog, why not donate a little bit of money to help me pay my bills?



Comments are closed.

1 Posted by Tom Mollerus on 15 November 2012 | Permalink

I've done a little experimenting, and found that if you remove the parentheses around "(grid)" that the CSS works:

@media (grid) {p#id1 {display: block} p#id2 {display: none;}}
@media not grid {p#id3 {display: block} p#id4 {display: none;}}
@media grid, not grid {p#id5 {display: block} p#id6 {display: none;}}

2 Posted by Eric A. Meyer on 15 November 2012 | Permalink

That’s wrong, though, isn’t it? The examples shown in http://www.w3.org/tr/css3-mediaqueries/#css(div.example%3Anth-child(43)) and later seem like the parentheses are expected, and I think the grammar requires them (though I admit my grammar-reading skills have gotten rusty).

3 Posted by ppk on 15 November 2012 | Permalink

At the moment I'm sorely tempted to ignore the spec altogether because it clearly doesn't describe what's actually happening. Note that it does *not* contain an example of @media not, just of links with not.

And in WebKit 537 the following media query works:

@media min-width: 800px {}

Note: no brackets. This is a change from 536 to 537. Ask the WebKit people.

4 Posted by Tom Mollerus on 15 November 2012 | Permalink

@Eric, you're correct that the parentheses are required, at least as mentioned in the CSS media query recommendation from 2007 (http://www.w3.org/TR/2007/CR-css3-mediaqueries-20070606/). I don't see any such mention in the most recent recommendation, which is an unfortunate omission.

However, removing the parens seems to be a workable hack for the use of the "grid" query.

5 Posted by Simon Sapin on 15 November 2012 | Permalink

For some obscure reason, `not` is only allowed in the grammar with a media type:


So the "correct" syntax is `@media not all and (grid)`. Works in current stables of Firefox, Chromium, and Opera:


We (CSSWG) are aware of this. I hope we can fix it in MQ4 and allow `not (grid)`. Discussion starts here:


6 Posted by boris on 15 November 2012 | Permalink

The spec requires that "not" be followed by a media type, not just a media query. So "not all and (grid)" is valid (as are "not screen and (grid)" and "not print and (grid)", but "not (grid)" is not valid syntax. See http://dev.w3.org/csswg/css3-mediaqueries/#syntax

"not grid" is a valid media query that will never match, because there is no "grid" medium. It has nothing to do with the "grid" query, unfortunately; it's just like "not screen", "not projection" and the like.

There seems to be general agreement that this part of the spec is silly, so there's a good chance it will change to allow "not (grid)" and browsers will align with the new spec.

7 Posted by Simon Sapin on 15 November 2012 | Permalink

Also, removing the brackets makes a single keyword parse as a media type. `@media not grid` is true because the media type is screen, not grid. `@media not color` is also true, while my screen does support colors.

As to `@media min-width: 800px`, it’s only true in WebKit (that I could test) and that’s a parsing bug. It’s true whatever the value (in Chromium 23). Try `@media min-width: 80px` and `@media min-width: 8000px`.

8 Posted by Kenneth Christiansen on 15 November 2012 | Permalink

@media not (grid) {styles} is not allowed per grammar and thus always false.

There is discussion on www-style to change this, but we don't know how widespread the current use it, thus it might be unsafe to change.

You can write @media not all and (grid) {styles} instead.

9 Posted by Eric A. Meyer on 16 November 2012 | Permalink

Ah, I see, I did miss something reading the grammar. Thanks! I need to start doing spec calisthenics to get back in shape.