Using Sass Variables with CSS3 Media Queries

2018-12-31 16:50发布

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?

4条回答
琉璃瓶的回忆
2楼-- · 2018-12-31 17:15

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);
}
查看更多
明月照影归
3楼-- · 2018-12-31 17:22

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
查看更多
旧时光的记忆
4楼-- · 2018-12-31 17:29

Edit: Please do not use this solution. The answer by ronen is much better.

As a DRY solution, you can use the @import statement inside a media query, e.g. like this.

@media screen and (max-width: 1170px) {
    $base_width: 960px;
    @import "responsive_elements";
}
@media screen and (min-width: 1171px) {
    $base_width: 1160px;
    @import "responsive_elements";
}

You define all responsive elements in the file included using the variables defined in the media query. So, all you need to repeat is the import statement.

查看更多
初与友歌
5楼-- · 2018-12-31 17:35

I had the same problem.

The $menu-width variable should be 240px on the mobile view @media only screen and (max-width : 768px) and 340px on the desktop view.

So i have simply created two variables:

$menu-width: 340px;
$menu-mobile-width: 240px;

And here is how i have used it:

.menu {
    width: $menu-width;
    @media only screen and (max-width : 768px) {
      width: $menu-mobile-width;
    }
}
查看更多
登录 后发表回答