@import

Sass 扩展了 CSS 的 @import 规则,能够导入 Sass 和 CSS 样式表,提供对 mixins、函数和变量的访问,并将多个样式表的 CSS 组合在一起。与普通的 CSS 导入不同,后者要求浏览器在呈现页面时发出多个 HTTP 请求,Sass 导入完全在编译期间处理。

SASS 导入与 CSS 导入具有相同的语法,只是它们允许多个导入用逗号分隔,而不是要求每个导入都有自己的 @import 。此外,在缩进语法中,导入的 URL 不需要有引号。

@forward "<url>"

<url> 是加载模块地址。但它使加载的模块中的公共成员,对您的模块的用户可用,就好像它们直接在您的模块中定义一样。但是,这些成员不能被外直接调用,需要 @use 来加载你的模块。别担心,它们只会加载一次模块!


⚠️注意!
Sass 团队不鼓励继续使用该 @import 规则。Sass 将在接下来的几年中逐步淘汰它,并最终将其从语言中完全删除。更喜欢 @use 规则。(请注意,目前只有 Dart Sass 支持 @use 。其他实现的用户必须使用该 @import 规则。)

@import 规则有许多严重的问题:
  • @import 使所有变量、mixin 和函数都可以全局访问。这使得人们(或工具)很难分辨出任何东西是在哪里定义的。
  • 因为一切都是全局的,所以库必须为其所有成员添加前缀以避免命名冲突。
  • @extend 规则也是全局的,这使得很难预测哪些样式规则会被扩展。
  • 每个样式表都会执行 @import ,并且每次编辑时都会发出其 CSS,这会增加编译时间并产生臃肿的输出。
  • 无法定义下游样式表,无法访问的私有成员或占位符选择器。
新的模块系统和@use规则解决了所有这些问题。

我如何迁移?
请使用 迁移工具 ,它可以自动将大多数基于 @import 代码,快速转换为基于代码的 @use 的代码。只需将其指向您的入口点并让它运行!


scss 语法 css 语法
// foundation/_code.scss
code {
  padding: .25em;
  line-height: 0;
}
// foundation/_lists.scss
ul, ol {
  text-align: left;

  & & {
    padding: {
      bottom: 0;
      left: 0;
    }
  }
}
// style.scss
@import 'foundation/code', 'foundation/lists';
code {
  padding: .25em;
  line-height: 0;
}

ul, ol {
  text-align: left;
}
ul ul, ol ol {
  padding-bottom: 0;
  padding-left: 0;
}

当 Sass 导入一个文件时,该文件被评估,就像其内容直接出现在 @import 的位置一样。导入文件中的任何mixin、函数和变量都是可用的,它的所有CSS都包含在 @import 的编写位置。此外,在 @import 之前定义的任何混合、函数或变量(包括来自其他 @import 的)都可以在导入的样式表中使用。

⚠️注意!
如果多次导入同一个样式表,则每次都会再次对其进行评估。如果它只是定义函数和 mixins,这通常没什么大不了的,但如果它包含样式规则,它们将被多次编译为 CSS 。


查找文件

为您导入的每个样式表写出绝对 URL 不会很有趣,因此 Sass 查找要导入的文件的算法使其变得更容易一些。对于初学者,您不必明确写出要导入的文件的扩展名; @import "variables" 将自动加载,variables.scss,variables.sass 或 variables.css。

为了确保样式表适用于每个操作系统,Sass 通过 URL 导入文件,而不是通过文件路径。这意味着您需要使用正斜杠,而不是反斜杠,即使在 Windows 上也是如此。

加载路径

所有 Sass 实现都允许用户提供加载路径:Sass 在解析导入时将查看的文件系统上的路径。例如,如果您 node_modules/susy/sass 作为加载路径传递,则可以使用 @import "susy" to load node_modules/susy/sass/susy.scss

不过,导入将始终首先相对于当前文件进行解析。仅当不存在与导入匹配的相对文件时才会使用加载路径。这可确保您在添加新库时不会意外地弄乱您的相关导入。

