Marinerer / store

转载 && 收藏 && 乱七八糟 :clap:
65 stars 10 forks source link

【SASS】笔记 #12

Open Marinerer opened 6 years ago

Marinerer commented 6 years ago

中文文档:sass.hksasschina
参考手册:http://www.tangshuang.net/3625.html
在线编译:https://www.sassmeister.com/

嵌套

选择器嵌套和&

Sass 允许将一套 CSS 样式嵌套进另一套样式中,内层的样式将它外层的选择器作为父选择器。

嵌套功能避免了重复输入父选择器,而且令复杂的 CSS 结构更易于管理。

.flex {
  display: flex; align-items: center;
  font-size: 14px;
  // 嵌套
  footer {
    background-color: #e9e9e9;
  }
  > .header{
    font-size: 16px;
  }
  // 父选择器 &, 生成复合的选择器
  &-item {
    flex: 1;
    a {
      color: red;
      text-decoration: none;
      &:hover {
        text-decoration: underline;
      }
    }
    // 父选择器 &
    .news & {
      margin:0 16px;
    }
    .news & a, span{
      color: green;
    }
  }
}

结果

.flex { display: flex; align-items: center; font-size: 14px; }

.flex footer { background-color: #e9e9e9; }
.flex > .header { font-size: 16px; }

.flex-item { flex: 1; }
.flex-item a { color: red; text-decoration: none; }
.flex-item a:hover { text-decoration: underline; }

.news .flex-item { margin: 0 16px; }
.news .flex-item a, .flex-item span { color: green; }

属性嵌套

有些 CSS 属性遵循相同的命名空间 (namespace),比如 font-family, font-size, font-weight 都以 font 作为属性的命名空间。

body {
  font: {
    family: fantasy;
    size: 30em;
    weight: bold;
  }
}

/*********** 编译后 => */
body { font-family: fantasy; font-size: 30em; font-weight: bold; }

跳出嵌套 @at-root

sass3.3.0中新增的功能,用来跳出选择器嵌套的。默认所有的嵌套,继承所有上级选择器,但有了这个就可以跳出所有上级选择器。

普通跳出嵌套

//没有跳出
.parent-1 {
  color:#f00;
  .child1-1 {
    width:100px;
  }
}

//单个选择器跳出
.parent-2 {
  color:#f00;
  @at-root .child2-1 {
    width:200px;
  }
}

//多个选择器跳出
.parent-3 {
  background:#f00;
  @at-root {
    .child3-1 {
      width:300px;
    }
    .child3-2 {
      width:400px;
    }
  }
}

编译后:

.parent-1 { color: #f00; }
.parent-1 .child1-1 { width: 100px; }

.parent-2 { color: #f00; }
.child2-1 { width: 200px; }

.parent-3 { background: #f00; }
.child3-1 { width: 300px; }
.child3-2 { width: 400px; }

without和with

默认@at-root只会跳出选择器嵌套,而不能跳出@media@support,如果要跳出这两种,则需使用@at-root (without: media)@at-root (without: support)。这个语法的关键词有四个:all(表示所有),rule(表示常规css),media(表示media),support(表示support,因为@support目前还无法广泛使用,所以在此不表)。我们默认的@at-root其实就是@at-root (without:rule)

// 1. 跳出父级元素嵌套
@media print {
  .parent1{
    color:#f00;
    @at-root .child1 {
      width:200px;
    }
  }
}

// 2. 跳出media嵌套, 父级有效
@media print {
  .parent2{
    color:#f00;

    @at-root (without: media) {
      .child2 {
        width:200px;
      } 
    }
  }
}

// 3. 跳出media和父级
@media print {
  .parent3{
    color:#f00;

    @at-root (without: all) {
      .child3 {
        width:200px;
      } 
    }
  }
}

// 4. @at-root与 & 配合使用
.child{
  @at-root .parent &{
      color:#f00;
  }
}

// 5. @at-root应用于@keyframe
.demo {
  color: red;
  animation: motion 3s infinite;

  @at-root {
    @keyframes motion {
      from {
        opacity: 0;
      }
      to {
        opacity: 1;
      }
    }
  }
}

编译后:

/** 1. 跳出父级元素嵌套 */
@media print {
  .parent1 {
    color: #f00;
  }
  .child1 {
    width: 200px;
  }
}
/** 2. 跳出media嵌套, 父级有效 **/
@media print {
  .parent2 {
    color: #f00;
  }
}
.parent2 .child2 {
  width: 200px;
}
/** 3. 跳出media和父级 **/
@media print {
  .parent3 {
    color: #f00;
  }
}
.child3 {
  width: 200px;
}
/** 4. @at-root与 & 配合使用 **/
.parent .child {
  color: #f00;
}
/** 5. @at-root应用于@keyframe */
.demo {
  color: red;
  animation: motion 3s infinite;
}
@keyframes motion {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@import导入

Sass 拓展了 @import 的功能,允许其导入 SCSS 或 Sass 文件。被导入的文件将合并编译到同一个 CSS 文件中,另外,被导入的文件中所包含的变量或者混合指令 (mixin) 都可以在导入的文件中使用。且Sass 允许同时导入多个文件。

通常,@import 寻找 Sass 文件并将其导入,但在以下情况下,@import 仅作为普通的 CSS 语句,不会导入任何 Sass 文件。

如果不在上述情况内,文件的拓展名是 .scss.sass,则导入成功。没有指定拓展名,Sass 将会试着寻找文件名相同,拓展名为 .scss.sass 的文件并将其导入。

// 会被导入
@import "foo.scss";
@import "foo";
@import "foo", "util.scss";    // 同时导入多个文件

// 不会被导入
@import "foo.css";
@import "foo" screen;
@import "http://foo.com/bar";
@import url(foo);

分音 (Partials)

如果需要导入 SCSS 或者 Sass 文件,但又不希望将其编译为 CSS,只需要在文件名前添加下划线,这样会告诉 Sass 不要编译这些文件,但导入语句中却不需要添加下划线。

例如,将文件命名为 _colors.scss,便不会编译 _colours.css 文件。

// 导入的其实是 _colors.scss 文件
@import "colors";

嵌套

// example.scss 文件
.example {
  color: red;
}

// 导入 example.scss 文件
#main {
  @import "example";
}

/*********** 编译后 => */
#main .example {
  color: red;
}

不可以在混合指令 (mixin) 或控制指令 (control directives) 中嵌套 @import

@media

Sass 中 @media 指令允许其在 CSS 规则中嵌套。如果 @media 嵌套在 CSS 规则内,编译时,@media 将被编译到文件的最外层,包含嵌套的父选择器。

.sidebar {
  width: 300px;
  @media screen and (orientation: landscape) {
    width: 500px;
  }
}

/*********** 编译后 => */
.sidebar {
  width: 300px;
}
@media screen and (orientation: landscape) {
  .sidebar {
    width: 500px;
  }
}

@mediaqueries 允许互相嵌套使用,编译时,Sass 自动添加 and

@media screen {
  .sidebar {
    @media (orientation: landscape) {
      width: 500px;
    }
  }
}

/*********** 编译后 => */
@media screen and (orientation: landscape) {
  .sidebar {
    width: 500px;
  }
}

@media 也可以使用 SassScript(比如变量,函数,以及运算符)代替条件的名称或者值。

$media: screen;
$feature: -webkit-min-device-pixel-ratio;
$value: 1.5;

@media #{$media} and ($feature: $value) {
  .sidebar {
    width: 500px;
  }
}

/*********** 编译后 => */
@media screen and (-webkit-min-device-pixel-ratio: 1.5) {
  .sidebar {
    width: 500px;
  }
}

变量 $Variables

变量以美元符号开头,赋值方法与 CSS 属性的写法一样。

变量支持块级作用域,嵌套规则内定义的变量只能在嵌套规则内使用(局部变量),不在嵌套规则内定义的变量则可在任何地方使用(全局变量)。将局部变量转换为全局变量可以添加 !global声明。

$width: 5em;            // 全局变量,可在任何地方引用

.content {
  color: green !global;  // 局部变量转为 全局变量
}

变量定义 !default

可以在变量的结尾添加 !default 给一个未通过 !default 声明赋值的变量赋值,此时,如果变量已经被赋值,不会再被重新赋值,但是如果变量还没有被赋值,则会被赋予新的值。

变量是 null 空值时将视为未被 !default 赋值。

$content: "First content";
$content: "Second content?" !default;
$new_content: "First time reference" !default;
$non_content: null;
$non_content: "Non-null content" !default;

#main {
  content: $content;
  new-content: $new_content;
  non-content: $non_content;
}

/*********** 编译后 => */
#main {
  content: "First content";
  new-content: "First time reference";
  non-content: "Non-null content";
}

