20

I'd like to use the same variable for different media queries. Something like this:

$avatar_size: 200px;

@media (#{$tablet_size}) {
  $avatar_size: 150px;
}
@media (#{$mobile_size}) {
  $avatar_size: 100px;
}

The objective is to be able to use this variable in multiple places, so I can just reference the variable and not have to throw in the media queries every time. Like so:

.font-awesome-icon {
  font-size: $avatar_size;
}
img {
  width: $avatar_size;
  height: $avatar_size;
}
.img-wrapper {
  height: $avatar_size;
}

Any way to do this?

Mateusz Piotrowski
  • 8,029
  • 10
  • 53
  • 79
Doug
  • 1,517
  • 3
  • 18
  • 40

6 Answers6

12

Try using CSS custom properties instead of SASS variables.

@media (min-width: 300px) {
  :root {
    --width: 250px;
  }
}

@media (min-width: 600px) {
  :root {
    --width: 450px;
  }
}

svg {
  width: var(--width);
}

This will change the width of a svg element dependent on the screen size.

Just experiment with it using this JSFiddle.

Note: If you want to use CSS custom properties with SASS expressions, you have to wrap them in #{}. Read more about CSS custom property support in SASS.

@media (min-width: 300px) {
  :root {
    --width: #{$small-width};
  }
}

@media (min-width: 600px) {
  :root {
    --width: #{$wide-width};
  }
}

svg {
  width: var(--width);
}
d-k-bo
  • 513
  • 5
  • 12
  • `var > $` Works nicely, I wonder if there’s any objection to using it in implementing responsiveness. – dakab Sep 28 '22 at 08:14
11

This is impossible, variables are assigned values when the Sass is compiled to CSS.

what you can do is this:

$avatar_size: 200px;
$avatar_tablet: 150px;
$avatar_mobile: 100px;

@media (#{$tablet_size}) {
  img {
    width: $avatar_tablet;
    height: $avatar_tablet;
  }
}

@media (#{$mobile_size}) {
  img {
    width: $avatar_mobile;
    height: $avatar_mobile;
  }
}
Nir Ben-Yair
  • 1,566
  • 3
  • 14
  • 18
  • It is not correct. You _can_ use scss (Sass) variables as property. [See this answer](https://stackoverflow.com/a/15292910/8783706) – Willi Jan 22 '18 at 18:08
6

If the sizes are fixed like that, you can create a mixin where the property value is the input:

@mixin avatar_size($prop) {
  #{$prop}: 200px;
  @media (#{$tablet_size}) {
    #{$prop}: 150px;
  }
  @media (#{$mobile_size}) {
    #{$prop}: 100px;
  }
}

.font-awesome-icon {
  @include avatar_size('font-size');
}
img {
  @include avatar_size('width');
  @include avatar_size('height');
}
.img-wrapper {
  @include avatar_size('height');
}

I'm guessing you're not really going to use the same value for font-size as for width/height, but since you showed that like that in your question, my answer shows that as well.

andi
  • 6,442
  • 1
  • 18
  • 43
1

Try to use utility class, instead of using variables.

.avatar-size {
  @media (your-breakpoint) { width: width-depends-your-situation }
}
Youssef
  • 11
  • 1
0

CSS variables (and SASS variables) cannot be assigned as properties, only values.

The whole point of setting up a variable is to be able to modify the variable and have the changes reflected in multiple places. Considering the variable is designed to change, it makes no sense to give it different values in different scenarios (such as media queries). In such, a situation, you would be looking to define multiple variables.

In terms of SASS, you need to define the standard CSS property, and then your custom variable (which gets used as the value):

$colour: red;

.a {
  color: $colour;
}

.b {
  background-color: $colour;
}

This will evaluate to:

.a {
  color: red;
}

.b {
  background-color: red;
}

This can be seen working in this JSFiddle.

Note that this can also be achieved with raw CSS. This is done with CSS variables, which are denoted with a double hyphen prefix in the :root selector:

:root {
  --colour: red;
}

.a {
  color: var(--colour);
}

.b {
  background-color: var(--colour);
}
<div class="a">One</div>
<div class="b">Two</div>

Hope this helps :)

Obsidian Age
  • 41,205
  • 10
  • 48
  • 71
  • How does this relate to the question? – Ruslan Jan 22 '18 at 10:52
  • @Sam -- By providing an answer to it? If you disagree, feel free to add your own answer. I love how people like you are so quick to criticise, yet rarely seem to offer an alternative solution to the "wrong" answer. – Obsidian Age Jan 22 '18 at 19:09
  • 1
    And I love people who answer but do not understand what the question is about =) – Ruslan Jan 22 '18 at 19:33
0

In case of using postcss try this: https://github.com/postcss/postcss-custom-media

@custom-media --small-viewport (max-width: 30em);

@media (--small-viewport) {
  /* styles for small viewport */
}

/* becomes */

@media (max-width: 30em) {
  /* styles for small viewport */
}