98

Of late, I've been designing sites that are more responsive and I've been using CSS media queries frequently. One pattern I noticed is that the order in which the media queries are defined actually matters. I didn't test it in every single browser, but just on Chrome. Is there an explanation for this behaviour? Sometimes it gets frustrating when your site doesn't work as it should and you are unsure if it's the query or the order in which the query is written.

Here's an example:

HTML

<body>
    <div class="one"><h1>Welcome to my website</h1></div>
    <div class="two"><a href="#">Contact us</a></div>
</body>

CSS:

body{
font-size:1em; /* 16px */
}

.two{margin-top:2em;}



/* Media Queries */

@media (max-width: 480px) {
    .body{font-size: 0.938em;}

}
/* iphone */
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
    body {font-size: 0.938em;}
}
/*if greater than 1280x800*/
@media (min-width: 1200px) {
       .two{margin-top:8em;}
            }
/*1024x600*/
@media (max-height: 600px) {
       .two{margin-top:4em;}
}
/*1920x1024*/
@media (min-height: 1020px) {
       .two{margin-top:9em;}
}
/*1366x768*/
@media (min-height: 750px) and (max-height: 770px) {
       .two{margin-top:7em;}
}

However, If I wrote the query for 1024x600 in the last, the browser would ignore it and apply the margin value specified in the starting of the CSS (margin-top:2em).

/* Media Queries - Re-arranged version */

@media (max-width: 480px) {
    .body{font-size: 0.938em;}
}
/* iphone */
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
    body {font-size: 0.938em;}
}
/*if greater than 1280x800*/
@media (min-width: 1200px) {
       .two{margin-top:8em;}
}
/*1920x1024*/
@media (min-height: 1020px) {
       .two{margin-top:9em;}
}
/*1366x768*/
@media (min-height: 750px) and (max-height: 770px) {
       .two{margin-top:7em;}
}
 /*1024x600*/
@media (max-height: 600px) {
       .two{margin-top:4em;}
}

If my understanding of media queries are correct, the order shouldn't matter, but it seems it does. What could be the reason?

simanacci
  • 2,197
  • 3
  • 26
  • 35
dsignr
  • 2,295
  • 2
  • 35
  • 45

4 Answers4

162

That's by design of CSS — Cascading Style Sheet.

It means that, if you apply two rules that collide to the same elements, it will choose the last one that was declared, unless the first one has the !important marker or is more specific (e.g. html > body vs just body, the latter is less specific).

So, given this CSS

@media (max-width: 600px) {
  body {
    background: red;
  }
}

@media (max-width: 400px) {
  body {
    background: blue;
  }
}

if the browser window is 350 pixels wide, the background will be blue, while with this CSS

@media (max-width: 400px) {
  body {
    background: blue;
  }
}

@media (max-width: 600px) {
  body {
    background: red;
  }
}

and the same window width, the background will be red. Both rules are indeed matched, but the second one it's the one that is applied because is the last rule.

Finally, with

@media (max-width: 400px) {
  body {
    background: blue !important;
  }
}

@media (max-width: 600px) {
  body {
    background: red;
  }
}

or

@media (max-width: 400px) {
  html > body {
    background: blue;
  }
}

@media (max-width: 600px) {
  body {
    background: red;
  }
}

the background will be blue (with a 350 pixels wide window).

Alessandro Vendruscolo
  • 14,493
  • 4
  • 32
  • 41
  • 16
    Thank you. I never imagined such a simple logic would ruin my sleep for nights together. Thanks. – dsignr Jan 09 '12 at 18:30
  • In a style sheet if same rules are applied without any media query and then within a media query for small screen mobile deices and there are some images to down load. So what would be happened, does browser will ignore the rules without media query and apply only specific media query's rules? –  Mar 11 '17 at 18:41
  • Is there a **programmatic** way to find out which media-query (between multiple matched-queries) will overcome over others? *I mean something like `matchMedia()` function that gets an **array of queries** and returns only one (or none) ... or even sorts them based on the priority.* – Mir-Ismaili Nov 10 '21 at 19:53
  • @Mir-Ismaili — I'm not aware of a programmatic way (nor can I really see a use for one) but the DOM Inspector features of the developer tools in most browsers will show you which rules are applied to any given element and will indicate which are overridden. – Quentin Apr 03 '23 at 16:20
24

Or you could just add min-width to the bigger media query/ies and not have any issues, regardless of the order.

@media (min-width: 400.1px) and (max-width: 600px) {
  body {
    background: red;
  }
}

@media (max-width: 400px) {
  body {
    background: blue;
  }
}

Using this code, in any order, the background-color will always be red for resolutions with a width of 400.1px-600px, and will always be blue for resolutions with a width of 400px or less.

Liran H
  • 9,143
  • 7
  • 39
  • 52
0

<body>
    <div id="div1">
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo similique minus facere error sunt tenetur deleniti debitis esse animi dolores repudiandae assumenda incidunt ipsa odio sapiente, omnis expedita aliquam sequi, cum reprehenderit? Asperiores aut officia dolorem voluptatem natus ipsum voluptates fuga odio qui velit et fugit consectetur esse obcaecati id, repudiandae alias delectus eveniet assumenda. Facere ex ea rem assumenda, in sequi animi quibusdam necessitatibus, totam error sed officia vel at maxime voluptate nam ipsam, provident aperiam nobis minus voluptates inventore? Voluptates minima debitis, qui architecto eius natus minus consectetur blanditiis unde suscipit tempore, nulla, fugit magni molestias odio doloribus!</p>
    </div>
</body>

Or you could just write that in Different Order i.e. Write a bigger media query first and then the smaller ones.

@media screen and (max-width: 900px) {  /* CSS runs from top to bottom  */
    #div1{
        background-color: red;
    }
}

@media screen and (max-width: 600px) {
    #div1{
        background-color: blue;
    }
}

Now, As you gradually going to decrease the size of the screen i.e. if the size of the screen is 601px (which is more than 600px but less than 900px) then, the background color will be "red" in that case. Similarly, if the screen size is 599px (which is less than both 600px and 900px) then the later one going to apply i.e. background becomes "blue". So, it checks each condition as you gradually decrease the screen size from top to bottom.

-1

I may be dumb but why not:

@media (max-width: 399px) {
  body {
    background: blue;
  }
}

@media (min-width: 400px) and (max-width: 600px) {
  body {
    background: red;
  }
}
  • While that is an approach for keeping the rules in that order and having them apply as expected … you haven't answered the question that was asked. – Quentin Apr 03 '23 at 16:21
  • Yes, but it doesn't matter which order the statements are in, the result is the same. The order only matters if the specificity is equal. – user1368737 Apr 04 '23 at 20:13