插值 #{$var}

通过 #{} 插值语句可以在选择器或属性名中使用变量。

$class: content;
$prop: color;
$value: green;
$height: 50px;
$font: 24px;

.#{$class} {
  #{$prop}: $value;
  height: #{$height};
  line-height: $height / $font;
}

/*********** 编译后 => */
.content {
  color: green;
  height: 50px;
  line-height: 2.08333;
}

数据类型

SassScript 支持 6 种主要的数据类型:

SassScript 也支持其他 CSS 属性值,比如 Unicode 字符集,或 !important 声明。然而Sass 不会特殊对待这些属性值,一律视为无引号字符串。

/** 1. 字符串
*/
$selector: '.header';

/** 2. 数组 list
* list数据可通过空格,逗号或小括号分隔多个值,可用nth($var,$index)取值。
*/
// 一维数据
$size: 12 16 18 20;
$size: 12, 16, 18, 20;
// 二维数据
$size: 5px 10px, 20px 30px;
$size: (5px 10px) (20px 30px);

body{
  margin: nth($size, 2);
}
// => body { margin: 20px 30px; }

/** 3. map
*/
$map: (key1: value1, key2: value2, key3: value3);

运算 Operations

1. 数字运算

SassScript 支持数字的加减乘除、取整等运算 (+, -, *, /, %),如果必要会在不同单位间转换值。

