Sass 入门教程介绍

发布于 2021-07-13 21:35:11 字数 11025 浏览 1610 评论 0

你是否一直想学 Sass,但却始终没有行动?你是否是Sass的使用者,但却感觉自己只是多了一个工具?那么请继续读下去,让我们一起重温 Sass 的特性和另外一些很酷的东西吧。

Sass 是什么?

Sass(Syntactically Awesome Style Sheets)是一个CSS预处理器。Sass 与 CSS 关系就像 CoffeeScript 与 JavaScript 关系。它通过添加标记到样式表中,帮助我们更轻松惬意的书写 CSS。

那么,Sass 使如何工作的?

很高兴你有此疑问,实际上有多种编译 Sass 的方法:

  • Ruby Sass二进制源码。通过 gem install sass 命令安装,然后就可以使用 running sassc myfile.scss myfile.css 来编译了。
  • 类似 HammerCodeKit 和 Compass 的 GUI 软件。
  • 我个人喜爱 libsass
  • 一个使用C语言编写且速度极快的Sass编译器。也可以通过 NPM 的 node-sassnpm install node-sass)安装 libsass。

到底应该选择哪一个呢?这取决于你所做的事。

目前我在从事大型电子商务网站代码库的维护工作,因此使用Ruby Sass编译大量源码就显得有点慢。我通常在构建系统中使用 node-sass,但是必须牢记libsass的特性并非完全与Ruby Sass相同。

如果你不是一个善于使用命令行工具的人,那么GUI软件是个不错的选择。通过安装此类软件监视.scss文件,那么当你编写它们的时候,软件将会自动编译。

如果你只是想尝鲜或者共享几段代码,非常建议使用Sassmeister。这是一款基于WEB的Sass开发平台,而我也将在本文中使用它。

.sass vs .scss?

Sass面世之初,其核心语法是明显不同于CSS的。它使用缩进代替了括号,没有分号并且操作符很短。简而言之,像极了Haml

有些人非常不喜欢这种语法格式,所以在Sass 3.0中开发者将核心语法改成了.scss。SCSS是CSS的一个超集,在与
CSS写法完全相同的基础上,还同时兼具了Sass的所有特性。

也就是说,如果你喜欢还可以使用原生语法。我个人使用.scss,并且在本文中也是使用.scss语法。

为什么使用 Sass?

问得不错。Sass让编写可维护的CSSS更加简易方便。可以用更少的代码,做更多的事,用更少的时间,具有更强的可读性。你还需要更多理由吗?

安装

废话少说,让我们开始干吧。如果你想尝鲜,下面的方法都不错:安装你选择的编译方法(软件或者命令行),同时创建 style.scss 文件。或者在 Sassmeister 上实践

变量

没错,就是变量。Sass让CSS可以使用变量。

变量类型可以是数字,字符串,颜色,null,列表和maps。

在Sass中使用$符号定义变量。让我们来创建第一个变量:

$primaryColor: #eeffcc;

如果尝试编译这个文件,你并不会在CSS中看到任何东西,但你做的都是对的。定义变量并不会输出任何CSS,它们只会被记录在当前作用域的变量集中。你需要使用一段CSS声明使用它,然后就可以看见了:

$primaryColor: #eeffcc;
body {
    background: $primaryColor;
}

提一下作用域这个坑,你知道Sass有变量作用域吧?那就对了,如果你在选择器中声明了一个变量,那么它的作用范围就是这个选择器内部。看看这个:

$primaryColor: #eeccff;
body {
  $primaryColor: #ccc;
  background: $primaryColor; //编译后#ccc
}
p {
  color: $primaryColor; //编译后#eeccff
}

但如果我们想在选择器中声明一个全局变量可如何是好?Sass提供了一个!global标识符来实现这一功能:

$primaryColor: #eeccff;
body {
  $primaryColor: #ccc !global;
  background: $primaryColor; //编译后#ccc
}
p {
  color: $primaryColor; //编译后#ccc
}

另一个很有用的标识符是!default——特别是编写混合宏时。这确保了我们在触发事件时,即使未传递参数,变量也会有默认的值。如果传递了参数,那么该参数就会覆盖默认值:

$firstValue: 62.5%;
$firstValue: 24px !default;
body {
    font-size: $firstValue; //编译后62.5%;
}

通过下面几个关于变量的例子,看看你编写的 Sass 是如何编译成 CSS 的:

在 SassMeister 上练习

数学计算

与 CSS 不同,Sass 允许使用数学表达式!这对于混合宏非常有用,是我们能够使用自己的标记做一些很酷的事情。

支持的操作符包括:

  • 加:+
  • 减:-
  • 除:/
  • 乘:*
  • 取余:%
  • 相等:==
  • 不相等:!=

