使用Sass变量和CSS3媒体查询

Jer*_* S. 94 sass media-queries

我正在尝试将Sass变量的使用与@media查询结合使用,如下所示:

$base_width:1160px;

@media screen and (max-width: 1170px) {$base_width: 960px;}
@media screen and (min-width: 1171px) {$base_width: 1160px;}
Run Code Online (Sandbox Code Playgroud)

$base_width 然后在基于样式表宽度百分比的测量中的各个点处定义,以产生流体布局.

当我这样做时,变量似乎被正确识别,但媒体查询的条件不是.例如,无论屏幕宽度如何,上面的代码都会产生1160px的布局.如果我像这样触发@media语句:

@media screen and (min-width: 1171px) {$base_width: 1160px;}
@media screen and (max-width: 1170px) {$base_width: 960px;}
Run Code Online (Sandbox Code Playgroud)

无论屏幕宽度如何,它都会产生960px的布局.另请注意,如果我删除它的第一行,$base_width: 1160px;则返回未定义变量的错误.我缺少什么想法?

woe*_*ndl 85

这根本不可能.由于触发@media screen and (max-width: 1170px)发生在客户端.

只有当SASS抓住包含$base_width变量的样式表中的所有规则和属性并相应地复制/更改它们时,才能实现预期结果.

由于它不能自动工作,你可以这样手工完成:

@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
          ...
Run Code Online (Sandbox Code Playgroud)

这不是真的干,但你能做的最好.

如果每次您还准备包含所有更改值的mixin时更改都相同,那么您不需要重复它.此外,您可以尝试将mixin与特定更改结合起来.喜欢:

@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
Run Code Online (Sandbox Code Playgroud)

Mixin看起来像这样

=base_width_changes($base_width)
    #wrapper
        width: $base_width
Run Code Online (Sandbox Code Playgroud)

  • @ericsoco我不明白为什么这是一个原因.SASS可以轻松地(?)跟踪变量的所有用法,并插入媒体查询使用它们; `$ foo:1rem; @media(min-width:10rem){$ foo:2rem} .class {font-size:$ foo} .class2 {padding:$ foo}`会产生`.class {font-size:1rem} .class2 { padding:1rem} @media(min-width:10rem)(.class {font-size:2rem} .class2 {padding:2rem}}` (21认同)
  • 是否仍然存在SASS不能与@media查询中的$变量一起使用的情况? (6认同)
  • 是的 sass 是一个预处理器,没有理由“这根本不可能”......它可以做到,只是没有实现。 (5认同)
  • 是的,不幸的是!(2014年9月) (2认同)
  • @HappyTorso 情况总是如此,直到出现在视口调整大小上运行的客户端 Sass 编译器(例如在 JavaScript 中)。Sass 变量在构建时被编译为静态值;它们在运行时不再存在。当查询中的媒体属性发生变化时,媒体查询会在运行时进行评估。 (2认同)

ron*_*nen 44

与Philipp Zedler的答案类似,你可以用mixin来做.如果您愿意,这可以让您将所有内容都放在一个文件中.

    @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);
    }
Run Code Online (Sandbox Code Playgroud)


fre*_*und 15

这对于 SASS 是不可能的,但是对于 CSS 变量(或CSS 自定义属性)是可能的。唯一的缺点是浏览器支持——但实际上有一个 PostCSS 插件——postcss-css-variables——它“扁平化”了 CSS 变量的使用(它也为你提供了对旧浏览器的支持)。

以下示例适用于 SASS(并且使用 postcss-css-variables 您也可以获得对旧浏览器的支持)。

$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);
}
Run Code Online (Sandbox Code Playgroud)

这将导致以下 CSS。重复的媒体查询会增加文件大小,但我发现一旦 Web 服务器应用gzip(它通常会自动执行),这种增加通常可以忽略不计。

$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);
}
Run Code Online (Sandbox Code Playgroud)


Phi*_*ler 7

编辑:请不要使用此解决方案.ronen的答案要好得多.

作为DRY解决方案,您可以@import在媒体查询中使用该语句,例如像这样.

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

您可以使用媒体查询中定义的变量定义文件中包含的所有响应元素.所以,你需要重复的是import语句.


Daw*_*rcz 6

我有同样的问题。

$menu-width变量在移动视图上应为 240@media only screen and (max-width : 768px)像素,在桌面视图上应为340 像素。

所以我简单地创建了两个变量:

$menu-width: 340px;
$menu-mobile-width: 240px;
Run Code Online (Sandbox Code Playgroud)

这是我如何使用它:

.menu {
    width: $menu-width;
    @media only screen and (max-width : 768px) {
      width: $menu-mobile-width;
    }
}
Run Code Online (Sandbox Code Playgroud)


Ben*_*Ben 5

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
        ));
    }
Run Code Online (Sandbox Code Playgroud)

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/