Using Sass Variables with CSS3 Media Queries

后端 未结 7 2141
醉话见心
醉话见心 2020-11-22 14:06

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: 96         


        
相关标签:
7条回答
  • 2020-11-22 14:50

    This isn't possible with SASS, but it is possible with CSS variables (or CSS custom properties). The only drawback is browser support – but there's actually a PostCSS plugin - postcss-css-variables - that "flattens" the use of CSS variables (which gives you support for older browsers, too).

    The following example works great with SASS (and with postcss-css-variables you get support for older browsers too).

    $mq-laptop: 1440px;
    $mq-desktop: 1680px;
    
    :root {
        --font-size-regular: 14px;
        --gutter: 1rem;
    }
    
    // The fact that we have to use a `max-width` media query here, so as to not
    // overlap with the next media query, is a quirk of postcss-css-variables
    @media (min-width: $mq-laptop) and (max-width: $mq-desktop - 1px) {
        :root {
            --font-size-regular: 16px;
            --gutter: 1.5rem;
        }
    }
    
    @media (min-width: $mq-desktop) {
        :root {
            --font-size-regular: 18px;
            --gutter: 1.75rem;
        }
    }
    
    .my-element {
        font-size: var(--font-size-regular);
        padding: 0 calc(var(--gutter) / 2);
    }
    

    This would result in the following CSS. The repetitive media queries will increase the file size, but I have found that the increase is usually negligible once the web server applies gzip (which it will usually do automatically).

    .my-element {
      font-size: 14px;
      padding: 0 calc(1rem / 2);
    }
    @media (min-width: 1680px) {
      .my-element {
      padding: 0 calc(1.75rem / 2);
      }
    }
    @media (min-width: 1440px) and (max-width: 1679px) {
      .my-element {
      padding: 0 calc(1.5rem / 2);
      }
    }
    @media (min-width: 1680px) {
      .my-element {
      font-size: 18px;
      }
    }
    @media (min-width: 1440px) and (max-width: 1679px) {
      .my-element {
      font-size: 16px;
      }
    }
    
    0 讨论(0)
  • 2020-11-22 14:50

    With @ronen's great answer and a map, there's some real power available:

        @mixin styling($map) {
            .myDiv {
                background: map-get($map, 'foo');
                font-size: map-get($map, 'bar');
            }
        }
    
        @media (min-height: 500px) {
            @include styling((
                foo: green,
                bar: 50px
            ));
        }
    
        @media (min-height: 1000px) {
            @include styling((
                foo: red,
                bar: 100px
            ));
        }
    

    It's now possible to have lots more DRY media queries targeting .myDiv with a bunch of different values.


    Map docs: https://sass-lang.com/documentation/functions/map

    Example map usage: https://www.sitepoint.com/using-sass-maps/

    0 讨论(0)
  • 2020-11-22 14:50

    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;
        }
    }
    
    0 讨论(0)
  • 2020-11-22 14:51

    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);
        }
    
    0 讨论(0)
  • 2020-11-22 14:51

    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.

    0 讨论(0)
  • 2020-11-22 14:53

    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
    
    0 讨论(0)
提交回复
热议问题