Category Archives: HTML

Choosing between min-width and max-width media queries

I’m often asked a variation of the following question:

Should I use min-width or max-width media queries?

The obvious answer is, of course, “yes”. But you know what they’re asking: which of the two is better?

Those for whom responsive design has become second nature might find it an odd question, and will know that the answer is, “it depends”. But having seen lots of responsive design implementations, it’s clear to me that many designers and developers aren’t quite sure. And I’m happy to share my own opinion of what “it depends” means regarding this particular question.

Desktop first and max-width

There’s a decent number of designers/developers that still think of “the desktop” as their primary design manifestation, with other (generally smaller) sizes as secondary; often these appear as afterthoughts, since there can be significant visual clues as to the amount of effort that has gone into these other screen sizes when compared to their desktop counterparts. Often, when one examines the CSS of these sites, `max-width` is the media feature of choice.

This makes sense. If a design is built desktop-first, then all the CSS for the desktop-ish version of the design has been written, and must be overridden with more CSS for any other breakpoints. If a given desktop-ish width is our baseline and we are unwilling or unable to refactor our CSS, then it seems logical to override what is now our base CSS for all viewport widths with those we only want to apply to smaller widths.

This can lead to a situation I’ve often joked about: writing styles only to undo them later. This is an example I often use (assume .related takes the form of a sidebar):


.content {
  width: 60%;
}

.related {
  width: 40%;
}

@media screen and (max-width: 37.4em) {
  .content,
  .related {
    width: 100%;
  }
}

The above example omits a lot, but I’m sure you get the idea. This approach, when used over a bunch of components, can greatly increase the amount of CSS needed to complete the project. But the main problem is how illogical it is, because when embracing the fact the block-level elements are 100% of their parent by default, then the following makes much more sense:


@media screen and (min-width: 37.5em) {
  .content {
    width: 60%;
  }

  .related {
    width: 40%;
  }
}

Here, we’re making use of the default state of block-level elements, and overriding them when they need to change from the default. Again, it might seem clear to some readers, but it doesn’t take looking at the source of many websites before you understand why I’m clarifying it here.

Using max-width against your better judgement

There are a couple of reasons why, even when you know better, you might deliberately choose to use an approach similar to max-width approach above:

  1. You’re a developer and you received desktop-only, desktop-first, or other-sizes-as-an-afterthought comps from the designer. How can you know? If you’ve only designed or received designs for desktop-ish widths, this is what you’re dealing with. If you’ve got nice detailed desktop-ish designs with a few “mobile” or “tablet” examples thrown in there, this is what you’re dealing with. In these cases, may the max-width be with you, unless you have a budget and/or schedule that allows you to refactor during development.
  2. You’re making an existing website responsive, and the existing CSS is design baggage you’ve inherited and cannot change, for whatever reason.
  3. You’re compensating for the fact that we don’t currently have element queries, and you’re handling this with CSS instead of using a JavaScript polyfill for a non-existent spec.

So, what’s the best to use?

Here’s my clarification of “it depends” for this particular question. And remember it’s just my own opinion based on my own experiences: look at default display of a given element. If you have to override this default for smaller screens, use max-width. If the default is usable on small screens, use min-width, and only when the element needs to deviate from the default. And of course, I recommend letting the content determine where that happens.

A good example of using max-width to override an element’s default display so that it works better on smaller screens is when using tables. Imagine a table that contains too much content to display in its default form on small screens. One approach might be:


@media only screen and (max-width: 30em) {
  .big-table tr,
  .big-table td {
    display: block;
  }
}

This turns each row (and cell) into a block on narrow screens. The table can become quite long vertically and more styling is usually required, but it’s often better than the back-and-forth horizontal scrolling that would otherwise be required to read the content.

In this case, it makes all the sense in the world to leave the table in default form, except for in browsers that understand the media query and where the screen is no larger than, in this case, 30em.

Other elements (I would venture to say most other elements) that have defaults that work fine on smaller screens, only need changing when necessary on larger screens; using min-width is then a solid choice.

In short: let element defaults help determine which media feature to use in your media queries.

Thanks to Brad Frost for reviewing this. He also has a post with related topics.

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.

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.