47

I have this form placed in the footer of my page (has just one text box and one button). I want to try and apply @media to it, based on the viewport width available ... So for example, in my case the full width this form needs it about 270px or so. So I want to apply CSS to say that:

if the width available is at least 270px
     apply first set of CSS rules
else
     apply second set of CSS rules

How can I do this using @media ?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Ahmad
  • 12,886
  • 30
  • 93
  • 146

3 Answers3

60

There's no if/else syntax for @media, so you would need to repeat the same media query in two separate @media rules and use not for one of them to mean "else".

In your case, the media query would be all and (min-width: 270px). (You need to have a media type for not to work; the default is all so I'm just using that.)

Your CSS would then look like this:

@media all and (min-width: 270px) {
    /* Apply first set of CSS rules */
}

@media not all and (min-width: 270px) {
    /* Apply second set of CSS rules */
}

I should add that one popular way is to make use of the cascade by having just one @media rule for overriding styles:

/* Apply second set of CSS rules */

@media all and (min-width: 270px) {
    /* Apply first set of CSS rules */
}

However this falls short if you have any styles outside the @media rule that aren't (or cannot be) overridden inside it. Those styles would continue to apply, and you have no way of undoing them short of actually redeclaring them. Sometimes you cannot undo them by redeclaring them, and that's when you cannot use this method to apply styles. See my answer to this question for a detailed explanation.

In this example, the height: 200px declaration will always apply:

.example {
    width: 200px;
    height: 200px;
}

@media all and (min-width: 270px) {
    .example {
        width: 400px;
    }
}

Of course, if that's not a problem then you can use this in order to avoid duplicating media queries. But if you're looking for a strict if/else construct, then you'll have to use not and a duplicated media query.

Community
  • 1
  • 1
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • 1
    @Ahmad: Yes, you can. – BoltClock Jul 14 '13 at 11:08
  • Technically your answer was correct here, but it seems my actual problem is still not 100% solved. I have a feeling you're pretty experienced in CSS, so please have a look here too: http://stackoverflow.com/questions/17640057/how-to-switch-between-css-rule-sets-based-on-available-parent-width-not-viewpo – Ahmad Jul 14 '13 at 14:07
  • @BoltClock do you know if this same logic is applicable to link head tags? 'Cause I'm facing some issue there using this fancy approach... – Niki Romagnoli Feb 24 '16 at 16:46
  • @TechNyquist: Yes, `` accepts a media query so you could, in theory, do the same thing using the `not` technique. – BoltClock Feb 24 '16 at 16:52
  • @BoltClock it works indeed. I was just mistyping it. Thanks. – Niki Romagnoli Feb 24 '16 at 17:11
  • Downvoted because "all" media types has nothing to do with the question, even though it sounds right. Maybe this works for the wrong reasons? Nonetheless, I think your answer is simply wrong and misleading a lot of people. – PJ Brunet May 18 '19 at 02:49
  • 1
    @PJ Brunet: As I stated in the second paragraph, the "all" media type is required for the "not" to work correctly in MQ3-compliant browsers. I addressed this further in an answer I posted [a little less than a year after this one](https://stackoverflow.com/a/24456052) and neglected to retroactively cite it here. I'm not sure if browsers have been updated to remove this inexplicable restriction yet. But this answer is six years old now. Internet Explorer still exists. I think it's worth leaving it in for historical reasons. I'd rather you didn't blame my answer for a flaw in the (old) spec... – BoltClock Sep 01 '19 at 18:31
7

Yes. Typically start with your main CSS and then alter the design based on width (or media type) with additional CSS that will overwrite any previous CSS.

<style type=text/css">

/* the main css for the site */
.main-content {width:960px;}


/* the css adjustment for the site between two widths */
@media screen and (max-width:600px) and (min-width:271px) {
    .main-content {width:100%;}
}

/* the css adjustment for the site with a max-width of 270px */
@media screen and (max-width:270px) {
    .main-content {width:260px;}
}
</style>
Shanosha
  • 106
  • 2
2

This is how you would implement that scenarion

<style>
 // apply second set of CSS rules
@media (min-width: 270px) {
 // apply first set of CSS rules
}
</style>

In this situation the CSS rules applied beforehand would get overwritten when the media query argument is met.

Kevin Lynch
  • 24,427
  • 3
  • 36
  • 37