Sass基础教程-3 数据类型 操作符

2021-05-05
css
约 5417 字 预计阅读 11 分钟

本篇介绍sass的数据类型, 函数functions, 和操作符operators, 任何一个语言都有基本的数据类型,操作符,方法或者函数,sass给css带来的新特性里

自然少不了它们.

本篇主要介绍Sass里的数据类型和操作符,基本的数据类型有数字,字符串,colors,列表,字典,boolean,null和函数引用

1. 数据类型

Sass里的基本数据类型有如下

  • Numbers

  • Strings

  • Colors

  • Lists

  • Maps

  • boolean

  • null

  • function 函数引用(get-function()获取, 用call()调用)

1.1. Numbers数值

像素,英尺,浮点数等等都算是数字类型,css支持的单位sass都支持

1
2
3
4
5
6
7
@debug 100; // 100
@debug 0.8; // 0.8
@debug 16px; // 16px
@debug 5px * 2px; // 10px*px (read "square pixels")

@debug 5.2e3; // 5200
@debug 6e-2; // 0.06

1.1.1. 不同的单位

同单位和不同单位可以相乘和相除, 分子是原来被除数的单位,分母是除数的单位

1
2
3
4
5
6
7
8
9
@debug 4px * 6px; // 24px*px (read "square pixels")
@debug math.div(5px, 2s); // 2.5px/s (read "pixels per second")

// 3.125px*deg/s*em (read "pixel-degrees per second-em")
@debug 5px * math.div(math.div(30deg, 2s), 24em); 

$degrees-per-second: math.div(20deg, 1s);
@debug $degrees-per-second; // 20deg/s
@debug math.div(1, $degrees-per-second); // 0.05s/deg

不同领域的单位不能相加减

1
2
3
4
5
6
// CSS defines one inch as 96 pixels.
@debug 1in + 6px; // 102px or 1.0625in

@debug 1in + 1s;
//     ^^^^^^^^
// Error: Incompatible units s and in.

像下面这样用速度(每像素所需事件) x 距离,可以得到总时间

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16

$transition-speed: math.div(1s, 50px);

@mixin move($left-start, $left-stop) {
  position: absolute;
  left: $left-start;
  transition: left ($left-stop - $left-start) * $transition-speed;

  &:hover {
    left: $left-stop;
  }
}

.slider {
  @include move(10px, 120px);
}

输出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11


.slider {
  position: absolute;
  left: 10px;
  transition: left 2.2s;
}
.slider:hover {
  left: 120px;
}

1.1.2. 注意事项

在创建数字变量的时候,尽量直接带上单位,不要出现差值这样的定义方式,比如#{$number}px,这会被解释成一个字符串,

应该直接定义成$num1 = 20px 或者 $num1 = $num2 * 1px

sass里50%0.5一个是百分比,一个是数值,两者完全不同.

math.div($percentage, 100%)可以返回小数, 相反的$decimal * 100%会得到一个百分比数.

1.1.3. 精度

sass支持小数点后面10位, 所以使用的时候注意:

  • sass只会取前10位, 编译后也只会保留小数点后10位
  • 比较操作符会比较也是基于小数点后10位
  • 一个数字和整数的差距比0.0000000001小, 当做需要整数参数的函数实参的时候,就被认为是整数, 比如3.00000000009

1.2. String字符串

在sass里带引号的和不带引号的一些字面量, 比如颜色名称, 粗细等等都算字符串

Sass: sass:string (sass-lang.com)里提供了一些常用的字符串工具函数,比如下面的加引号和去引号

1
2
3
4
@use "sass:string";

@debug string.unquote(".widget:hover"); // .widget:hover
@debug string.quote(bold); // "bold"

1.2.1. Escape转义

和大部分语言一样.\可以用来转义特殊字符串, 引号,unicode字符串(16进制),换行符, .等等

1
2
3
4
5
@debug "\""; // '"'
@debug \.widget; // \.widget
@debug "\a"; // "\a" (a string containing only a newline)
@debug "line1\a line2"; // "line1\a line2"
@debug "Nat + Liz \1F46D"; // "Nat + Liz 👭"

1.2.2. Quoted带引号的

  • \a 代表新行,换行
  • 单双引号前面加\
  • \可以用\\表示
1
2
3
4
5
6
7
@debug "Helvetica Neue"; // "Helvetica Neue"
@debug "C:\\Program Files"; // "C:\\Program Files"
@debug "\"Don't Fear the Reaper\""; // "\"Don't Fear the Reaper\""
@debug "line1\a line2"; // "line1\a line2"

