条件媒体查询 Mixin

Avatar of Chris Coyier
Chris Coyier 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

Sass 使使用媒体查询变得非常出色。您可以在其他 CSS 代码块中嵌套它们,这将把您要更改的属性和值放在一起。这在它们之间创建了一个明显的关联,这比尝试维护那些被大量其他代码分隔或在不同文件中更改的属性和值要好得多。我们之前已经介绍过这个内容。它是在 Sass 3.2 中新增的

.column-1-3 {
  width: 33.3333%;
  @media (max-width: 600px) {
    width: 100%;
  }
}

但是,由于我们可能会一遍又一遍地这样做,因此我们应该像处理任何其他变量一样将媒体查询抽象出来。

$bp-babybear: "(max-width: 600px)";

.column-1-3 {
  width: 33.33%;
  @media #{$bp-babybear} {
    width: 100%;
  }
}

不过,更常见的是看到 @mixin 与 Sass @content 块一起使用。我们在文章 媒体查询命名 中介绍了这一点。

@mixin bp($point) {
  @if $point == papa-bear {
    @media (max-width: 1600px) { @content; }
  }
  @else if $point == mama-bear {
    @media (max-width: 1250px) { @content; }
  }
  @else if $point == baby-bear {
    @media (max-width: 600px)  { @content; }
  }
}

您可以像这样使用它

.sidebar {
  width: 33.33%;
  @include bp(baby-bear) {
    width: 100%;
  }
}

并且没有理由不能同时进行这两者,如果您更喜欢这种外观,可以将媒体查询抽象成变量。

@mixin bp($point) {
  
  $bp-babybear: "(max-width: 600px)";
  $bp-mamabear: "(max-width: 1250px)";
  $bp-papabear: "(max-width: 1600px)";

  @if $point == papa-bear {
    @media #{$bp-papabear} { @content; }
  }
  @else if $point == mama-bear {
    @media #{$bp-mamabear} { @content; }
  }
  @else if $point == baby-bear {
    @media #{$bp-babybear}  { @content; }
  }

}

它具有完全相同的用法。

顺便说一句,我喜欢“bp”作为名称,因为它是一个您需要一遍又一遍键入的东西,而且它简短而简洁。

乍一看,@mixin 方法似乎价值有限。仅使用变量更简洁,并且同样有意义。但是,使用 @mixin,我们获得了额外的功能!

也许我们想创建一个根本不包含任何媒体查询的样式表版本。在某些情况下,这绝对是合理的。也许我们想创建一个 IE 8 及以下版本的样式表。Nicolas Gallagher 几年前尝试使用 Sass 来实现这一点,但这略有不同。IE 8 及以下版本本身不支持媒体查询,因此也许我们决定要 为它们提供一个不包含媒体查询的精简样式表。像这样的旧浏览器速度本来就慢,因此与其用它们无法使用的额外代码来惩罚它们,不如通过为它们提供更少的代码来帮助它们。有点像 通用 IE 6 样式表 的想法。

我们可以结合使用 条件注释 来做到这一点。

<!--[if !IE 8]><!-->
  <link rel="stylesheet" href="style.css">
<!--<![endif]-->

<!--[if gte IE 9]>
  <link rel="stylesheet" href="style.css">
<![endif]-->

<!--[if lte IE 8]>
  <link rel="stylesheet" href="style-NoMQs.css">
<![endif]-->

另一个合理的和现实世界的提供不含媒体查询样式表的理由是,如果您的网站某些页面使用响应式设计,而某些页面具有特定于移动设备的版本。我认为这是合理的。 那些具有特定于移动设备版本的页面实际上并不需要其中的媒体查询。

那么,如何从相同的 Sass 源创建 style.cssstyle-NoMQs.css 呢?我们使用 @mixin 的强大功能。

我们在 bp @mixin 中使用逻辑条件,该条件将继续输出媒体查询或不输出任何内容。

$MQs: true;

@mixin bp($point) {
  @if ($MQs) {
    $bp-babybear: "(max-width: 600px)";
    $bp-mamabear: "(max-width: 1250px)";
    $bp-papabear: "(max-width: 1600px)";
  
    @if $point == papa-bear {
      @media #{$bp-papabear} { @content; }
    }
    @else if $point == mama-bear {
      @media #{$bp-mamabear} { @content; }
    }
    @else if $point == baby-bear {
      @media #{$bp-babybear}  { @content; }
    }
  }
}

您不会在 @mixin 之外声明该变量。您将从 @import 所有部分文件的“主”文件中声明它。因此,也许您的 style.scss 文件是

$MQs: true;

@import "variables";
@import "colors";
@import "global";
/* etc. */

并且您可以通过创建 style-NoMQs.scss 来创建“无媒体查询”版本 (style-NoMQs.css)

$MQs: false;

@import "variables";
@import "colors";
@import "global";
/* etc. */

只需将该变量更改为 false,输出的 CSS 将完全不包含任何媒体查询。

非常感谢 Cat Farman 在她的 Cognition 文章 回退到级联 中写下了这个想法,并略微修改了将支持变量传递给 @mixin 本身。(这样更安全吗?)

最后,我了解到许多人不喜欢 Sass 在最终输出中输出重复的媒体查询的方式,只将媒体查询“冒泡”到嵌套的底部。为了尊重选择器的源顺序特异性(据我了解),这是必要的。我个人从未担心过这个问题,因为我始终使用启用了 GZip 的方式提供资源,而 GZip 可以将重复的文本作为早餐,它不会改变文件大小太多。更不用说浏览器毫无问题地快速浏览并应用这些规则。但是,如果您仍然不喜欢这样(或者我错了),则有一个 Grunt 插件 可以解决这个问题。

其他方法