分享个人 Full-Stack JavaScript 项目开发经验
网上已有不少 Sass 的快速入门教程,中文官网也有很详尽的介绍。本文旨在用简洁的语言,整理出 Sass 的主要功能,顺便带出一些注意问题。只要熟练这些的基本功能,便可在实际应用上作延申。
了解有关 Sass 编译环境的介绍,可以参阅:
下面说明例子均基于 Sass 的 SCSS 语法格式,CSS 语法在 SCSS 中通用。
.container {
p {
color: #337ab7;
// 1、允许属性嵌套,但不常用,一般使用 CSS 属性值的缩略写法。
border: #666 {
width: 1px;
style: solid;
}
}
// 2、编译时,& 会被替换成上一层的父选择器,它必须作为选择器的第一个字符!
&-black {
color: #333;
}
// 3、@media 最终会被编译到最外层。
@media (max-width: 430px) {
line-height: 32px;
// 4、@at-root 指令可使规则跳出当前指令,或直接置于文档最外层。
@at-root (without: media) {
.warn {
color: red;
}
}
}
}
编译结果如下:
.container p {
color: #337ab7;
border: #666;
border-width: 1px;
border-style: solid;
}
.container-black {
color: #333;
}
@media (max-width: 430px) {
.container {
line-height: 32px;
}
}
.container .warn {
color: red;
}
// 1、$ 开头,赋值方式跟 CSS 属性写法一样
// 2、受块级作用域约束
// 3、先声明后使用
// 4、使用 !default 声明变量默认值时,如果变量先前没有被赋值,则此时被赋值为默认值
$var_name: 4em;
$var_name: 3em !default;
a {
// 变量值后添加 !global 可把其提升为全局变量,谨慎使用,尽量统一定义
$var_global: 2em !global;
font-size: $var_name;
}
// 插值语句 #{}
// 使用情形:
// 1、在选择器或属性名中使用变量
// 2、给有引号的字符串插入动态值(被插入的那部分值将被编译为无引号字符串)
// 3、可以用来确保 / 不被当作除法运算
p {
$prefix: "alert";
$path: "../data/";
.#{$prefix}-span {
color: #333;
background-image: url("#{$path}example.png");
}
}
编译结果如下:
a {
font-size: 4em;
}
p .alert-span {
color: #333;
background-image: url("../data/example.png");
}
对于 UI 框架项目中的变量,建议使用 _variables.scss 对组件元素值、色彩风格、页面布局标准值等进行统一定义。
SassScript 支持的数据类型有:
运算符种类包括:算术运算符(+, -, *, /, %),关系运算符(<, >, <=, >=, ==, !=)。另外,字符串可以使用 + 连接,或者使用 #{} 插入值。
对于无意义的、单位不可相互转换的运算,sass 在编译时会报错而终止。
以下情况下,@import 仅作为普通的 CSS 语句:
除以上情况,sass 会尝试找到 .scss 或 .sass 文件并导入(可省略扩展名)。
在 sass 中,@import 指令还可以同时导入多个文件,路径以逗号分隔;在 url() 方式中也可通过 #{} 使用变量;嵌套在其它选择器中。
最终,所有导入的文件会合并编译到同一个 CSS 文件中。若果不想被导入的文件被单独编译成一个 css,可以在文件名前添加 _ ,如 _header.scss,导入方式不变,即:
@import "header";
值得一提,@import 指令是构建 UI 框架时的模块化、组件化的基础。
延申指令可以在一个元素使用到另一个元素中的样式时,避免重复的编写。这可以很好地帮助我们处理通用样式和特殊样式的关系。
即同一个选择器可以延申多个选择器。
.size {
width: 10px;
}
.color {
color: #333;
}
.btn {
// 后面延申的样式享有更高优先级
@extend .size;
@extend .color;
}
即选择器的延申具有链式关系。
.btn {
width: 100px;
height: 28px;
}
.btn-normal {
@extend .btn;
padding: 10px;
}
.btn-alert {
@extend .btn-normal;
color: red;
}
这可以使只在延申中使用的选择器不被编译到 css 文件中。
// btn 的样式不会被编译到 css 文件中
%btn {
width: 10px;
height: 10px;
}
.btn-alert {
@extend %btn;
}
sass 中用于流程控制的指令。
.container {
$var: 1;
// 1、条件控制
@if $var > 1 {
color: red;
} @else if $var == 1 {
color: blue;
} @else {
color: black;
}
// 2、循环控制
@for $i from 0 through 3 {
// [0, 3]
.through-#{$i} {
font-size: 12px + $i;
}
}
@for $i from 0 to 3 {
// [0, 3)
.to-#{$i} {
font-size: 12px + $i;
}
}
$i: 0;
@while $i < 3 {
.while-#{$i} {
font-size: 12px + $i;
}
// 注意控制循环初始值、终止条件和递增!
$i: $i + 1;
}
// 3、遍历数组,支持一元和二元数组
@each $color, $font-size in ((red 12px), (blue 13px)) {
.p-#{$color} {
color: $color;
font-size: $font-size;
}
}
// 4、遍历 maps
@each $key, $value in (h1: 2em, h2: 1.5em) {
#{$key} {
font-size: $value;
}
}
}
@mixin 指令用于定义可复用的一组样式。它可以接收参数,同样需要先定义后使用。
// 1、不接收参数的混合
@mixin clearfix {
&:before,
&:after {
content: " ";
display: table;
}
&:after {
clear: both;
}
}
// 2、接收参数的混合。注意,可选(带有默认值的)参数要求放在必须参数后面!
@mixin button-size($padding-vertical, $padding-horizontal, $font-size, $line-height: 36px, $border-radius: 3px) {
padding: $padding-vertical $padding-horizontal;
font-size: $font-size;
line-height: $line-height;
border-radius: $border-radius;
}
// 3、不确定参数数量的混合
@mixin button-border($border...) {
border: $border;
}
// 4、类似于 React 组件合成方式的混合,混合内还包含其它选择器
@mixin p-compose {
p {
@content;
}
}
// 调用方式
section {
@include clearfix;
.btn {
@include button-size(5px, 5px, 12px);
@include button-border(1px solid #ccc);
}
@include p-compose {
a {
color: #337ab7;
}
}
}
混合中变量的优先级同样遵循局部变量 > 全局变量的原则。
混合在架构上的良好实践是围绕组件和实用样式进行划分,然后通过 _mixins.scss 统一导入:
sass/
├── mixins/
├ ├── _组件1.scss
├ ├── _组件2.scss
├ ├── ......
├ ├── _实用样式1.scss
├ ├── _实用样式2.scss
├ └── .....
└── _mixins.scss
函数指令用于返回特定的运算结果,可在属性值和 SassScript 中调用,参数规则跟混合一样。
// 定义
@function btn-max-width($width, $padding) {
@return $width - $padding*2;
}
// 调用
.btn {
max-width: btn-max-width(100px, 10px);
}
了解更多官网教程,请点击这里。