在继续之前,我要提醒两个Sass有关于数学计算的“陷阱”。

第一,因为 / 符号用来简写CSS字体属性,比如 font: 14px/16px,所以如果你想在非变量值上使用除法操作符,那么你需要使用括号包裹它们:

$fontDiff: (14px/16px);

第二,不可以混合使用值的单位:

$container-width: 100% - 20px;

上面这个例子行不通。相反,对于这个特殊的例子你可以使用calc函数——它可以在渲染时解释执行。

回到数学计算上来,让我们基于基础的容器宽度创建一个动态列声明:

$container-width: 100%;
.container {
  width: $container-width;
}
.col-4 {
  width: $container-width / 4;
}
//  Compiles to:
//  .container {
//   width: 100%;
//  }
//
//  .col-4 {
//      width: 25%;
//  }

非常棒,对不对?尝试下面的代码,看看我们是如何进一步使用 Sass 的数学计算增加 margin 值。

在SassMeister上练习

函数

在我看来,Sass最好的一点就是它的内建函数。可以在 这里 查看完整的函数列表。内容非常广泛。

你是否想创建一个非常酷的按钮,然后在调色板上花费了很多时间,以尝试为阴影部分找到正确的色调?

尝试 darken() 函数吧。你可以传递给它一个颜色和比例,稍等一会,就会使你的颜色变暗了。看看这个例子就知道为什么它很酷了:

在SassMeister上练习

嵌套

Sass 中一个很有用又经常被误用的特性,就是嵌套声明。能力越大责任越大,所以让我们花费点时间了解它都做了什么,另一方面,也看看它做了什么坏事。

基础的嵌套指在一个声明内实现另一个声明的能力。通常在CSS中,我们会这么写:

.container {
    width: 100%;
}
.container h1 {
    color: red;
}

但在Sass中,我们可以通过如下写法获得相同代码:

.container {
    width: 100%;
    h1 {
        color: red;
    }
}

这太疯狂了!那么如果我们想引用父选择器又该怎么办呢?可以通过使用&符号实现。看看我们是如何利用这个方式给伪选择器添加链接属性的吧:

a.myAnchor {
    color: blue;
    &:hover {
        text-decoration: underline;
    }
    &:visited {
        color: purple;
    }
}

现在已经知道怎样嵌套了,但是如果想离开嵌套回到顶层选择器,那么我们可以使用@at-root指令。比如我们有一个这样的嵌套:

.first-component {
    .text { font-size: 1.4rem; }
    .button { font-size: 1.7rem; }
    .second-component {
        .text { font-size: 1.2rem; }
        .button { font-size: 1.4rem; }
    }
}

当意识到第二个组件可能会被用作他处,那我们就有麻烦了。实际上,这并不完全对。@at-root可以解决这个问题:

在SassMeister上练习

很酷对不对?嵌套是节省时间和提高可读性的窍门,但是过度嵌套则会制造过度选择和文件大小的问题。思考你的Sass编译结果并尝试遵循“inception rule”。

Inception Rule:选择器深度不要超过四层。——thesassway

如果可能,嵌套不要超过四层。不过即使你必须嵌套五层,Hampton Catlin也不会去你家和你理论的。尽量不要这样做。

Imports

开始Sass中我又一个喜爱的部分吧。imports允许将总的样式分割成小文件,并在另一个文件中导入。这对于组织方式和编写速度来说是神奇的。

我们可以使用@import指令导入.scss文件:

@import "grids.scss";

实际上,你都不需要写扩展名:

@import "grids";

Sass编译器还有一个“partials”的概念。如果.sass.scss文件名有一个下划线前缀,那么它就不会被编译成CSS。如果你的文件只是被引用到主体样式style.scss中而并不需要编译,这个特性就会很有用。

扩展和占位符

在Sass中,@extend 指令是继承既有样式的标准方式。

让我们使用@extend指令扩展一个input样式——指向input-error类:

.input {
  border-radius: 3px;
  border: 4px solid #ddd;
  color: #555;
  font-size: 17px;
  padding: 10px 20px;
  display: inline-block;
  outline: 0;
}
.error-input {
  @extend .input;
  border:4px solid #e74c3c;
}

请注意,这么做并不会从.input复制样式到.error-input中。看看这个例子中编译后的CSS样式,理解Sass是如何智能处理的吧:

在SassMeister上练习

但如果我们想声明的扩展来自尚未实现的样式集,那该如何做呢?占位符选择器就可以解决这个问题。

%input-style {
    font-size: 14px;
}
input {
    @extend %input-style;
    color: black;
}

声明占位符选择器需要在目标类名上前缀一个%符号。只有当扩展它的元素被渲染时,占位符选择器才会被编译输出。

