使用Sass变量和CSS3媒体查询

时间:2012-02-03 00:41:49

标签: 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;}
然后在样式表宽度百分比测量中的各个点定义

$base_width以生成流体布局。

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

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

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

8 个答案:

答案 0 :(得分:76)

这根本不可能。由于触发器@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
          ...

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

如果每次您还准备包含所有更改值的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

Mixin看起来像这样

=base_width_changes($base_width)
    #wrapper
        width: $base_width

答案 1 :(得分:34)

与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);
}

答案 2 :(得分:6)

修改:请不要使用此解决方案。 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";
}

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

答案 3 :(得分:2)

我遇到了同样的问题。

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

所以我只创建了两个变量:

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

以下是我如何使用它:

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

答案 4 :(得分:2)

两个建议

1 将您的“默认” CSS语句编写为用于小屏幕,而仅将媒体查询用于大屏幕。通常不需要max-width媒体查询。

示例(假设元素具有“容器”类)

@mixin min-width($width) {
  @media screen and (max-width: $width) {
    @content;
  }
}

.container {
  width: 960px;

  @include min-width(1170px) {
    width: 1160px;
  }
}

2 ,如果为you can,则使用CSS变量解决问题。

@mixin min-width($width) {
  @media screen and (max-width: $width) {
    @content;
  }
}

:root {
  --container-width: 960px;
  @include min-width(1170px) {
    --container-width: 1160px;
  }
}

.container {
  width: var(--container-width);
}

注意:

由于当窗口的宽度为1170px时它将具有1160px的宽度,因此最好使用100%的宽度和1160px的最大宽度,并且父元素的水平填充为5px,只要box-sizing属性设置为border-box。有很多解决问题的方法。如果父级不是flex或grid容器,则可以使用.container { margin: auto }

答案 5 :(得分:1)

这对于SASS是不可能的,但是对于CSS变量(或CSS custom properties)是可行的。唯一的缺点是对浏览器的支持–但是实际上有一个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);
}

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

.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;
  }
}

答案 6 :(得分:0)

使用@ronen的great answer和地图,可以使用一些实际功能:

@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
    ));
}

现在可能有更多针对.myDiv的DRY媒体查询,并且具有许多不同的值。


地图文档:https://sass-lang.com/documentation/functions/map

地图用法示例:https://www.sitepoint.com/using-sass-maps/

答案 7 :(得分:0)

这也可以使用 %placeholders。

%placeholders 可以包含在媒体查询中。因此,您可以设置多个变量以用于不同的屏幕尺寸,然后占位符将自动进行相应的预处理。我也在此处使用了一些 mixin 来缩短我的媒体查询声明。

在您的 _vars.scss 文件中:

    $width-1: 960px;
    $width-2: 1160px;

在您的 _placeholders.scss 文件中:

    %variable-site-width                    { 
        @media screen and (max-width: 1170px)       { width: $width-1; }
        @media screen and (min-width: 1171px)       { width: $width-2; }
    }

在您的 page.scss 文件中:

    .wrapper.     { @extend %variable-site-width; background: red; etc... }

这将编译为类似于:

    @media screen and (max-width: 1170px) { 
        .wrapper { width: 960px; }
    }
    @media screen and (min-width: 1171px) { 
        .wrapper { width: 1160px; }
    } 

瞧!

我广泛地将这种技术用于诸如可变字体大小和大量其他事情之类的事情。