与其他一些语言不同,Sass 不要求您使用./相对导入。相对导入始终可用。


Partials

按照惯例,仅用于导入而不是自行编译的 Sass 文件以 _ 开头(如: _code.scss)。这些被称为 partials,它们告诉 Sass 工具不要尝试自己编译这些文件。您可以在导入部分时省略 _

scss 语法 css 语法
// foundation/_code.scss
code {
  padding: .25em;
  line-height: 0;
}
// foundation/_lists.scss
ul, ol {
  text-align: left;

  & & {
    padding: {
      bottom: 0;
      left: 0;
    }
  }
}
// foundation/_index.scss
@import 'code', 'lists';
// style.scss
@import 'foundation';
code {
  padding: .25em;
  line-height: 0;
}

ul, ol {
  text-align: left;
}
ul ul, ol ol {
  padding-bottom: 0;
  padding-left: 0;
}


自定义导入器

所有 Sass 实现都提供了一种定义自定义导入器的方法,它控制如何 @import 定位样式表:

  • npm 上的 Node Sass和 Dart Sass提供了一个 importer 选项,作为其JS API 的一部分。
  • pub 上的 Dart Sass 提供了一个可以由自定义导入器扩展的抽象 Importer 类。
  • Ruby Sass提供了一个可以由自定义导入器扩展的抽象 Importers::Base 类。


嵌套

导入通常写在样式表的顶层,但并非必须如此。它们也可以嵌套在样式规则或纯 CSS 规则中。导入的 CSS 嵌套在该上下文中,这使得嵌套导入对于将一大块 CSS 限定为特定元素或媒体查询很有用。请注意,嵌套导入中定义的顶级 mixins、functions和variables 仍然是定义的全局。

scss 语法 css 语法
// _theme.scss
pre, code {
  font-family: 'Source Code Pro', Helvetica, Arial;
  border-radius: 4px;
}
// foundation/_index.scss
@import 'code', 'lists';
// style.scss
.theme-sample {
  @import "theme";
}
.theme-sample pre, .theme-sample code {
  font-family: 'Source Code Pro', Helvetica, Arial;
  border-radius: 4px;
}

嵌套导入对于确定第三方样式表的范围非常有用,但如果您是您要导入的样式表的作者,那么将样式写入mixin并将该 mixin 包含在嵌套上下文中通常是一个更好的主意。可以以更灵活的方式使用 mixin,并且在查看导入的样式表时会更清楚地了解它的用途。

嵌套导入中的 CSS 像 mixin 一样被评估,这意味着任何父选择器都将引用嵌套样式表的选择器。

scss 语法 css 语法
// _theme.scss
ul li {
  $padding: 16px;
  padding-left: $padding;
  [dir=rtl] & {
    padding: {
      left: 0;
      right: $padding;
    }
  }
}
// style.scss
.theme-sample {
  @import "theme";
}
.theme-sample ul li {
  padding-left: 16px;
}
[dir=rtl] .theme-sample ul li {
  padding-left: 0;
  padding-right: 16px;
}


导入 CSS

除了导入 .sass .scss 文件,Sass 还可以导入普通的 .css 文件。唯一的规则是导入不能显式包含 .css 扩展名,因为那是用来表示 @import 的纯 CSS。

scss 语法 css 语法
// code.css
code {
  padding: .25em;
  line-height: 0;
}
// style.scss
@import 'code';
code {
  padding: .25em;
  line-height: 0;
}

SASS 导入的 CSS 文件不允许任何特殊的 Sass 功能。为了确保作者不会在他们的 CSS 中意外编写 Sass ,所有不是有效 CSS 的 Sass 功能都会产生错误。否则,CSS 将按原样呈现。它甚至可以扩展!


导入纯CSS