$roboto-variant: "Mono";
@debug "Roboto #{$roboto-variant}"; // "Roboto Mono"

1.2.3. Unquoted不带引号的

一般就是一些字面量,标识符等等, 一般都是以-或者--开始

1
2
3
4
5
6
@debug bold; // bold
@debug -webkit-flex; // -webkit-flex
@debug --123; // --123

$prefix: ms;
@debug -#{$prefix}-flex; // -ms-flex
  • boolean值, true 和false不是
  • 颜色名称不是
  • null不是
  • not or and是boolean 操作符,也不算

1.3. Colors颜色

颜色比较简单,一些字面量和函数 hsl, rgb, rgba, hsla 等等都支持为颜色类型

1
2
3
4
5
6
7
@debug #f2ece4; // #f2ece4
@debug #b37399aa; // rgba(179, 115, 153, 67%)
@debug midnightblue; // #191970
@debug rgb(204, 102, 153); // #c69
@debug rgba(107, 113, 127, 0.8); // rgba(107, 113, 127, 0.8)
@debug hsl(228, 7%, 86%); // #dadbdf
@debug hsla(20, 20%, 85%, 0.7); // rgb(225, 215, 210, 0.7)

Sass提供了很多颜色函数,可以做颜色的变化,深浅等等效果, 参考Sass: sass:color (sass-lang.com)

1.4. Lists

List包含一组相同类型的值,可以用逗号分隔,也可以用空格分隔,或者/, 并且不需要特殊的括号,任何被上述逗号,或者空格分隔的表达式都是List

当然如果有特殊需要,比如css里的grid-template-columns(grid-template-columns - CSS: Cascading Style Sheets | MDN (mozilla.org)),可以写成css的[linename2 linename3]

1.4.1. Slash分隔的Lists

比如font的大小,行高可以这样font: 12px/30px, 或者一个hsl的颜色可以这样hsl(80 100% 50% / 0.5), 尽管如此,

尽量不要使用/来分隔list,因为过去/表示除法,现在用math.div(),如果需要用slash分隔list,用list.slash()

1.4.2. 按索引取值

list.nth($list, $n) function

1
2
@debug list.nth(10px 12px 16px, 2); // 12px
@debug list.nth([line1, line2, line3], -1); // line3

1.4.3. 迭代

@each rule

1
2
3
4
5
6
7
8
9
$sizes: 40px, 50px, 80px;

@each $size in $sizes {
  .icon-#{$size} {
    font-size: $size;
    height: $size;
    width: $size;
  }
}

1.4.4. 添加

list.append($list, $val) function

1
2
@debug append(10px 12px 16px, 25px); // 10px 12px 16px 25px
@debug append([col1-line1], col1-line2); // [col1-line1, col1-line2]

注意:sass里的list是不可变的,添加产生的是一个新的变量

1.4.5. 查找

获取索引 list.index($list, $value) function

1
2
3
@debug list.index(1px solid red, 1px); // 1
@debug list.index(1px solid red, solid); // 2
@debug list.index(1px solid red, dashed); // null

如果不存在,就返回的是null

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@use "sass:list";

$valid-sides: top, bottom, left, right;

@mixin attach($side) {
  @if not list.index($valid-sides, $side) {
    @error "#{$side} is not a valid side. Expected one of #{$valid-sides}.";
  }

  // ...
}

1.4.6. 不可变

虽然不可变,但是原始变量标识符是可以重新赋值的,所以如果有编辑list的操作,一定要重新赋值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@use "sass:list";
@use "sass:map";

$prefixes-by-browser: ("firefox": moz, "safari": webkit, "ie": ms);

@function prefixes-for-browsers($browsers) {
  $prefixes: ();
  @each $browser in $browsers {
    $prefixes: list.append($prefixes, map.get($prefixes-by-browser, $browser));
  }
  @return $prefixes;
}

@debug prefixes-for-browsers("firefox" "ie"); // moz ms

1.4.7. 参数里的list

前面的篇章里关于@mixin里有讲到,我们可以通过将key的列表取出,来进一步获取参数中的每一个key,value

如下面的例子,利用meta.keywords函数将可变参数键值对进行解构,这里有个细节,就是在已知数量的情况下,可以命名参数并解构,在上一篇@each的章节里有详细介绍

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
@use "sass:meta";

@mixin syntax-colors($args...) {
  @debug meta.keywords($args);
  // (string: #080, comment: #800, variable: #60b)

  @each $name, $color in meta.keywords($args) {
    pre span.stx-#{$name} {
      color: $color;
    }
  }
}