看看下面了解上一个例子使用占位符是怎样编译的:

在SassMeister上练习

混合宏

混合宏是Sass令人惊艳的特性,因为它在让你实现类似@extend功能的同时还提供了传参的功能。

Sass使用@mixin指令定义混合宏,并使用@include指令引入。让我们构建一个简单的混合宏实现媒体查询吧。

第一步是定义混合宏:

@mixin media($queryString){
  //
}

注意我们在混合宏media中声明了一个$queryString参数。当我们引入混合宏时,可以一个字符串参数以实现动态渲染。勇敢试一下吧:

@mixin media($queryString){
    @media #{$queryString} {
      @content;
    }
}

因为我们期待字符串参数被目标函数使用,所以使用了Sass的插值语法,#{}。当你传递变量到这个括号中时,变量会像字符串一样输出而不是进行某种逻辑运算。

这个例子中另一个生疏的地方是@content指令。当你使用的混合宏后接被大括号包裹的样式,那么被包裹样式就可以通过@content指令加以使用。

最后,让我们使用混合宏和@include指令试一下吧:

.container {
    width: 900px;
    @include media("(max-width: 767px)"){
        width: 100%;
    }
}

看看下面这个演示,了解我们新的混合宏是怎样渲染媒体查询的吧:

在SassMeister上练习

函数指令

在Sass中,函数指令类似于混合宏,它们会通过@return指令返回值而不是返回样式。这可以降低代码中的重复率并提高可读性。

让我们创建一个函数指令以清除grid例子中的grid运算式:

@function getColumnWidth($width, $columns,$margin){
    @return ($width / $columns) - ($margin * 2);
}

现在就可以在代码中使用这个函数了:

$container-width: 100%;
$column-count: 4;
$margin: 1%;
.container {
  width: $container-width;
}
.column {
  background: #1abc9c;
  height: 200px;
  display: block;
  float: left;
  width: getColumnWidth($container-width,$column-count,$margin);
  margin: 0 $margin;
}

很有范儿对不对?

演示

现在我们已经可以使用这些工具,那我们怎样构建自己配置的栅格框架呢?继续看:

让我们从创建一个setings map开始:

$settings: (
    maxWidth: 800px,
    columns: 12,
    margin: 15px,
    breakpoints: (
        xs: "(max-width : 480px)",
        sm: "(max-width : 768px) and (min-width: 481px)",
        md: "(max-width : 1024px)  and (min-width: 769px)",
        lg: "(min-width : 1025px)"
    )
);

记下来创建一个混合宏渲染我们的框架:

@mixin renderGridStyles($settings){
//
}

继而,我们需要渲染每个断点处的样式,所以遍历所有断点并调用媒体查询的混合宏。我们可以使用map-get方法获取断点值,同时使用@each指令遍历所有断点:

@mixin renderGridStyles($settings){
  $breakpoints: map-get($settings, "breakpoints");
  @each $key, $breakpoint in $breakpoints {
    @include media($breakpoint) {
      //
    }
  }
}

我们需要在迭代器内部实现具体栅格的样式渲染,所以创建一个renderGrid混合宏。使用map-get方法获得map值,并使用@while指令迭代以$i作为索引的列。我们使用插值作为类名。

@mixin renderGrid($key, $settings) {
  $i: 1;
  @while $i <= map-get($settings, "columns") {
    .col-#{$key}-#{$i} {
      float: left;
      width: 100% * $i / map-get($settings,"columns");
    }
    $i: $i+1;
  }
}

接下来,添加容器和列的样式:

.container {
    padding-right: map-get($settings, "margin");
    padding-left: map-get($settings, "margin");
    margin-right: auto;
    margin-left: auto;
}
.row {
    margin-right: map-get($settings, "margin") * -1;
    margin-left: map-get($settings, "margin") * -1;
}

大功告成!看看下面关于我们框架的演示吧:

在SassMeister上练习

总结

可能你已经掌握了这些知识并认为这就是Sass了,其实不然,这些只是冰山一角。Sass是一款非常强大的工具,可以帮助我们处理非同凡响的设计。期望各位继续阅读具有精妙思想的文章,直到达到 Happy Sassing 境界,资源如下:

  • The Sass Way – A phenomenal source of Sass tutorials.
  • Hugo Giraudel – An amazing tech writer & Sass wizard with a keen focus on Sass.
  • SassNews – A twitter account managed by Stuart Robson that will keep you in the know.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

虐人心

有一天你能到我的心里去,你会看到那里全是你给的伤悲。

文章
评论
24518 人气
更多

推荐作者

夢野间

文章 0 评论 0

doggiejohn

文章 0 评论 0

就此别过

文章 0 评论 0

初见终念

文章 0 评论 0

qq_rvKjBH

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文