关系运算 <, >, <=, >= 也可用于数字运算,相等运算 ==, != 可用于所有数据类型。

p {
  width: 1in + 8pt;
}
// => p { width: 1.11111in; }

// 除法运算
p {
  font: 10px/8px;             // Plain CSS, no division
  $width: 1000px;
  width: $width/2;            // Uses a variable, does division
  width: round(1.5)/2;        // Uses a function, does division
  height: (500px/2);          // Uses parentheses, does division
  margin-left: 5px + 8px/2px; // Uses +, does division
}
// => p { font: 10px/8px; width: 500px; width: 1; height: 250px; margin-left: 9px; }

除法运算 / (Division and /)

/ 在 CSS 中通常起到分隔数字的用途,SassScript同时也赋予了 / 除法运算的功能。

以下三种情况 / 将被视为除法运算符号:

2. 颜色值运算

p {
  color: #010203 + #040506;
}
// => p { color: #050709; }

p {
  color: #010203 * 2;
}
// => p { color: #020406; }

// rgba或hsla 两种颜色值必须拥有相等的 alpha 值才能进行运算
p {
  color: rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75);
}
// => p { color: rgba(255, 255, 0, 0.75); }

// 颜色值的 alpha channel 可以通过 opacify 或 transparentize 两个函数进行调整
$translucent-red: rgba(255, 0, 0, 0.5);
p {
  color: opacify($translucent-red, 0.3);
  background-color: transparentize($translucent-red, 0.25);
}
// => p { color: rgba(255, 0, 0, 0.8); background-color: rgba(255, 0, 0, 0.25); }

3. 字符串运算

+ 可用于连接字符串

注意,如果有引号字符串(位于 + 左侧)连接无引号字符串,运算结果是有引号的,相反,无引号字符串(位于 + 左侧)连接有引号字符串,运算结果则没有引号。

font-size: 16 + px;  // => font-size: 16px;
cursor: e + -resize;  // => cursor: e-resize;

content: "Foo " + Bar;           // => content: "Foo Bar";
font-family: sans- + "serif";    // => font-family: sans-serif;

margin: 3px + 4px auto;  // => margin: 7px auto;

content: "I ate #{5 + 10} pies!";  // => content: "I ate 15 pies!";

$value: null;
content: "I ate #{$value} pies!";  // => content: "I ate pies!";

4. 布尔运算

SassScript 支持布尔的 and ornot 运算

$age: 12;
/** and 运算 */
body {
  @if ($age > 10 and $age < 25) {
    color: green;
  } @else {
    color: red;
  }
}
// => body {color: red;}

/** or 运算 */
body {
  @if ($age < 10 or $age > 25) {
    color: green;
  } @else {
    color: red;
  }
}
// => body {color: red;}

/** not 运算 */
body {
  @if ($age not 25) {
    color: green;
  } @else {
    color: red;
  }
}
// => body {color: green;}

5. 数组运算

数组不支持任何运算方式,只能使用 list functions 控制。

条件判断

@if判断

@if 的表达式返回值不是 false 或者 null 时,条件成立,输出 {} 内的代码。

p {
  @if 1 + 1 == 2 { border: 1px solid; }
  @if 5 < 3 { border: 2px dotted; }
  @if null  { border: 3px double; }
}
// => p {border: 1px solid; }