@include syntax-colors(
  $string: #080,
  $comment: #800,
  $variable: #60b,
)

1.5. Maps

键值对,形式为(<expression>: <expression>, <expression>: <expression>)

  • 必须用()
  • 空的时候写成()

list和map有相同之处,他们的实现中有关联,比如(1:2, 3:4)其实在list里表现为(1 2, 3 4)

1.5.1. 获取value

map.get($map, $key) function

1
2
3
4
$font-weights: ("regular": 400, "medium": 500, "bold": 700);

@debug map.get($font-weights, "medium"); // 500
@debug map.get($font-weights, "extra-bold"); // null

1.5.2. 迭代

同样用@each可以用于循环map

1
2
3
4
5
6
7
8
9
$icons: ("eye": "\f112", "start": "\f12e", "stop": "\f12f");

@each $name, $glyph in $icons {
  .icon-#{$name}:before {
    display: inline-block;
    font-family: "Icon Font";
    content: $glyph;
  }
}

1.5.3. 添加

map.set($map, $key, $value) function

1
2
3
4
5
6
7
8
@use "sass:map";

$font-weights: ("regular": 400, "medium": 500, "bold": 700);

@debug map.set($font-weights, "extra-bold", 900);
// ("regular": 400, "medium": 500, "bold": 700, "extra-bold": 900)
@debug map.set($font-weights, "bold", 900);
// ("regular": 400, "medium": 500, "bold": 900)

1.5.4. 合并

1
2
3
4
5
6
7
@use "sass:map";

$light-weights: ("lightest": 100, "light": 300);
$heavy-weights: ("medium": 500, "bold": 700);

@debug map.merge($light-weights, $heavy-weights);
// ("lightest": 100, "light": 300, "medium": 500, "bold": 700)

合并时, 相同的key会被后者替换

1
2
3
4
5
6
@use "sass:map";

$weights: ("light": 300, "medium": 500);

@debug map.merge($weights, ("medium": 700));
// ("light": 300, "medium": 700)

1.5.5. 不可变

同样map也是不可变的,更新,添加,合并都会产生新的map

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@use "sass:map"

$prefixes-by-browser: ("firefox": moz, "safari": webkit, "ie": ms)

@mixin add-browser-prefix($browser, $prefix)
  $prefixes-by-browser: map.merge($prefixes-by-browser, ($browser: $prefix)) !global


@include add-browser-prefix("opera", o)
@debug $prefixes-by-browser
// ("firefox": moz, "safari": webkit, "ie": ms, "opera": o)

1.5.6. 注意事项

尽量不要用没有引号的值做key

1.6. null空值

null是空值类型的唯一值,通常也作为参数返回,表示没有任何值

1
2
3
4
5
6
@use "sass:map";
@use "sass:string";

@debug string.index("Helvetica Neue", "Roboto"); // null
@debug map.get(("large": 20px), "small"); // null
@debug &; // null

null在编译css的时候,通常被忽略掉

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$fonts: ("serif": "Helvetica Neue", "monospace": "Consolas");

h3 {
  font: 18px bold map-get($fonts, "sans");
}

// 得到
h3 {
  font: 18px bold;
}

属性的值如果为null,编译时,整个属性会被忽略

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
$fonts: ("serif": "Helvetica Neue", "monospace": "Consolas");

h3 {
  font: {
    size: 18px;
    weight: bold;
    family: map-get($fonts, "sans");
  }
}
// 生成
h3 {
  font-size: 18px;
  font-weight: bold;
}

null是假性的, 只有false和null是假性, 其它任何值,空字符串,0,空list和空map等等都是true,这是sass和别的语言不一样的地方

1.7. ture and flase

和其它语言一样,boolean类型可以用来比较,可以用来判断如>=之类的关系正确性, 也可以作为一些方法如math.comparable()map.has-key()的返回值

1
2
3
4
5
6
@use "sass:math";

@debug 1px == 2px; // false
@debug 1px == 1px; // true
@debug 10px < 3px; // false
@debug math.comparable(100px, 3in); // true

注意:在sass里, 只有false和null为假, 其它的都是真,包括空字符串和0,这一点和大部分语言都不一样

1.7.1. 操作符

and or not

1
2
3
4
5
6
7
8
@debug true and true; // true
@debug true and false; // false

@debug true or false; // true
@debug false or false; // false

@debug not true; // false
@debug not false; // true

1.7.2. 一些使用方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
@mixin avatar($size, $circle: false) {
  width: $size;
  height: $size;

  @if $circle {
    border-radius: $size / 2;
  }
}

