Category Archives: Web Standards

Nesting media queries

In my presentation at Mobilism 2011 (slides) I talked about using logical and and or in media queries. Most of us use and, but I found that not as many people knew about the logical or, which in the case of media queries is the comma. In comma-separated media queries, like this one:

@media screen and (min-resolution: 300dpi), screen and (-webkit-min-device-pixel-ratio: 2) { }

the comma is an or. The first query will be evaluated. If not true, the second one will be evaluated. If one of these is true, the styles will be applied.

Another thing I mentioned (which is on the video but unfortunately not in the slides) is that it is possible to nest media queries. Since we can use media queries in the link element as well as in a CSS file itself, I found that doing both allows you some simple nesting. Whenever you want to apply styles based on two conditions which cannot be fulfilled within a single query, this could be useful.

I couldn’t think of any other use cases at the time other than my typical use case of using min-width queries and having specific page components which need to change at a certain max-width. That works just fine. But then just yesterday Ben Callahan provided us all a new use case: working with logical not.

As I discussed at Mobilism, it is possible to create a media query like so:

@media not screen and (min-width: 600px) { }

This might look like it means “if it’s not a screen but it is at least 600px wide, then apply these styles.” In fact, the not negates the entire query. This is according to spec. So this query actually says, “if it’s not a screen which is at least 600px wide, apply these styles.” That’s a huge difference.

Ben sent an article which he and Matt Griffin wrote in which they describe this problem, as in one key example they wanted to target all media types which are not print. You can’t do:

@media not print and (min-width: 60em)

and expect the min-width to still apply, since the not negates the entire query. So, glad with another possible use case for nesting media queries, I suggested the idea to Ben, who promptly added some nesting tests to the slew of media query tests he’d done for the article. As far as I can tell, Ben’s tests work as expected. By linking to a style sheet like so:

<link … media="not print">

and then in that style sheet creating another query like so:

@media all and (min-width: 60em)

you have created a nice little nested conditional, saying, “as long as the media type is not print, if the minimum width is 60em, apply these styles”. Of course, the only styles that will be applied are those in that particular query block in your style sheet.

While I could confirm Ben’s tests worked in a couple of modern browsers (and an actual printer, of course), it obviously will not work in any browser which doesn’t support the not keyword. And as always, I’m sure there are several other caveats to be found. Nevertheless, it’s a useful trick to know.

Hats off to Ben and Matt for their explorations. Great stuff!

NOTE (2012-10-17): As Bruce Lawson pointed out to me, browsers will most likely support nesting of media blocks in the future.

Multi-column confusion

tl;dr: Be careful when using multi-column layout.

Today I was finishing up a small portion of a project which involves generating PDFs with a multi-column layout from web content. Since we’re using the Prince formatter for the PDFs, there are no worries there, as Prince is one of the finest rendering engines out there, especially for this kind of thing.

But since I also created a live preview so the client can see their text in the intended layout while typing, I tested in some major desktop browsers. I was in in for a big surprise.

For anyone familiar with CSS Multi-column layout, the spec says basically—if I understand it correctly—that if no height is specified on the element containing the text columns, then the text should be distributed amongst these columns so that they are of (roughly) equal height. The value for this behavior is balance. If a height is specified, then the browser should use the value of the column-fill property, if it has been specified. If there is no column-fill property, then the browser should still balance the columns. Go ahead and read that again. I’ll wait.

I had set a height on my container. So I was confused about the fact that Chrome/Safari and Firefox were applying auto where they should have been applying balance.

A column-fill value of auto means that the browser should fill the columns in sequence, starting with the first column and filling it, then column two, etc. until there is no remaining text. The browser can do this because it knows the height of the column container. So the spec makes perfect sense, but I was scratching my head at this point. I had specified a height, but not column-fill. Every browser should have used balance, but only Opera did.

Well, I’m thinking it’s me, then I’m thinking it’s not me, so I tweet about it. Fellow CSS layout fan (and author of The Book of CSS3) Peter Gasston and I started chatting about it and tonight we jumped on GTalk and starting testing. Turns out the answer is quite simple: Peter starts off by telling me how Firefox and the Webkit browsers haven’t fully implemented the spec yet. I should have known that, but I didn’t, like an idiot. And it’s logical because the spec is obviously not finished yet.

But even after knowing that, it’s still pretty confusing, because which behavior conforms to the spec right now and which doesn’t? What’s supposed to happen when? I mapped my tests out in the form of two small comparison tables. They might look confusing, but they really aren’t. It’s pretty easy to figure out what you’d need to do to get either balance or auto. Even when the spec is implemented, it’s still useful to know under what conditions each of these values will be acted upon.

Multi-column column-fill defaults, when column-fill is not explicitly specified.
  Opera Firefox Chrome/Safari
No explicit height on container balance balance balance
Explicit height on container balance auto * auto *
Multi-column column-fill behavior when column-fill property is explicitly specified.
  Opera Firefox Chrome/Safari
column-fill: balance;
(container height specified)
balance auto * auto *
column-fill: balance;
(No container height specified)
balance balance balance
column-fill: auto;
(container height specified)
auto auto auto
column-fill: auto;
(No container height specified)
balance balance balance

As far as Peter and I can tell, the only behavior which does not conform to the spec is marked in red and with an asterisk. The rest seems (to me) to conform to the spec.

Again, I’ve run into this kind of thing because I’m knowingly using a spec which is not fully implemented. If you do the same, please realize that things can go wrong, and that you’re basically working with a work-in-progress. It might change, and you might have to change your code in the future. If you do use Multi-column now, please use it as a progressive enhancement. And don’t forget to use all the necessary vendor prefixes so that we all may live in peace and harmony.

As always, have fun!

New HTML5 beer logo

Update: The W3C have updated their stance on this subject.

Finally, the moment we’ve all been waiting for: drinking beer is now part of HTML5! This puts drinking beer just ahead of cooking, and right alongside CSS3 as a “technology class” of HTML5.

HTML5 beer logo

Obviously, this means a lot for your expense reports while traveling, as the blob that is HTML5 slowly assimilates all of your activities, allowing you to claim you were working on web stuff the whole time.

To celebrate this milestone in web development, we here at the Haystack decided to step up and use Creative Commons to its full extent by giving beer the logo it deserves. The t-shirts are in the works, so stay tuned!

Background information

The HTML5 logo (excluding the beer) is licensed by the W3C under a CC-BY license.