$type: monster;
p {
  @if $type == ocean {
    color: blue;
  } @else if $type == matador {
    color: red;
  } @else if $type == monster {
    color: green;
  } @else {
    color: black;
  }
}
// => p {color: green; }

三目判断

语法为:if($condition, $if_true, $if_false) 。三个参数分别表示:条件,条件为真的值,条件为假的值。

$age: 12;
body {
  font-size: if($age > 10, 10px, 20px);
}
// => body {font-size: 10px;}

循环指令

@for循环

for循环有两种形式,分别为:@for $var from <start> through <end>@for $var from <start> to <end>。 $i表示变量,start表示起始值,end表示结束值,这两个的区别是关键字through表示包括end这个数,而to则不包括end这个数。

// from ... through
@for $i from 1 through 3 {
  .item-#{$i} {
    width: 2em * $i;
  }
}

// from ... to
@for $i from 1 to 4 {
  .item-#{$i} {
    width: 2em * $i;
  }
}

编译后的结果都是一样的:

.item-1 { width: 2em; }
.item-2 { width: 4em; }
.item-3 { width: 6em; }

@each循环

语法为:@each $var in <list or map>。其中$var表示变量,而list和map表示list类型数据和map类型数据。

1. 单字段list数据循环

@each $val in 12 14 16 {
  .font-#{$val} {
      font-size: $val + px;
  }
}

// 或者

$fonts: 12, 14, 16;
@each $val in $fonts {
  .font-#{$val} {
    font-size: $val + px;
  }
}

/** 编译后: */
.font-12 { font-size: 12px; }
.font-14 { font-size: 14px; }
.font-16 { font-size: 16px; }

2. 多字段list数据循环

$icon-data: (success green), (fail, #ff0000);
@each $status, $color in $icon-data {
  .icon-#{$status} {
    color: $color;
    background: url('/path/'+ $status +'c.png');
  }
}

// 或者

@each $status, $color in success green, fail #ff0000 {
  .icon-#{$status} {
    color: $color;
    background: url('/path/'+ $status +'c.png');
  }
}

/** 编译后:*/
.icon-success {
  color: green;
  background: url("/path/successc.png");
}
.icon-fail {
  color: #ff0000;
  background: url("/path/failc.png");
}

3. 多字段map数据循环

$headers: (h1: 2em, h2: 1.5em, h3: 1.2em);
@each $tag, $size in $headers {
  #{$tag} {
    font-size: $size;
  }
}

/** 编译后:
h1 { font-size: 2em; }
h2 { font-size: 1.5em; }
h3 { font-size: 1.2em; }
*/

@while循环

混合 @mixin

混合指令(Mixin)用于定义可重复使用的样式,避免了使用无语意的 class,比如 .float-left。混合指令可以包含所有的 CSS 规则,绝大部分 Sass 规则,甚至通过参数功能引入变量,输出多样化的样式。

1. 无参数

@mixin link{
  text-decoration: underline;
  color: #ff0;
}

@mixin title {
  @include link;
  font-size: 16px;
  font-weight: bold;

  article & {
    text-align: center;
  }
}

.page-title{
  @include title;
}

编译后:

.page-title {
  text-decoration: underline;
  color: #ff0;
  font-size: 16px;
  font-weight: bold;
}

article .page-title {
  text-align: center;
}

2. 有参数

参数用于给混合指令中的样式设定变量,并且赋值使用。在定义混合指令的时候,按照变量的格式,通过逗号分隔,将参数写进圆括号里。引用指令时,按照参数的顺序,再将所赋的值对应写进括号。

@mixin opacity($opacity:50) {
  opacity: $opacity / 100;
  filter: alpha(opacity=$opacity);
}

.opacity{
  @include opacity;         //参数使用默认值
}

.opacity-80{
  @include opacity(80);     //传递参数
}

编译后:

.opacity {
  opacity: 0.5;
  filter: alpha(opacity=50);
}

.opacity-80 {
  opacity: 0.8;
  filter: alpha(opacity=80);
}

3. 多参数

混合指令也可以使用关键词参数。

@mixin line($border: 1px dashed #ccc, $padding: 10px, $font: 16px){
  border-bottom: $border;
  padding: $padding 0;
  font-size: $font;
}