.square-av {
  @include avatar(100px, $circle: false);
}
.circle-av {
  @include avatar(100px, $circle: true);
}

if有一种特殊用法,可以返回值, 如果true返回第二个参数,如果false返回第三个参数

1
2
@debug if(true, 10px, 30px); // 10px
@debug if(false, 10px, 30px); // 30px

1.8. function

函数类型的值是比较特殊的值,在一些脚本语言,和真正面向对象的语言里非常常见, 函数在编译后也会有引用,所以函数也可以作为值来进行逻辑处理

因为函数 也是值,所以同样可以放到maps和lists里

可以通过meta.get-function()来获取函数引用, 然后用 meta.call()来调用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@use "sass:list";
@use "sass:meta";
@use "sass:string";

/// Return a copy of $list with all elements for which $condition returns `true`
/// removed.
@function remove-where($list, $condition) {
  $new-list: ();
  $separator: list.separator($list);
  @each $element in $list {
    @if not meta.call($condition, $element) {
      $new-list: list.append($new-list, $element, $separator: $separator);
    }
  }
  @return $new-list;
}

$fonts: Tahoma, Geneva, "Helvetica Neue", Helvetica, Arial, sans-serif;

content {
  @function contains-helvetica($string) {
    @return string.index($string, "Helvetica");
  }
  font-family: remove-where($fonts, meta.get-function("contains-helvetica"));
}

2. 操作符

2.1. 简介

sass遵循标准的操作符优先级顺序,参考Order of operations - Wikipedia

  1. 一元操作符 not, +, -, and /.
  2. The *, /, and % operators.
  3. The + and - operators.
  4. The >, >=, < and <= operators.
  5. The == and != operators.
  6. The and operator.
  7. The or operator.
  8. The = operator, when it’s available.

所以这里就不做介绍了,有任何一门语言基础的应该都能理解

2.2. Equality 比较

  • 数值
  • 字符串
  • 颜色
  • list
  • map
  • boolean
  • 函数引用
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@debug 1px == 1px; // true
@debug 1px != 1em; // true
@debug 1 != 1px; // true
@debug 96px == 1in; // true

@debug "Helvetica" == Helvetica; // true
@debug "Helvetica" != "Arial"; // true

@debug hsl(34, 35%, 92.1%) == #f2ece4; // true
@debug rgba(179, 115, 153, 0.5) != rgba(179, 115, 153, 0.8); // true

@debug (5px 7px 10px) == (5px 7px 10px); // true
@debug (5px 7px 10px) != (10px 14px 20px); // true
@debug (5px 7px 10px) != (5px, 7px, 10px); // true
@debug (5px 7px 10px) != [5px 7px 10px]; // true

