0

I'm trying to do something like this:

$arrow-size: 30px;

@media only screen and (max-width: 449px) {
  $arrow-size: 15px;
}

div.selector {
  height: 0px;
  width: 0px;
  position: absolute;
  bottom: 0px;
  left: 50%;
  border-bottom: $arrow-size solid white;
  border-left: $arrow-size solid transparent;
  border-right: $arrow-size solid transparent;
}

Unfortunately, $arrow-size does not change according to the media query (my arrow is always 15px, even if my window is wider than 449px).

Any idea ? Or am I taking the problem the wrong way ?

MaximeBernard
  • 1,090
  • 1
  • 19
  • 33
  • Related: http://stackoverflow.com/questions/5305952/how-to-use-sass-logic-within-a-css-3-media-query – cimmanon Sep 03 '13 at 13:58
  • It's exactly the possible duplicate quoted by @cimmanon! Thanks for the link. By the way, the related one seems to be opposing the duplicate one. Am I wrong ? – MaximeBernard Sep 03 '13 at 14:19

3 Answers3

2

I would use a mixin:

@mixin arrow($size) {
  border: $size;
}

Then you can use it in your media query like this (combined with a variable):

$arrowSize: 30px;

@media only screen and (max-width: 449px) {
  div.selector {
    @include arrow($arrowSize / 2);
  }
}

div.selector {
  @include arrow($arrowSize);
}
Jasper de Vries
  • 19,370
  • 6
  • 64
  • 102
2

As an alternative, try using the power of em's:

$arrow-size: 1.875em; // 30px, use pxtoem.com for conversion

div.selector {
  height: 0px; width: 0px;
  position: absolute;
  bottom: 0px; left: 50%;
  border-bottom: $arrow-size solid white;
  border-left: $arrow-size solid transparent;
  border-right: $arrow-size solid transparent;
}

@media only screen and (max-width: 449px) {
  div.selector { font-size: 50%; }
}

Since the em is relative to the font-size, all you gotta do is play with that value to change the size of the arrow across different responsive states.

Brian
  • 2,819
  • 4
  • 24
  • 30
  • I would prefer this approach. It's better then repeating the entire selector in each query. +1 – Jasper de Vries Sep 03 '13 at 15:20
  • I also love this trick. But you have to think "em" since the begining of your project if you don't want side effects. I'll use this one next time :) Thanks! – MaximeBernard Sep 03 '13 at 16:29
  • It's true em's should be planned from the start, but as long as your parent isn't being modified, you can be pretty safe with it. Heck, do the whole arrow on a :before, leaving .selector to always have a fixed font-size and then you can modify w/o side effects. – Brian Sep 03 '13 at 16:59
1

I think you did not understand how works SASS / Compass and media queries. Variables are transformed by the compiler before being sent to the client as opposed to media queries that are interpreted by the browser's CSS engine as well as conventional selectors (id, class, tag)

The compiler does not interpret the media query as a condition, simply because at the time of compilation, the screen size is not defined, and especially because it is not his job.

Here is a simplified version of what happens:

  • 1 $arrow-size: 30px; "ok, I set a new variable arrow-size to 30px"
  • 3 @media only screen and (max-width: 449px) { "ok, a new selector... syntax is correct, I'll look later if the brace is closed."
  • 4 $arrow-size: 15px; "ok, I set the arrow-size variable to 15px"
  • 5 } "ok, brace is closed"
  • ...
  • 13 border-bottom: $arrow-size solid white; "A new css rule, syntax ok... oh, I have to replace a variable ! How much for $arrow-size ? Oh yes, 15px, I change it."

In result, the compiled CSS file will be :

screen.css

@media only screen and (max-width: 449px) {
}

div.selector {
  height: 0px;
  width: 0px;
  position: absolute;
  bottom: 0px;
  left: 50%;
  border-bottom: 15px solid white;
  border-left: 15px solid transparent;
  border-right: 15px solid transparent;
}

you can also put your media queries into selectors :

$arrow-normal-size: 30px;
$arrow-small-size: 15px;

div.selector {
  height: 0px;
  width: 0px;
  position: absolute;
  bottom: 0px;
  left: 50%;
  border-bottom: solid white;
  border-left: solid transparent;
  border-right: solid transparent;
  border-width: $arrow-normal-size;

  @media only screen and (max-width: 449px) {
    border-width: $arrow-small-size;
  }
}

or use a mixin :

a little bit useless in this specific case

@mixin responsive-border($max-screen-width, $border-width){
  @media only screen and (max-width: #{$max-screen-width}) {
    border-width: $border-width;
  }
}

div.selector {
  height: 0px;
  width: 0px;
  position: absolute;
  bottom: 0px;
  left: 50%;
  border-bottom: solid white;
  border-left: solid transparent;
  border-right: solid transparent;
  border-width: 30px;

  @include responsive-border(449px,15px);
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
hexaJer
  • 825
  • 7
  • 12