I'm trying to combine the use of a Sass variable with @media queries as follows:
$base_width:1160px;
@media screen and (max-width: 1170px) {$base_width: 960px;}
@media screen and (min-width: 1171px) {$base_width: 1160px;}
$base_width
is then defined at various points in the stylesheet width percentage-based measurements to produce fluid layouts.
When I do this, the variable seems to be recognized properly but the conditions for the media query are not. For example, the above code produces an 1160px layout regardless of screen width. If I flip-flop the @media statements like so:
@media screen and (min-width: 1171px) {$base_width: 1160px;}
@media screen and (max-width: 1170px) {$base_width: 960px;}
It produces a 960px layout, again regardless of screen width. Also note that if I remove the first line of $base_width: 1160px;
it returns an error for an undefined variable. Any ideas what I'm missing?
If you're like me, you've probably been stretching CSS variables / custom properties to their limits while building your own design systems. But this "silver bullet" can lead to a nasty roadblock: you can't use them in media query declarations.
@media permalink @mediaLibSass and older versions of Dart Sass and Ruby Sass don't support media queries with features written in a range context. They do support other standard media queries.
Sass variables are all compiled away by Sass. CSS variables are included in the CSS output. CSS variables can have different values for different elements, but Sass variables only have one value at a time.
To convert the SASS variable to a CSS custom property you put curly brackets around it, and a hash in front. If you've used template literals in JavaScript it's the same thing, just with a # instead of a $ (because we already have $ in the variable name).
This is simply not possible. Since the trigger @media screen and (max-width: 1170px)
happens on the client-side.
Achieving your expected result would only be possible if SASS grabbed all rules and properties in your stylesheet containing your $base_width
variable and copied/changed them accordingly.
Since it won't work automatically you could do it by hand like this:
@media screen and (max-width: 1170px)
$base_width: 960px // you need to indent it to (re)set it just within this media-query
// now you copy all the css rules/properties that contain or are relative to $base_width e.g.
#wrapper
width: $base_width
...
@media screen and (min-width: 1171px)
$base_width: 1160px
#wrapper
width: $base_width
...
This is not really DRY but the best you can do.
If the changes are the same every time you could also prepare a mixin containing all the changing values, so you wouldn't need to repeat it. Additionally you can try to combine the mixin with specific changes. Like:
@media screen and (min-width: 1171px)
+base_width_changes(1160px)
#width-1171-specific-element // additional specific changes, that aren't in the mixin
display: block
And the Mixin would look like this
=base_width_changes($base_width)
#wrapper
width: $base_width
Similar to Philipp Zedler's answer, you can do it with a mixin. That lets you have everything in a single file if you want.
@mixin styling($base-width) {
// your SCSS here, e.g.
#Contents {
width: $base-width;
}
}
@media screen and (max-width: 1170px) {
@include styling($base-width: 960px);
}
@media screen and (min-width: 1171px) {
@include styling($base-width: 1160px);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With