因为在 CSS 中,也定义有 @import ,所以 Sass 需要一种 @import 编译纯 CSS 的方法,而不是在编译时尝试导入文件。为了实现这一点,并确保 SCSS 尽可能多地成为 CSS 的超集,Sass 会将 @import 具有以下特征的,编译为纯 CSS 导入:

  • 导入 URL 以 .css 结尾。
  • 导入 URL 开始的位置是 http:// https://
  • 导入 URL 写为 url()
  • 具有媒体查询的导入。
scss 语法 css 语法
@import "theme.css";
@import "http://fonts.googleapis.com/css?family=Droid+Sans";
@import "landscape" screen and (orientation: landscape);
@import url(theme);
@import url(theme.css);
@import "http://fonts.googleapis.com/css?family=Droid+Sans";
@import "landscape" screen and (orientation: landscape);
@import url(theme);


插值

尽管 Sass 导入不能使用插值(以确保始终可以分辨 mixins、functions 和 variables 的来源),但导入纯 CSS 可以。这使得动态生成导入成为可能,例如基于 mixin 参数。

scss 语法 css 语法
@mixin google-font($family) {
  @import url("http://fonts.googleapis.com/css?family=#{$family}");
}

@include google-font("Droid Sans");
@import url("http://fonts.googleapis.com/css?family=Droid Sans");


导入和模块

Sass 的模块系统与 @import 无缝集成,无论您是导入包含 @use 规则的文件,还是加载包含导入作为模块的文件。我们希望从 @import 到的过渡 @use 尽可能顺利。

导入模块系统文件

当您导入包含 @use 规则的文件时,导入文件可以访问直接在该文件中定义的所有成员(甚至是私有成员),但不能访问该文件加载的模块中的任何成员。但是,如果该文件包含 @forward 规则,则导入文件将有权访问转载的成员。这意味着您可以导入为与模块系统一起使用而编写的库。

⚠️注意!
当一个带有 @use 规则的文件被导入时,所有被这些规则加载的 CSS 都包含在结果样式表中,即使它已经被另一个导入包含了。如果你不小心,这可能会导致 CSS 输出臃肿!


仅导入文件

@use 有意义的 API,可能对 @import 没有意义。例如,在默认情况下, @use 为所有成员添加了一个命名空间,因此您可以安全地使用短名称,但 @import 不这样做,您可能需要更长的名称。如果您是库作者,您可能会担心,如果您更新库以使用新的模块系统,您现有的基于 @import 的用户将崩溃。

为了简化此过程,Sass 还支持仅导入文件。如果你给一个文件 <name>.import.scss ,它将仅为导入而加载,不用于 @uses 。通过这种方式,您可以保留 @import 用户的兼容性,同时仍然为新模块系统的用户提供良好的 API。

// _reset.scss
// Module system users write `@include reset.list()`.
@mixin list() {
  ul {
    margin: 0;
    padding: 0;
    list-style: none;
  }
}

// _reset.import.scss
// Legacy import users can keep writing `@include reset-list()`.
@forward "reset" as reset-*;


通过导入配置模块

在首次 @import 加载该模块之前,您可以通过定义全局变量,来配置通过 @import 加载的模块。

scss 语法 css 语法
// _library.scss
$color: blue !default;

a {
  color: $color;
}
// _library.import.scss
@forward 'library' as lib-*;
// style.sass
$lib-color: green;
@import "library";
a {
  color: green;
}
⚠️注意!
模块只加载一次,因此如果您 @import 在第一次(甚至是间接地)更改模块后更改配置,如果您 @import 再次使用模块,更改将被忽略。


加载包含导入的模块

当您使用 @use (或 @forward )加载一个使用 @import 的模块时,该模块将包含您加载的样式表定义的所有公共成员以及样式表可传递导入的所有内容。换句话说,导入的所有内容都被视为编写在一个大样式表中。

这使得在样式表中使用 @use ,这也使得转换为新的模块系统,变得很容易。但是,请注意,如果他们确实转换了API,那么他们的API很可能会发生变化!