Sass 速学

发布于 2024-11-13 03:46:34 字数 11503 浏览 7 评论 0

什么是 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 技术交流群。

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

发布评论

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

关于作者

世界等同你

暂无简介

0 文章
0 评论
23 人气
更多

推荐作者

一梦浮鱼

文章 0 评论 0

mb_Z9jVigFL

文章 0 评论 0

伴随着你

文章 0 评论 0

耳钉梦

文章 0 评论 0

18618447101

文章 0 评论 0

蜗牛

文章 0 评论 0

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