$theme: ("venus": #998099, "nebula": #d2e1dd);
@debug $theme == ("venus": #998099, "nebula": #d2e1dd); // true
@debug $theme != ("venus": #998099, "iron": #dadbdf); // true

@debug true == true; // true
@debug true != false; // true
@debug null != false; // true

@debug get-function("rgba") == get-function("rgba"); // true
@debug get-function("rgba") != get-function("hsla"); // true

2.3. Relational 大小关系

1
2
3
4
@debug 100 > 50; // true
@debug 10px < 17px; // true
@debug 96px >= 1in; // true
@debug 1000ms <= 1s; // true

自动单位转换

1
2
@debug 100 > 50px; // true
@debug 10px < 17; // true

不可比较的单位会报错

2.4. Numeric 数值计算

  • +
  • -
  • *
  • 取摸 %

2.4.1. 单位转换

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@debug 10s + 15s; // 25s
@debug 1in - 10px; // 0.8958333333in
@debug 5px * 3px; // 15px*px
@debug 1in % 9px; // 0.0625in

// 自动识别
@debug 100px + 50; // 150px
@debug 4s * 10; // 40s

// 无法转换的会报错
@debug 100px + 10s;
//     ^^^^^^^^^^^
// Error: Incompatible units px and s.

2.4.2. 一元操作符

紧跟-或者+, +不变, -为负数

  1. - as part of an identifier. The only exception are units; Sass normally allows any valid identifier to be used as an identifier, but units may not contain a hyphen followed by a digit.
  2. - 表达式之间没有空格,被视为减法
  3. - 加上一个数字开头,被视为是一个负数
  4. - 两个数字之前,不考虑空格,被视为减法
  5. - 在非数字之前,被视为一元否定

2.4.3. Division除法

在sass里非常特殊,/通常有别的用途,比如分隔符, 用 math.div()来表示除法

注意下面的一些特殊情况

  • 任何表达式都不是数值类型
  • 结果存储在变量中或者作为返回值
  • 被括号直接包裹
  • 结果作为计算的另一个组成部分
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
@use "sass:list";

@debug 15px / 30px; // 15px/30px
@debug (10px + 5px) / 30px; // 0.5
@debug list.slash(10px + 5px, 30px); // 15px/30px

$result: 15px / 30px;
@debug $result; // 0.5

@function fifteen-divided-by-thirty() {
  @return 15px / 30px;
}
@debug fifteen-divided-by-thirty(); // 0.5

@debug (15px/30px); // 0.5
@debug (bold 15px/30px sans-serif); // bold 15px/30px sans-serif
@debug 15px/30px + 1; // 1.5

如果明确是分隔符,sass:listslash

1
@debug list.slash(10px + 5px, 30px); // 15px/30px

2.4.4. 单位

单位可以相同,可以不通, 除法的时候, 一般都可以将数值和时间作为任意一边的表达式

1
2
3
4
5
6
7
8
9
@debug 4px * 6px; // 24px*px (read "square pixels")
@debug math.div(5px, 2s); // 2.5px/s (read "pixels per second")

// 3.125px*deg/s*em (read "pixel-degrees per second-em")
@debug 5px * math.div(math.div(30deg, 2s), 24em); 

$degrees-per-second: math.div(20deg, 1s);
@debug $degrees-per-second; // 20deg/s
@debug math.div(1, $degrees-per-second); // 0.05s/deg

如果分子分母是兼容单位,那么单位就可以换算并抵消

做了一个实验

1
2
3
4
@use "sass:math";

@debug math.div(96px, 1in)
// DEBUG: 1

2.4.5. 补充下css的单位

参考:

绝对单位

Unit Description
cm centimeters
mm millimeters
in 英寸inches (1in = 96px = 2.54cm)
px * 像素pixels (1px = 1/96th of 1in)
pt 点points (1pt = 1/72 of 1in)
pc 派卡picas (1pc = 12 pt)

相对单位

Unit Description
em Relative to the font-size of the element (2em means 2 times the size of the current font)
ex Relative to the x-height of the current font (rarely used)
ch Relative to the width of the “0” (zero)
rem Relative to font-size of the root element
vw Relative to 1% of the width of the viewport*
vh Relative to 1% of the height of the viewport*
vmin Relative to 1% of viewport’s* smaller dimension
vmax Relative to 1% of viewport’s* larger dimension
% Relative to the parent element

2.4.6. 注意事项

-很多字面量标识符和字符串会用到,所以特殊场景不一定是减号

1
2
3
4
5
6
7
8
@debug a-1; // a-1
@debug 5px-3px; // 2px
@debug 5-3; // 2
@debug 1 -2 3; // 1 -2 3

$number: 2;
@debug 1 -$number 3; // -1 3
@debug 1 (-$number) 3; // 1 -2 3

尽量在定义的时候不要用差值来表示数值单位, 直接在变量定义的时候带上单位,前面也有提到过,参考2.1.2. 注意事项

2.5. String 字符串操作符

2.5.1. 字符串连接

  • + 将两个字符串连接
  • - 将两个字符串用-连接
1
2
3
@debug "Helvetica" + " Neue"; // "Helvetica Neue"
@debug sans- + serif; // sans-serif
@debug sans - serif; // sans-serif

如果有其它类型值和字符串进行操作,同样也是连接操作

1
2
@debug "Elapsed time: " + 10s; // "Elapsed time: 10s";
@debug true + " is a boolean value"; // "true is a boolean value";

2.5.2. 一元操作符

  • /<expression> 返回一个没有引号的字符串,以/开头
  • -<expression> 返回一个没有引号的字符串,以-开头
1
2
@debug / 15px; // /15px
@debug - moz; // -moz

2.6. Boolean 布尔操作符

特殊一点,不是用符号,是用下面的关键字

  • not <expression> 取反
  • <expression> and <expression> 都为true则是true, 有一个false就返回false
  • <expression> or <expression> 有一个true返回true, 两个false就返回false
1
2
3
4
5
6
7
8
@debug not true; // false
@debug not false; // true

@debug true and true; // true
@debug true and false; // false

@debug true or false; // true
@debug false or false; // false

任何可以使用boolean类型的地方,都可以用其它值类型代替,

上一篇也说过除了falsenull,其它任何都为true,包括0, 空字符串

TAG: sass scss css web
文章作者 : Cocding