Sass 速学
什么是 Sass
Sass 可帮助我们更高效地编写 CSS 样式,同时为 CSS 提供了像编程语言一样的变量、流程控制、函数、嵌套和继承等特性。但是浏览器无法直接渲染 Sass 文件,我们必须要先将 Sass 编译(转换)为 CSS 后,才可以被浏览器识别。
- Sass(Syntactically Awesome StyleSheets),顾名思义就是支持很棒语法的样式表
- Sass 又称为 CSS 的预处理器或扩展
- Sass 可为我们提供 CSS 没有的功能
- Sass(.scss)文件需要被编译为正常的 CSS 文件
一般我们会通过以下几种方式来编译 Sass:
npm install -g sass
,然后通过命令行执行编译:sass input.scss output.css
:将input.scss
编译为output.css
sass --watch input.scss output.css
:监控input.scss
的更改,在保存时,实时编译为output.css
sass --watch scss:dist/css
:监控scss
目录中的更改,实时编译 CSS 到dist/css
目录--no-source-map
:不生成.css.map
文件--style=compressed
:删除尽可能多的多余字符,并将整个样式表写在一行上
- 通过类似
gulp.js
这样的自动化构建工具来管理编译工作流 - 在 VS Code 中使用
Live Sass Compiler
插件来即时编译
.scss vs .sass
Sass 支持两种不同的语法:
- SCSS 语法,对应文件扩展名
.scss
。SCSS 是 CSS 的超集,即意味着基本上所有有效的 CSS 也是有效的 SCSS - Sass 语法,它是 Sass 的原始缩进语法,所以对应文件扩展名
.sass
。缩进语法支持与 SCSS 相同的所有功能,但是它使用缩进代替大括号和分号来描述文档的格式
主流上都是使用 SCSS 语法,即文件扩展名为
.scss
。
比如对以下 .scss
和 .sass
文件,最终编译得到的结果都是相同的。
.scss
示例代码:
$primary-color: #333; body { font: 100% $font-stack; color: $primary-color; }
.sass
示例代码:
$font-stack: Helvetica, sans-serif $primary-color: #333 body font: 100% $font-stack color: $primary-color
以上两个文件的编译结果都是:
body { font: 100% Helvetica, sans-serif; color: #333; }
变量
Sass 视以 $
开头的东西为变量:
$primary-color: lightblue; body { background-color: $primary-color; }
编译输出 CSS:
body { background-color: #add8e6; }
嵌套
Sass 中可嵌套 CSS 选择器,从而达到和 HTML 一样的视觉层次:
nav { ul { list-style: none; } li { display: inline-block; } a { text-decoration: none; } }
编译输出 CSS:
nav ul { list-style: none; } nav li { display: inline-block; } nav a { text-decoration: none; }
模块
- Sass 将以
_
开头的文件作为部分文件,从而编写出模块化 CSS - 下划线让 Sass 知道该文件只是一个部分文件,不应该生成一个 CSS 文件
- Sass 部分文件与
@use
规则一起使用
部分文件 _base.scss
:
$primary-color: lightblue; $font-color: red; body { background-color: $primary-color; }
将 _base.scss
作为模块引入,并以 base
作为该模块的命名空间:
@use 'base'; h1 { color: base.$font-color; }
编译后的 CSS:
body { background-color: lightblue; } h1 { color: red; }
混合
Sass 允许我们创建一组可重用的 CSS 声明块。
比如我们以前经常会为了兼容各个浏览器,而写各种重复且繁杂的浏览器厂商前缀。有了 Sass 后,我们就可以避免这种情况的发生,比如:
@mixin transform($property) { -webkit-transform: $property; -ms-transform: $property; transform: $property; } .box { width: 200px; height: 100px; border: 1px solid red; @include transform(rotate(30deg)); }
编译后的 CSS:
.box { width: 200px; height: 100px; border: 1px solid red; -webkit-transform: rotate(30deg); -ms-transform: rotate(30deg); transform: rotate(30deg); }
继承
Sass 允许我们使用 @extend
从一个选择器到另一个选择器共享一组 CSS 属性:
/* This CSS will print because %message-shared is extended. */ %message-shared { border: 1px solid #ccc; padding: 10px; color: #333; } // This CSS won't print because %equal-heights is never extended. %equal-heights { display: flex; flex-wrap: wrap; } .message { @extend %message-shared; } .success { @extend %message-shared; border-color: green; } .error { @extend %message-shared; border-color: red; } .warning { @extend %message-shared; border-color: yellow; }
编译后的 CSS:
/* This CSS will print because %message-shared is extended. */ .warning, .error, .success, .message { border: 1px solid #ccc; padding: 10px; color: #333; } .success { border-color: green; } .error { border-color: red; } .warning { border-color: yellow; }
运算
Sass 支持标准数学运算符,比如 +
、 -
、 *
、 /
和 %
:
.container { width: 100%; } article.main { border: 1px solid red; float: left; width: 600px / 960px * 100%; } aside.complementary { border: 1px solid blue; float: right; width: 300px / 960px * 100%; }
编译后的 CSS:
.container { width: 100%; } article.main { border: 1px solid red; float: left; width: 62.5%; } aside.complementary { border: 1px solid blue; float: right; width: 31.25%; }
条件判断
Sass 支持使用 @if
、 @else
和 @else if
来进行条件判断:
@mixin triangle($size, $color, $direction) { height: 0; width: 0; border-color: transparent; border-style: solid; border-width: $size / 2; @if $direction == up { border-bottom-color: $color; } @else if $direction == right { border-left-color: $color; } @else if $direction == down { border-top-color: $color; } @else if $direction == left { border-right-color: $color; } @else { @error "Unknown direction #{$direction}."; } } .next { @include triangle(5px, black, right); }
编译后的 CSS:
.next { height: 0; width: 0; border-color: transparent; border-style: solid; border-width: 2.5px; border-left-color: black; }
Demo
项目目录结构:
. ├── dist │ └── css │ └── style.css ├── home.png ├── index.html └── sass ├── _buttons.scss ├── _config.scss ├── _mobile.scss ├── _utilities.scss └── style.scss
index.html
源码为:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Learn Sass</title> <link rel="stylesheet" href="dist/css/style.css" /> </head> <body> <header class="showcase"> <div class="container"> <nav> <h1 class="logo">My Website</h1> <ul> <li><a href="#">Home</a></li> <li><a href="#">About</a></li> <li><a href="#">Services</a></li> </ul> </nav> <div class="showcase-content"> <div> <h1>Make Your Marketing Real</h1> <p class="my-1"> Lorem ipsum, dolor sit amet consectetur adipisicing elit. Velit, veniam nesciunt modi quasi, adipisci natus commodi assumenda similique quis iusto consequatur. Cupiditate maiores esse autem aspernatur dignissimos, quas asperiores adipisci? </p> <a href="#" class="btn-primary">Learn More</a> <a href="" class="btn-secondary">Sign Up</a> </div> <img src="./home.png" alt="" /> </div> </div> </header> </body> </html>
style.scss
源码为:
@use 'config'; @use 'utilities'; @use 'buttons'; @use 'mobile'; * { box-sizing: border-box; margin: 0; padding: 0; } body { background-color: config.$light-color; line-height: 1.6; } img { width: 100%; } a { text-decoration: none; } .showcase { @include config.set-background(config.$primary-color); height: 600px; nav { display: flex; align-items: center; justify-content: space-between; ul { display: flex; list-style: none; } li { padding: 15px; } a { color: config.set-text-color(config.$primary-color); } a:hover { color: config.$secondary-color; } } &-content { height: 100%; display: flex; align-items: center; justify-content: center; margin-top: 30px; img { width: 50%; } h1 { font-size: 50px; line-height: 1.2; } } }
_config.scss
源码为:
$font-stack: Arial, Helvetica, sans-serif; $light-color: #f4f4f4; $primary-color: #0e6cff; // $primary-color: #e0ffff; $secondary-color: #ff8700; // Set text color based on background color @function set-text-color($color) { @if (lightness($color) > 70) { @return #333; } @else { @return #fff; } } // Set background & text color @mixin set-background($color) { background-color: $color; color: set-text-color($color); }
_utilities.scss
源码为:
.container { max-width: 1100px; padding: 0 30px; margin: 0 auto; overflow: auto; } // Margin & padding classes $spacemounts: (1, 2, 3, 4, 5); @each $space in $spacemounts { .m-#{$space} { margin: #{$space}rem; } .my-#{$space} { margin: #{$space}rem 0; } .p-#{$space} { padding: #{$space}rem; } .py-#{$space} { padding: #{$space}rem 0; } }
_buttons.scss
源码为:
@use 'config'; %btn { display: inline-block; border-radius: 5px; padding: 8px 20px; margin: 3px; &:hover { transform: scale(0.98); } } .btn-primary { @extend %btn; @include config.set-background(lighten(config.$primary-color, 10%)); } .btn-secondary { @extend %btn; @include config.set-background(config.$secondary-color); }
_mobile.scss
源码为:
@media (max-width: 700px) { .showcase { height: 400px; &-content { text-align: center; img { display: none; } } } }
编译结果 style.css
源码为:
.container{max-width:1100px;padding:0 30px;margin:0 auto;overflow:auto}
.m-1{margin:1rem}.my-1{margin:1rem 0}.p-1{padding:1rem}.py-1{padding:1rem 0}
.m-2{margin:2rem}.my-2{margin:2rem 0}.p-2{padding:2rem}.py-2{padding:2rem 0}
.m-3{margin:3rem}.my-3{margin:3rem 0}.p-3{padding:3rem}.py-3{padding:3rem 0}
.m-4{margin:4rem}.my-4{margin:4rem 0}.p-4{padding:4rem}.py-4{padding:4rem 0}
.m-5{margin:5rem}.my-5{margin:5rem 0}.p-5{padding:5rem}.py-5{padding:5rem 0}
.btn-secondary,.btn-primary{display:inline-block;border-radius:5px;padding:8px 20px;margin:3px}
.btn-secondary:hover,.btn-primary:hover{transform:scale(0.98)}
.btn-primary{background-color:#418bff;color:#fff}.btn-secondary{background-color:#ff8700;color:#fff}
@media(max-width: 700px){.showcase{height:400px}.showcase-content{text-align:center}
.showcase-content img{display:none}}*{box-sizing:border-box;margin:0;padding:0}
body{background-color:#f4f4f4;line-height:1.6}img{width:100%}a{text-decoration:none}
.showcase{background-color:#0e6cff;color:#fff;height:600px}
.showcase nav{display:flex;align-items:center;justify-content:space-between}
.showcase nav ul{display:flex;list-style:none}.showcase nav li{padding:15px}
.showcase nav a{color:#fff}.showcase nav a:hover{color:#ff8700}
.showcase-content{height:100%;display:flex;align-items:center;justify-content:center;margin-top:30px}
.showcase-content img{width:50%}.showcase-content h1{font-size:50px;line-height:1.2}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论