.products li{
  @include line(1px solid #e9e9e9, 12px);
}

.news li{
  @include line($font: 14px, $padding: 15px);        // 关键词参数
}

编译后:

.products li {
  border-bottom: 1px solid #e9e9e9;
  padding: 12px 0;
  font-size: 16px;
}

.news li {
  border-bottom: 1px dashed #ccc;
  padding: 15px 0;
  font-size: 14px;
}

4. 多组值参数

有时,不能确定混合指令需要使用多少个参数,比如一个关于 box-shadow 的混合指令不能确定有多少个 'shadow' 会被用到。这时,可以使用参数变量 声明(写在参数的最后方)告诉 Sass 将这些参数视为值列表处理,如$variables...

@mixin box-shadow($shadows...) {
  -moz-box-shadow: $shadows;
  -webkit-box-shadow: $shadows;
  box-shadow: $shadows;
}

.shadows {
  @include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
}

// 或者
$values: 0px 4px 5px #666, 2px 6px 10px #999;
.shadows {
  @include box-shadow($values...);
}

编译后:

.shadows {
  -moz-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
  -webkit-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
  box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
}

参数变量也可以用在引用混合指令的时候 (@include),与平时用法一样,将一串值列表中的值逐条作为参数引用

@mixin colors($text, $background, $border) {
  color: $text;
  background-color: $background;
  border-color: $border;
}

@mixin item($args...) {
  margin-bottom: 10px;
  font-size: 16px;
  @include colors($args...);
}

$values: #ff0000, #00ff00, #0000ff;
.news-item {
  @include item($values...);
}

编译后:

.news-item {
  margin-bottom: 10px;
  font-size: 16px;
  color: #ff0000;
  background-color: #00ff00;
  border-color: #0000ff;
}

5. @content传递样式片段

@mixin button {  
  font-size: 1em;
  color: #fff;  
  @content;

  .cell & {            // 可以用 & 引用父选择器
    font-size: 14px;
  }
}

.button-green {  
  @include button {  
    background: green;
  }
  text-align: center;
}

编译后:

.button-green {
  font-size: 1em;
  color: #fff;
  background: green;        /* 代替@content语句 */
  text-align: center;
}

.cell .button-green {
  font-size: 14px;
}

继承 @extend

sass中,选择器继承可以让选择器继承另一个选择器的所有样式,并联合声明。使用选择器的继承,要使用关键词@extend,后面紧跟需要继承的选择器。

Class 选择器并不是唯一可以被延伸 (extend) 的,Sass 允许延伸任何定义给单个元素的选择器,比如 .special.coola:hover 或者 a.user[href^="http://"]

@extend 还可以多重延伸,继续延伸。

input[type="button"] {
  -webkit-appearance: none;
  border: 1px solid rgba(0, 0, 0, .12);
}
.button {
  @extend input[type="button"];
  display: inline-block;
  width: 120px; height: 32px;
}
.btn-{
  &primary {
    @extend .button;
    background-color: #000;
  }
  &default {
    @extend .button;
    background-color: #e9e9e9;
  }
}

编译后:

input[type="button"], .button, .btn-primary, .btn-default {
  -webkit-appearance: none;
  border: 1px solid rgba(0, 0, 0, 0.12);
}

.button, .btn-primary, .btn-default {
  display: inline-block;
  width: 120px;
  height: 32px;
}

.btn-primary {
  background-color: #000;
}
.btn-default {
  background-color: #e9e9e9;
}

缺点:

占位选择器%

占位选择器以%标识定义,通过@extend调用。

如果不调用则不会有任何多余的css文件,避免了以前在一些基础的文件中预定义了很多基础的样式,然后实际应用中不管是否使用了@extend去继承相应的样式,都会解析出来所有的样式。

$screen: 800;

%link {
  color: #f00;
  text-decoration: none;
  @if $screen > 500 {
    font-size: 14px;
  }
}

.title {
  @extend %link;
}
article .more{
  @extend %link;
  font-size: 12px;
}

编译后:

.title, article .more {
  color: #f00;
  text-decoration: none;
  font-size: 14px;
}

article .more {
  font-size: 12px;
}

函数 @function

sass定义了很多函数可供使用,当然也可以自己定义函数,以@fuction开始。 sass的官方函数链接为:sass fuction,实际项目中我们使用最多的应该是颜色函数,而颜色函数中又以lighten减淡和darken加深为最,其调用方法为lighten($color,$amount)darken($color,$amount),它们的第一个参数都是颜色值,第二个参数都是百分比。

$grid: 40px;
$gutter: 10px;

@function grid-width($n) {
  @return $n * $grid + ($n - 1) * $gutter;
}

#sidebar {
  width: grid-width(5);
}

编译后:

#sidebar {
  width: 240px;
}