@规则
在原生 CSS 中,存在一些 @ 开头的规则,例如 @import、@media,Sass 对这些 @ 规则完全支持,不仅支持,还在原有的基础上做了一些扩展。
@import
在原生的 CSS 里面,@import 是导入其他的 CSS 文件,Sass 再此基础上做了一些增强:
-
编译时合并:Sass 在编译时将导入的文件内容合并到生成的 CSS 文件中,这意味着只会生成一个 CSS 文件,而不是像原生 CSS 那样需要额外的 HTTP 请求去加载导入的文件。
-
变量、函数和混合体共享:Sass 允许在导入的文件之间共享变量、函数和混合体,这有助于组织代码并避免重复。
-
部分文件:Sass 支持将文件名前缀为 _ 的文件称为部分文件(partials)。当使用 @import 指令导入部分文件时,Sass 不会生成一个单独的 CSS 文件,而是将其内容合并到主文件中。这有助于更好地组织项目。
-
文件扩展名可选:在 Sass 中,使用 @import 指令时可以省略文件扩展名(.scss 或 .sass),Sass 会自动识别并导入正确的文件。
-
嵌套导入:Sass 允许在一个文件中嵌套导入其他文件,但请注意,嵌套导入的文件将在父级上下文中编译,这可能会导致输出的 CSS 文件中的选择器层级不符合预期。
接下来,我们来看一个具体的例子:
src/
├── _variable.scss
├── _mixins.scss
├── _header.scss
└── index.scss
// _variable.scss
$primary-color: #007bff;
$secondary-color: #6c757d;
// _mixins.scss
@mixin reset-margin-padding {
margin: 0;
padding: 0;
}
// _header.scss
header {
background-color: $primary-color;
color: $secondary-color;
@include reset-margin-padding;
}
可以看出,在 _header.scss 里面使用了另外两个 scss 所定义的变量以及混合体,说明变量、函数和混合体是可以共享的。
之后我们在 index.scss 里面导入了这三个 scss
@import "variable";
@import "mixins";
@import "header";
body{
background-color: $primary-color;
color: $secondary-color;
@include reset-margin-padding;
}
最终生成的 css 如下:
header {
background-color: #007bff;
color: #6c757d;
margin: 0;
padding: 0;
}
body {
background-color: #007bff;
color: #6c757d;
margin: 0;
padding: 0;
}
最终只会生成一个 css。
通常情况下,我们在通过 @import 导入文件的时候,不给后缀名,会自动的寻找 sass 文件并将其导入。但是有一些情况下,会编译为普通的 CSS 语句,并不会导入任何文件:
- 文件拓展名是 .css;
- 文件名以 http:// 开头;
- 文件名是 url();
- @import 包含 media queries。
例如:
@import "foo.css"
@import "foo" screen;
@import "http://foo.com/bar";
@import url(foo);
@media
这个规则在原生 CSS 里面是做媒体查询,Sass 里面是完全支持的,并且做了一些增强操作。
- Sass里面允许你讲 @media 嵌套在选择器内部
.navigation {
display: flex;
justify-content: flex-end;
@media (max-width: 768px) {
flex-direction: column;
}
}
.navigation {
display: flex;
justify-content: flex-end;
}
@media (max-width: 768px) {
.navigation {
flex-direction: column;
}
}
- 允许使用变量
$mobile-breakpoint: 768px;
.navigation {
display: flex;
justify-content: flex-end;
@media (max-width: $mobile-breakpoint) {
flex-direction: column;
}
}
.navigation {
display: flex;
justify-content: flex-end;
}
@media (max-width: 768px) {
.navigation {
flex-direction: column;
}
}
- 可以使用混合体
@mixin respond-to($breakpoint) {
@if $breakpoint == "mobile" {
@media (max-width: 768px) {
@content;
}
} @else if $breakpoint == "tablet" {
@media (min-width: 769px) and (max-width: 1024px) {
@content;
}
} @else if $breakpoint == "desktop" {
@media (min-width: 1025px) {
@content;
}
}
}
.container{
width: 80%;
@include respond-to("mobile"){
width: 100%;
}
@include respond-to("desktop"){
width: 70%;
}
}
.container {
width: 80%;
}
@media (max-width: 768px) {
.container {
width: 100%;
}
}
@media (min-width: 1025px) {
.container {
width: 70%;
}
}
@extend
我们在书写 CSS 样式的时候,经常会遇到一种情况:一个元素使用的样式和另外一个元素基本相同,但是又增加了一些额外的样式。这个时候就可以使用继承。Sass里面提供了@extend规则来实现继承,让一个选择器能够继承另外一个选择器的样式规则。
.button {
display: inline-block;
padding: 20px;
background-color: red;
color: white;
}
.primary-button{
@extend .button;
background-color: blue;
}
.button, .primary-button {
display: inline-block;
padding: 20px;
background-color: red;
color: white;
}
.primary-button {
background-color: blue;
}
如果是刚接触的同学,可能会觉得 @extend 和 @mixin 比较相似,感觉都是把公共的样式提取出来了,但是两者其实是不同的。
- 参数支持:@mixin 支持传递参数,使其更具灵活性;而 @extend 不支持参数传递。
- 生成的 CSS:@extend 会将选择器合并,生成更紧凑的 CSS,并且所继承的样式在最终生成的 CSS 样式中也是真实存在的;而 @mixin 会在每个 @include 处生成完整的 CSS 代码,做的就是一个简单的 CSS 替换。
- 使用场景:@extend 更适用于继承已有样式的情况,例如 UI 框架中的通用样式;而 @mixin 更适用于需要自定义参数的情况,例如为不同组件生成类似的样式。
接下来我们来看一个复杂的例子:
.box {
border: 1px #f00;
background-color: #fdd;
}
.container {
@extend .box;
border-width: 3px;
}
.box.a{
background-image: url("/image/abc.png");
}
.box, .container {
border: 1px #f00;
background-color: #fdd;
}
.container {
border-width: 3px;
}
.box.a, .a.container {
background-image: url("/image/abc.png");
}
在上面的代码中,container 是继承了 box 里面的所有样式,假设一个元素需要有 box 和 a 这两个类才能对应一段样式(abc),由于 box 类所对应的样式,如果是挂 container 这个类的话,这些样式也会有,所以一个元素如果挂了 container 和 a 这两个类,同样应该应用对应 abc 样式。
有些时候,我们需要定义一套用于继承的样式,不希望 Sass 单独编译输出,那么这种情况下就可以使用 % 作为占位符。
%button {
display: inline-block;
padding: 20px;
background-color: red;
color: white;
}
.primary-button{
@extend %button;
background-color: blue;
}
.secondary-button{
@extend %button;
background-color: pink;
}
.secondary-button, .primary-button {
display: inline-block;
padding: 20px;
background-color: red;
color: white;
}
.primary-button {
background-color: blue;
}
.secondary-button {
background-color: pink;
}
@at-root
有些时候,我们可能会涉及到将嵌套规则移动到根级别(声明的时候并没有写在根级别)。这个时候就可以使用 @at-root
.parent{
color: red;
@at-root .child{
color: blue;
}
}
.parent {
color: red;
}
.child {
color: blue;
}
如果你想要移动的是一组规则,这个时候需要在 @at-root 后面添加一对大括号,将想要移动的这一组样式放入到大括号里面
.parent {
color: red;
@at-root {
.child {
color: blue;
}
.test {
color: pink;
}
.test2 {
color: purple;
}
}
}
.parent {
color: red;
}
.child {
color: blue;
}
.test {
color: pink;
}
.test2 {
color: purple;
}
@debug、@warn、@error
这三个规则是和调试相关的,可以让我们在编译过程中输出一条信息,有助于调试和诊断代码中的问题。