Category Archives: Mobile

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) {
  .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.

Another approach to responsive scrollable tables

A few days ago, Roger Johansson posted his approach to creating responsive scrollable tables. As as is the case with most of what Roger publishes, I like the approach.

I thought I’d share something similar I used on a client project I did earlier this year; an (imperfect) approach that is practically the same as Roger’s, but slightly different in how I’m dealing with shadows as a visual clue about the “scrollability” of the table.

Roger creates a shadow along the rightmost edge of a container holding the table. This serves as a visual clue that the table can be horizontally scrolled. The shadow remains on the right side of the table at all times.

Thinking about requirements

While working on the client project, my thinking was along those same lines. I wanted any table, whether narrow or wide, to be supported, so I just wanted normal table markup, and content authors should not have to worry about doing anything special; just create a normal table. The CMS would automatically put every table into a container with overflow scrolling enabled, as Roger does.

This would be enough for practical purposes, although if I did this again, I would follow Roger’s advice and add some CSS to make the a scrollbar immediately visible in iOS Safari and Android browser (mine wasn’t).

Making shadows even more useful

What I wanted (which differs from Roger’s demo) was to have the visual clue of a shadow, but to also have the shadow indicate which direction contains hidden table content. This means that when you start out, all the content of the table is hidden to the right, so the rightmost side has a shadow indicating that. As you scroll, your table content scrolls to the left. When that disappears behind the leftmost side, a shadow should appear there as well. And finally, the shadow should disappear when you can’t scroll further on a given side.

See the demo to see exactly what I mean:

Plain HTML as a base

This is simply progressive enhancement. The table is simply a table. The only concession we’re doing here is putting the table into an extra container (I’m using a div). Then we turn on overflow scrolling.


.widetable {
  overflow-x: auto;

Add scrollbars for certain browsers

I didn’t do this in my project, but you could use Roger’s code which improves the usability by making it even clearer that you can scroll.

Add the shadows

Lucky for me, I had seen Lea Verou do one of her usual fantastic talks, this particular one on multiple backgrounds and background-attachment. In fact, she described this very use case, only along a vertical axis rather than horizontal. Take a look at her post on the subject, it makes the strategy behind these shadows very clear. Thanks, Lea!

.widetable {
  overflow-x: auto;
  background-image: linear-gradient(left, #ffffff, rgba(255, 255, 255, 0)), linear-gradient(right, #ffffff, rgba(255, 255, 255, 0)), linear-gradient(left, #c3c3c5, rgba(195, 195, 197, 0)), linear-gradient(right, #c3c3c5, rgba(195, 195, 197, 0));
  background-position: 0 0, 100% 0, 0 0, 100% 0;
  background-repeat: no-repeat;
  background-color: white;
  background-size: 4em 100%, 4em 100%, 1em 100%, 1em 100%;
  background-attachment: local, local, scroll, scroll;

Use vendor prefixes where necessary.

To break it down, remember that background-attachment: local fixes a background to the content, so it will scroll when the content scrolls. background-attachment: scroll, which is the default, means that the background will scroll with (in this case the containing) block within the viewport.

Now imagine the block that contains the table (we’re not touching the actual table at all). This container has four backgrounds: two on the left and two on the right. Two of these are the actual shadows. They are placed on either side of the container. The other two are gradients that are attached (via background-attachment: local) to each side of the content of the container, which is the table itself. These gradients serve to hide the shadows when they pass over them. See an example using colored gradients, which makes it easier to follow what is going on.

Many variations

There are many approaches to responsive tables. This worked for my project, but it depends on your tables. The method does have the advantage that it can be universally applied (to any table), and shadows and scrolling only appear when the table is too wide for the viewer’s screen. Some tables could or should be handled differently. Your mileage may vary. Also, nothing’s perfect. You might prefer to tweak the gradients. Great. I’m sure there are things that can be improved. At the base level, though, we’ve simply got a normal HTML table that scrolls within its container. Not too fancy, but it might beat scrolling the whole page horizontally or jumping through hoops to accommodate every table in your responsive site.

Carousel-Based Web Design

It’s time to stop this ridiculous talk about semantics, multi-platform, accessibility and universal web bullshit and start talking about… carousels. That’s right. Carousels.

No one actually expected a new solution to the problems of stakeholder pacification and attention-grabification after the untimely demise of blink and marquee, but we certainly found it. The carousel. Beautiful. Dynamic. There’s no getting around the carousel. It’s here to stay. Let’s talk about why.

Departments, stakeholders, and the push mentality

You can blah blah blah all you want, but the only responsible way to make every single stakeholder happy is to put all of their stuff on the home page, and do you really want to make the home page that big? No way in hell. The answer is, as you might have guessed: a carousel. Works just as well for three departments as for 15. All of these stakeholders get their Very Important Information on the home page.

That said, you can’t simply create a normal carousel and call it a day. Forward-thinking web developers always write some kind of algorithm to make sure that each department gets the proper amount of “first views” on the carousel. Stop the Math.random madness before it gets out of hand.

Sites need movement

This isn’t 1996. With billions of sites that the user is not looking at while they’re looking at yours by choice without any goals in their mind whatsoever, we need to use movement to turn their attention to the things they’re not looking for. And what better way to do that than use some kind of jQuery plugin. Experienced developers choose a plugin that will slow the page down a bit, giving users time to read the stuff in the carousel. All that bullshit about performance simply makes it harder for users to read the copy that people painstakingly write to fill the same amount of characters that was in the design’s Lorem Ipsum.

Good design has movement, which makes it “dynamic”. All clients want a dynamic site, since dynamic is the opposite of static. When you think about it, this makes perfect sense. Without light, there is no dark.

What the critics say

Some (ignorant) critics will say that users don’t want to sit there and wait to see the next item in the carousel. This is, well, just plain stupidity. Obviously, that’s why we have those little dots in there, but the skeptics fail to notice the thought that has gone into that.

And to those who say that those dots only tell us how many items there are but nothing about the content, forcing users to click on each one, well… isn’t that the whole point? We are the ninjas of the user experience, the conjurors of marketing. We are leading the users into the experience we want them to have.

At the end of the day, users don’t just want to get the information they want. They want an experience. We know this because we present statistics in such a way that they support our opinions on these matters. It’s called research, and you can’t argue with research.

Carousels save money

Let’s face facts: carousels are easy to make because the Not Invented Here syndrome means that we have 12,347 different carousel options to choose from, depending on the size of dots we want and if they are presented horizontally or vertically. Almost all of these are free to use, so we can charge our clients for implementation. They are okay with these charges because of the value the carousel brings to the project. Carousels allow us to present all of the content the client wants to present, which saves the client money because they no longer need a content strategist.

The mobile problem

The whole idea that carousels might be a problem on mobile is debatable. On the other hand, we know based on factual guesswork that mobile users (as opposed to desktop users) prefer to get straight to the information they need, so we can simply use browser detection and use display:none for carousels on mobile devices. Mobile users are in a hurry and need information, not entertainment, so in this case, CSS is our friend. Stakeholders accept this, and are usually willing to accept hiding carousels, although as mobile browsers become more capable, we might consider supporting more of them.

Use carousels for the serious stuff

If we want to do things right, we need to start putting other content into carousels as well. As we say in the industry, “carousels are the new tabs”. Why not put sections of the main content into carousels? And yes, I will even go so far as to suggest that navigation be placed a carousel. We need to encourage users to really think about what information they need. Seeing “Products” for a few seconds before seeing “About Us” really gives them the opportunity to think about their navigational choices. Seriously, our world’s fast enough as it is. Give the users some time to think, for goodness’ sake.

In conclusion

In summary, this approach, which we’ll call CBWD (Carousel-Based Web Design) for easy remembering, can help you please your clients by giving them more opportunity for publishing trivial content in less space. It will save money by eliminating tiresome considerations like content relevance and importance, accessibility (oh man talk about time-consuming), and website performance (as trendy and overrated as the whole “standards” thing, which has made it almost impossible to sell good Flash intros nowadays).

Be sure to follow us on Twitter, and check out our GitHub repo for the newest code. A one-page site with a cute logo of a cartoon animal and the text npm install cbwd in a low-vision user font is coming soon. CBWD is node.js based but we’ve got ports in ruby, python, even C++ and SWI Prolog. Proudly using Sass, Compass, Grunt, Yeoman, Angular.js, offered as a Flask, Django, or Rails app, with some Ember.js, D3, and we’re using HTML5 localStorage instead of cookies to store carousel view user info. All of this is packed into a fork of Bootstrap weighing a tiny 6MB (minified, gzipped and microwaved).


(2013-09-22) Just to be on the safe side: This article is sarcasm. I do not advocate using carousels. Read that again. It pains me to have to point out what I think is obvious, but English is not everyone’s first language, and my sense of humor is hit-or-miss on some people. The last thing we want is for this post to land in someone’s web design curriculum. Now relax and have a nice day.