Sass (Dart) knowledge required for Vue component library

Time:2022-11-25

foreword

There are three versions of SassDart SasslibsassandRuby Sass

  • Dart Sass:useDartwritten in languagesassImplementation, the alpha version was released on November 1, 2016, and the modular mechanism is fully supported after version 1.23.0.
  • libSassalso known asnode-sass, implemented in c/c++sassversion, widely used, wherenode-sassis boundlibsassofnodejslibrary, which can be very quickly.scssfile compiled as.cssfile, the installation process is very slow, and the official does not recommend using it anymore.
  • Ruby Sassis the originalSassimplementation, but it was stopped on March 26, 2019, and will no longer be supported in the future. Users need to migrate to other implementations

SassThe official team is also officially announced in October 2020Libsasswill be deprecated, and based on itNode SassandSassC, and users are advised to useDart Sass, there are mainly the following points:

  • It is no longer recommended toLibSassfor newSassproject, use theDart Sass
  • suggest existingLibSassUsers make plans to eventually migrate toDart Sass, and allSassKudu makes plans and eventually abandons theLibSasssupport.
  • no longer plan toLibSassAdd any new features, including newCSSCompatibility of features.
  • LibSassandNode SassIt will be maintained indefinitely on a best effort basis, including fixing major bugs and security issues and compatibility with the latest Node versions.

Why use Dart Sass

Currently Dart Sass is already the latest version of Sass, when executingnpm install sass -DBy default, the Dart Sass package is used,vue-cliViteScaffolding also uses the latest version of Dart sass by default, and does not need to be installednode-sass[Previous installation of node-sass often failed]

in addition,element-plusThe component library also uses the dart dass modulesass:mapand@useRefactored all SCSS variables to resolve issues caused by@importThe duplicate output problem caused.

So, to getsassProvide more and more powerful functions, it is strongly recommended to usedart sass

installation and use

If previously installednode-sass, you can first uninstall

npm uninstall node-sass

install dart-sass

npm install sass [email protected]^10.1.1 -D

NOTE: Before installingsass-loaderversion is13.0+, the version is too high to cause an error, promptingTypeError: this.getOptions is not a function,return10.+can run successfully

If the project previously used/deep/needs to be replaced with::v-deep, a global search/deep/, put the project in/deep/replace with::v-deep

SCSS variables

scssVariable Naming Rules

  • with dollar sign$at the beginning, followed by the variable name; and must be defined first, then used
  • Variable names cannot start withnumber starts with, can contain letters, numbers, underscores, dashes (connectors)
  • through connectors-with underscore_A variable with the same name is defined asthe same variable
  • Written in the same waycss, that is, a colon is used between the variable name and the value:separate
$color:#F00;
p {
    color: $color;
}

compiles to

p {
    color: #F00;
}

SCSSVariables have two scopes:global variable scopeandlocal variable domain

  • Global variables: variables declared at the outermost layer, which can be used anywhere; or added to local variables!globalstatement
  • Local variables: Variables defined within nested rules can only be used within nested rules
$color: red;
.container {
    $height: 500px;
    $font-size: 16px !global; // global variable, externally available
    font-size: $font-size;
    color: $color;
    height: $height;
}
.footer {
    /**$font-size is declared as a global variable using !global*/
    font-size: $font-size; 
    /**
    * Error: Undefined variable. 
    * $height is a local variable under .container and cannot be compiled under .footer
    */
    height:$height;
}

compile css

.container {
    font-size: 16px;
    color: red;
    height: 500px;
}

.footer {
     /**$font-size is declared as a global variable using !global*/
    font-size: 16px;
}

CSS variables

Sass supports by defaultcss variable, through scss variables and css variable management can easily achieve skinning,element-plusis achieved in this way

css variableTo declare a custom attribute, the attribute name needs to be preceded by two minus signs (--) to start, define the variable-- variable name: variable valueE.g:--main-color: black;,Depend onvar()function to get the value, e.g.color: var(--main-color)

:root {
    --main-color: #F00;
}
p {
    color: var(--main-color);
}

:rootis accessible anywhere in the HTML document

Notice:Custom property names are case sensitive,--my-colorand--My-colorwould be considered two different custom attributes

passJavaScriptObtaining or modifying CSS variables is the same as manipulating ordinary CSS properties

// Get a CSS variable on a Dom node
element.style.getPropertyValue("--my-var");

// Get CSS variables on any Dom node
getComputedStyle(element).getPropertyValue("--my-var");

// Modify a CSS variable on a Dom node
element.style.setProperty("--my-var", jsVar + 4);

SCSS data type

  • number:1rem2vh1310px
  • String: There are quoted strings and unquoted strings,"foo"'bar'baz
  • color:blue, #04a3f9, rgba(255,0,0,0.5)
  • Boolean:trueandfalse
  • null value:nullis the only value of its type. Indicates a missing value, usually returned by a function to indicate a missing result;
  • array(list): Use spaces or commas as separators,1.5em 1em 02em,Helvetica,Arial,sans-serif
  • maps: equivalent toJavaScriptofobjectObject, format brackets wrap key-value pairs, separated by commas (key1: value1, key2: value2)
// number
$layer-index: 10;
$border-width: 3px;

// string
$font-weight: bold;

// array
$font-base-family: "Open Sans", Helvetica, Sans-Serif;
$block-base-padding: 6px 10px 6px 10px;

// color
$top-bg-color: rgba(255, 147, 29, 0.6);

// Boolean value
$blank-mode: true;

// null
$var: null;

// maps value
$fonts: (
  serif: "Helvetica Neue",
  monospace: "Consolas",
);

.container {
  // internal variable
  font-family: $font-base-family;
  font-size: $font-size;
  padding: $block-base-padding;

  @if $blank-mode {
    background-color: #000;
  } @else {
    background-color: #fff;
  }

  content: type-of($var);
  content: length($var);
  color: $top-bg-color;
}

// If the list contains a null value, it will be ignored in the generated CSS.
.wrap {
  font: 18px $font-weight map-get($fonts, "sans");
}

!default

You can add at the end of the variable!defaultTo set default values ​​for variables, something likeJavascriptlogical operators forlet content=value || "default value". Note that the variable isnullwill be deemed not to have been!defaultassignment

// If $content didn't use !default before, there is no way to assign and overwrite
$content: "First content";
$content: "Second content" !default;
#main {
    content: $content;
}

compile to css

#main {
  content: "First content";
}

interpolation statement

pass#{}Interpolation statements can use variables in selectors, attribute names, and annotations, using#{}The interpolation statement wraps the variable, andjsneutraltemplate stringvery much like

$font-size: 12px;
$line-height: 30px;
$class-name: danger;
$attr: color;
$author: "Fukudai Mikoto";

p {
    font: #{$font-size}/#{$line-height} Arial Helvetica, sans-serif;
}

/* 
* This is the description section of the file
* @author: #{$author}
*/

a.#{$class-name} {
    border-#{$attr}: #f00;
}

compile to css

p {
    font: 12px/30px Arial Helvetica, sans-serif;
}

/* 
* This is the description section of the file
* @author: Fukuda Life
*/
a.danger {
    border-color: #f00;
}

conditional statement @if

@ifGrammar andjsSimilarly, the basic format is@if...@else if...@else

$theme:3;
.container {
    @if $theme >= 5 {
        background-color: red;
    }
    @else {
        background-color: blue;
    }
}

compile to css

.container {
    background-color: blue;
}

@for loop

forTo repeat operations within a conditional range, this directive has two formats:

  • @for $var from start through end
  • @for $var from start to end

The difference between the two isthroughandtothe meaning of

  • usethrough, the criteria range includesstartandendvalue;
  • usetoWhen the condition scope only containsstartThe value of does not containendvalue;

$varcan be any variable, such as$istartandendMust be an integer value.

@for $i from 1 to 3 {
  #loading span:nth-child(#{$i}) {
      width: 20 * ($i - 1) + px;
  }
}

compile to css

#loading span:nth-child(1) {
    width: 0px;
}

#loading span:nth-child(2) {
    width: 20px;
}

If puttoreplace withthrough

#loading span:nth-child(1) {
    width: 0px;
}

#loading span:nth-child(2) {
    width: 20px;
}

#loading span:nth-child(3) {
    width: 40px;
}

@each loop

@eachThe format of the command is@each $var in $list , $varCan be any variable name, such as$lengthor$name,and$listis a sequence of values, that is, a list of values

$color-list:red green blue turquoise darkmagenta;
@each $color in $color-list {
    $index: index($color-list, $color);
    .p#{$index - 1} {
        background-color: $color;
    }
}

compile to css

.p0 {
    background-color: red;
}

.p1 {
    background-color: green;
}

.p2 {
    background-color: blue;
}

.p3 {
    background-color: turquoise;
}

.p4 {
    background-color: darkmagenta;
}

@while loop

@whileThe instruction loops through the output until the expression returns a result offalse. This can be achieved than@formore complex loops. For example, you can use this to generate rasterized layouts

$column:12;
@while $column>0 {
   .col-sm-#{$column} {
      width: $column / 12 * 100%;
   }
    $column:$column - 1;
}

compile to css

.col-sm-12 {
    width: 100%;
}

.col-sm-11 {
    width: 91.6666666667%;
}

.col-sm-10 {
    width: 83.3333333333%;
}

.col-sm-9 {
    width: 75%;
}

.col-sm-8 {
    width: 66.6666666667%;
}

.col-sm-7 {
    width: 58.3333333333%;
}

.col-sm-6 {
    width: 50%;
}

.col-sm-5 {
    width: 41.6666666667%;
}

.col-sm-4 {
    width: 33.3333333333%;
}

.col-sm-3 {
    width: 25%;
}

.col-sm-2 {
    width: 16.6666666667%;
}

.col-sm-1 {
    width: 8.3333333333%;
}

@import

scss extended@importA function that allows it to import scss or sass files. The imported files will be merged and compiled into the same css file, and the variables or mixins contained in the imported files can be used in the imported files.

common.scss

$color:red;

index.scss

@import "common.scss";
.container {
    border-color: $color;
}

compile to css

.container {
  border-color: red;
}

In the following cases,@importonly as ordinarycssstatement, will not importscssdocument:

  • file extension is.css
  • file name starts withhttp://beginning;
  • file name isurl()
  • @importContains media queries.
@import "common.css";
@import url(common);
@import "http://xxx.com/xxx";
@import 'landscape' screen and (orientation:landscape);

scssAllows simultaneous import of multiple files, e.g. simultaneous import ofa.scssandb.scssTwo files, no need to write a separate oneimportintroduce

@import "a", "b";

@Partials

Import if requiredscssorsassfile, but don’t want it to be compiled ascss, just add an underscore before the file name, which will tellscssDo not compile these files.
Notice:

  • The import statement does not need to addunderline
  • Underlined and non-underlined files with the same name cannot exist at the same time, and underlined files will be ignored

_common.scss

$color:red;

index.scss

@import "common.scss";
.container {
    border-color: $color;
}

compiles to

.container {
  border-color: red;
}

_common.scssfile will not be compiled into_common.cssdocument,PartialsMainly used to define public styles, specially designed to be used by otherscssdocumentimportfor use

@mixin

Mixin directives (Mixin) are used to definereusablestyle. Mixed instructions can contain all css rules, most scss rules, and even introduce variables through parameter functions to output diverse styles;

@mixinand@includeWith the use of

// Define the basic style of a block
@mixin block {
    width: 96%;
    margin-left: 2%;
    border-radius: 8px;
    border: 1px #f6f6f6 solid;
}
// use mixin 
.container {
    .block {
        @include block;
    }
}

compile to css

.container .block {
    width: 96%;
    margin-left: 2%;
    border-radius: 8px;
    border: 1px #f6f6f6 solid;
}

@mixinMultiple parameters and default values ​​can be defined

// Define the inner margin of the block element, the parameter specifies the default value
@mixin block-padding($top:0, $right:0, $bottom:0, $left:0) {
    padding-top: $top;
    padding-right: $right;
    padding-bottom: $bottom;
    padding-left: $left;
}

// Can specify parameter assignment
.container {
    /** without parameters */
    @include block-padding;
    /** Specify parameter values ​​​​in order */
    @include block-padding(10px,20px);
    /** Specify a value for the specified parameter */
    @include block-padding($left: 10px, $top: 20px)
}

Compile CSS

.container {
    /** without parameters */
    padding-top: 0;
    padding-right: 0;
    padding-bottom: 0;
    padding-left: 0;
    /** Specify parameter values ​​​​in order */
    padding-top: 10px;
    padding-right: 20px;
    padding-bottom: 0;
    padding-left: 0;
    /** Specify a value for the specified parameter */
    padding-top: 20px;
    padding-right: 0;
    padding-bottom: 0;
    padding-left: 10px;
}

variable parameter:use...Handle the situation where the parameters are not fixed, similar to the remaining parameters of the function in js

@mixin linear-gradient($direction, $gradients...) {
    background-color: nth($gradients, 1);
    background-image: linear-gradient($direction, $gradients);
}

.table-data {
    @include linear-gradient(to right, #F00, orange, yellow);
}

compiles to

.table-data {
    background-color: #F00;
    background-image: linear-gradient(to right, #F00, orange, yellow);
}

Summarize

  • mixinis a reusable set ofcssDeclaration, which helps to reduce duplication of code, only needs to be declared once, and can be referenced in the file;
  • It is recommended to add default values ​​when using parameters;
  • @importImport partial modular styles (similar functions, same components);
  • @minixdefines reusable styles

@function function

@functionUsed to encapsulate complex operations, it is easy to abstract general formulas and behaviors in a readable way, functions provide return values, and are often used to do calculation work

@functionparameter default value

//change-color and hue are built-in methods
//hue returns the color of $color as a number between 0 and 360 degrees.
//change-color property used to set the color
@function invert($color, $amount: 100%) {
    //@error hue($color); debug 210deg
    $inverse: change-color($color, $hue: hue($color) + 180);
    @return mix($inverse, $color, $amount);
}

$primary-color: #036;
.header {
    background-color: invert($primary-color, 80%);
}

Compile CSS

.header {
    background-color: #523314;
}

variable parameteras a js functionrest parameter

@function sum($numbers...) {
    $sum: 0;
    @each $number in $numbers {
        $sum: $sum + $number;
    }
    @return $sum;
}

$widths: 50px, 30px, 100px;
.micro {
    width: sum($widths...);
}

Compile to CSS

.micro {
    width: 180px;
}

@returnonly allowed in@functionused within, andjssame, metreturnwill return

Summarize

  • @functionand@mixinThere is no difference in the way the parameters are used;
  • @functionused to calculate,@mixinUsed to encapsulate styles,@importto extract them into a module

@extend inherits

byelementUIofel-buttoncomponent as an example, you can use@extendTo inherit an existing style, use the comma selector.

// # same as id selector
.button {
    display: inline-block;
    margin-bottom: 0;
    font-weight: normal;
    text-align: center;
    white-space: nowrap;
    vertical-align: middle;
    cursor: pointer;
    background-image: none;
    border: 1px solid transparent;
    padding: 6px 12px;
    font-size: 14px;
    line-height: 1.42857143;
    border-radius: 4px;
    user-select: none;
}

.btn-default {
    @extend .button;
    color: #333;
    background-color: #fff;
    border-color: #ccc;
}

.btn-danger {
    @extend .button;
    color: #fff;
    background-color: #d9534f;
    border-color: #d43f3a;
}

compile to css

.button, .btn-danger, .btn-default {
    display: inline-block;
    margin-bottom: 0;
    font-weight: normal;
    text-align: center;
    white-space: nowrap;
    vertical-align: middle;
    cursor: pointer;
    background-image: none;
    border: 1px solid transparent;
    padding: 6px 12px;
    font-size: 14px;
    line-height: 1.42857143;
    border-radius: 4px;
    user-select: none;
}

.btn-default {
    color: #333;
    background-color: #fff;
    border-color: #ccc;
}

.btn-danger {
    color: #fff;
    background-color: #d9534f;
    border-color: #d43f3a;
}

placeholder selector

placeholder selector%, with the usualidandclassSelectors are written in a similar way, except that#or.replaced by%, placeholder selectors must pass@extendinstruction call

.button %base {
    display: inline-block;
    margin-bottom: 0;
    font-weight: normal;
    text-align: center;
    white-space: nowrap;
    vertical-align: middle;
    cursor: pointer;
    background-image: none;
    border: 1px solid transparent;
    padding: 6px 12px;
    font-size: 14px;
    line-height: 1.42857143;
    border-radius: 4px;
    user-select: none;
}
        
.btn-default {
    @extend %base;
    color: #333;
    background-color: #fff;
    border-color: #ccc;
}

.btn-danger {
    @extend %base;
    color: #fff;
    background-color: #d9534f;
    border-color: #d43f3a;
}

The effect is the same as the class selector above, but it has an advantage,placeholder selector %When the style it belongs to is not used, it will not be compiled intocssin the file

.button .btn-danger, .button .btn-default {
    display: inline-block;
    margin-bottom: 0;
    font-weight: normal;
    text-align: center;
    white-space: nowrap;
    vertical-align: middle;
    cursor: pointer;
    background-image: none;
    border: 1px solid transparent;
    padding: 6px 12px;
    font-size: 14px;
    line-height: 1.42857143;
    border-radius: 4px;
    user-select: none;
}

.btn-default {
    color: #333;
    background-color: #fff;
    border-color: #ccc;
}

.btn-danger {
    color: #fff;
    background-color: #d9534f;
    border-color: #d43f3a;
}

@use

There are compatibility issues, only valid on Dart Sass 1.23.0 and above,The official document has a compatibility introduction

cssModularity in the true sense can be obtained from otherscssstylesheet loadedmixinfunctionand variables, and combine thecsscombine it all toghther.scssMany built-in modules are also provided, we can pass@useUse, the official also recommends the use of@usereplace@import, which will be discarded later@import

Disadvantages of @import

  • There are multiple imports and repeated loading of styles.
  • There is no namespace, in order to avoid name collision, dare not use shorthandclassname, so naming always requires attention.
  • There is no concept of private functions, styles are fully exposed usingimportThis is not friendly enough for the ui library

@useUse the default with a namespace, you can also rename the space

src/_corners.scss

$radius: 3px;
@mixin rounded {
    border-radius: $radius;
}

index.scss

@use "src/corners"; // default namespace corners
// @use "src/corners" as c; // rename space
.button {
    @include corners.rounded;
    padding: 5px + corners.$radius;
    // padding: 5px + c.$radius; // rename c reference
}

as *Let the module be in the global namespace, you can use it directly without bringing the namespace

$radius: 3px;
@mixin rounded {
    border-radius: $radius;
}

use

@use "src/corners" as *;

.button {
    @include rounded;
    padding: 5px + $radius;
}

private module

variable use-beginning,@usewill not introduce this variable

$-radius: 3px;

@mixin rounded {
    border-radius: $-radius;
}

index.scss

@use "src/corners";

.button {
    @include corners.rounded;
    // Error: Private members can't be accessed from outside their modules
    padding: 5px + corners.$-radius;
}

@forward

@forwardIt can be seen as forwarding, introducing all variables of another module in the current module,mixinsAnd functions, directly expose the API to the outside, and will not add code to the current module, different from@use@forwardCannot add namespace to variable

For example inbootstrap.cssintroducefunctionsvariablesmixinsfile, not directly in thebootstrap.scssThese imported modules are used in the file. Instead, it needs to be introduced in another file@use bootstrapmodule, and then use these methods

/* bootstrap.scss */
@forward"functions";
@forward"variables";
@forward"mixins";

@forwardby controllingshowandhideShow or hide certain variables in a module

a.scss

@mixin rounded {
    border-radius: 100px;
}
footer {
    height: 1px;
}

b.scss

$radius: 3px;

c.scss

@forward “a” show rounded;
@forward “b” hide $radius;


index.scss

@import “c.scss”;

.button {

@include rounded;
padding: $radius;

}
// Error: Undefined variable. padding: $radius;

### @at-root

`@at-root` is used to jump out of nesting, it is more commonly used in multi-level nesting, including `without` and `with`

// did not jump out
.parent-1 {

color:#f00;
.child {
    width:100px;
}

}

//Single selector jumps out
.parent-2 {

color:#f00;
@at-root .child {
    width:200px;
}

}

//Multiple selectors jump out
.parent-3 {

background:#f00;
@at-root {
    .child1 {
        width:300px;
    }
    .child2 {
        width:400px;
    }
}

}

compiles to

.parent-1 {

color: #f00;

}
.parent-1 .child {

width: 100px;

}

.parent-2 {

color: #f00;

}
.child {

width: 200px;

}

.parent-3 {

background: #f00;

}
.child1 {

width: 300px;

}

.child2 {

width: 400px;

}

**@without and with**

By default `@at-root` will only jump out of selector nesting, but not `@media` or `@support`, if you want to jump out of these two, you need to use `@at-root (without: media)` or `@at-root (without: support)`, `@at-root` has four keywords

- `all` means all;
- `rule` means a regular `css` selector;
- `media` means `media`;
- `support` means `support` (`@support` is mainly used to detect whether the browser supports a certain property of css)

The default `@at-root` is `@at-root (without:rule)`

/Jump out of parent element nesting/
@media print {

.parent1{
    color:#f00;
    @at-root .child1 {
        width:200px;
    }
}

}

/Jump out of media nesting, the parent is valid/
@media print {

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

}

/Jump out of media and parent/
@media print {

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

}

compiled into

/Jump out of parent element nesting/
@media print {

.parent1 {
    color: #f00;
}
.child1 {
    width: 200px;
}

}
/Jump out of media nesting, the parent is valid/
@media print {

.parent2 {
    color: #f00;
}

}
.parent2 .child2 {

width: 200px;

}
/Jump out of media and parent/
@media print {

.parent3 {
    color: #f00;
}

}
.child3 {

width: 200px;

}

**@at-root is used with &**

.child{

@at-root .parent &{
    color:#f00;
}

}

compiles to

.parent .child {

color: #f00;

}

### SCSS built-in extensions

The built-in extensions of scss are divided into `color, list, map, math, meta, selector, string`, etc. Extensions are some built-in `function` of `scss`, which are equivalent to `JS` built-in methods

Built-in functions can be introduced using `@use` modularization, or they can be called directly using the global function name provided by him. The following two methods are the same.

@use ‘sass:list’;
p {

color: nth($list: red blue green, $n: 2); // blue
color: list.nth($list: red blue green, $n: 2); // blue

}

### String string functions

`scss` has many functions for manipulating strings
- `quote($string)`: add quotes to a string

quote(hello) //”hello”

- `unquote($string)` removes quotes from a string

unquote(“hello”) //hello

- `str-index($string, $substring)` returns the first occurrence of substring in string. Returns null if no substring was matched. Case sensitive.

str-index(abcd, a) // 1
str-index(abcd, ab) // 1
str-index(abcd, X) // null

- `str-length($string)` gets the string length

str-length(“hello”) //5

- `string-insert($string, $insert, $index)` inserts the insert at the index position in the string string

str-insert(“Hello world!”, ” xiaoming”, 6) //”Hello xiaoming world!”

- `str-slice($string, $start-at, $end-at: -1)` intercepts a substring from string, sets the start and end positions by start-at and end-at, and defaults if the end index value is not specified Truncate to the end of the string. It feels a bit similar to js

str-slice(“abcd”, 2, 3) => “bc”
str-slice(“abcd”, 2) => “bcd”
str-slice(“abcd”, -3, -2) => “bc”
str-slice(“abcd”, 2, -2) => “bc”

other
- `to-lower-case(*string*)` convert string to lowercase
- `to-upper-case(*string*)` convert string to uppercase
- `unique-id()` returns an unquoted random string as id

case code

p {

&:after {
    content: quote (this is the content inside);
}
background-color: unquote($string: "#F00");
z-index:str-length("scss learning");

}

compile result

p {

background-color: #F00;
z-index: 6;

}
p:after {

content: "This is the content inside";

}

### Math Mathematical functions

`Math` numeric functions handle numerical calculations

- `abs(number)` returns the absolute value of a number

abs(13) // 13
abs(-13) // 13

- `comparable(num1, num2)` returns a Boolean value to judge whether *num1* and *num2* can be compared, and note whether they can be compared, not the result of the comparison

comparable(15px, 10px) // true
comparable(20mm, 1cm) // true
comparable(35px, 2em) // false

- `ceil(*number*)` rounds up

ceil(13.24) //14

- `floor(*number*)` rounds down

floor(15.84) // 15

- `max(number...` returns the maximum value

max(5, 7, 9, 0, -3, -7) // 9

- `min(number...` returns the minimum value

min(7, 2, 0, -2, -7) // -7

- `percentage(number)`: convert the number into a percentage expression

percentage(1.2) // 120

- `random()`: returns a decimal in the range 0-1,

random() // 0.2783

- `random(number)` returns an integer between 1 and number, including 1 and limit, if the number parameter is passed in

random(10) // 4

- `round(number)`: returns an integer closest to the number, rounded up

round(15.20) // 15 round(15.80) // 16

- `div($number1, $number2)` //=> number returns the result of dividing `$number2` by `$number1`

@debug math.div(1, 2); // 0.5
@debug math.div(100px, 5px); // 20
@debug math.div(100px, 5); // 20px
@debug math.div(100px, 5s); // 20px/s
@debug math.percentage(0.2); // 20%

case code

p {

z-index: abs(-15); // 15
z-index: ceil(5.8); //6
z-index: max(5, 1, 6, 8, 3); //8
opacity: random(); // random 0-1

}

compiles to

p {

z-index: 15;
z-index: 6;
z-index: max(5, 1, 6, 8, 3);
opacity: 0.8636254167;

}

### List list function

`List` features
- The `List` function can access values ​​in a list, add elements to a list, merge lists, etc.
- The `List` list is immutable, so when the list is processed, a new list is returned instead of modifying the original list.
- The starting index value of the list is `1`, remember not `0`

**List method**

- `append(*list*, *value*, [*separator*])` appends a single value *value* to the end of the list. *separator* is the delimiter, which is automatically detected by default, or specified as a comma or a space, represented by `comma` and `space` respectively

append((a b c), d) // a b c d
append((a b c), (d), comma) // a, b, c, d

- `index(list, value)` returns the index position of the element *value* in the list

index(a b c, b) // 2
index(a b c, f) // null

- `is-bracketed(list)` determines whether there are brackets in the list

is-bracketed([a b c]) // true
is-bracketed(a b c) // false

- `list-separator(list)` returns the separator type for a list. Can be a space or a comma

list-separator(a b c) // “space”
list-separator(a, b, c) // “comma”

- `join(list1, list2, [separator, bracketed])` merges two lists, appending list *list2* to the end of list *list1*. *separator* is the separator, which is automatically detected by default, or specified as a comma or space. *bracketed* automatically detects whether there are brackets by default, can be set to true or false

join(a b c, d e f) // a b c d e f
join((a b c), (d e f), comma) // a, b, c, d, e, f
join(a b c, d e f, $bracketed: true) // [a b c d e f]

- `length($list)` returns the length of the list

length(a b c) // 3

- `set-nth(list, n, value)` sets the value of the *nth* item in the list to *value*.

set-nth(a b c, 2, x) // a x c

- `nth($list, $n)` gets the value of the *n*th item

nth(a b c, 3) // c

- `zip(lists)` groups multiple lists with the same index value to form a new multi-dimensional list, which is very easy to use

zip(1px 2px 3px, solid dashed dotted, red green blue)
// 1px solid red, 2px dashed green, 3px dotted blue

case code

p {

z-index: length(12px); //1
z-index: length(12px 5px 8px); //3
z-index: index(a b c d, c); //3
padding: append(10px 20px, 30px); // 10px 20px 30px
color: nth($list: red blue green, $n: 2); // blue
@debug list.zip(10px 50px 100px, short mid long); // 10px short, 50px mid, 100px long

}

compile result

p {

z-index: 1;
z-index: 3;
z-index: 3;
padding: 10px 20px 30px;
color: blue;

}

### Map function

[Sass Map](https://sass-lang.com/documentation/modules/map) is immutable, so when processing a Map object, a new Map object is returned instead of the original Map object to modify.

Map (mapping) objects are represented by one or more pairs of `key/value`

- `map-get(map, key)` returns the value (value) corresponding to *key* in the Map. If there is no corresponding key, return a null value

$font-sizes: (“small”: 12px, “normal”: 18px, “large”: 24px)
map-get($font-sizes, “small”) // 12px

- `map-has-key(map, key)` determines whether *map* has a corresponding *key*, returns true if it exists, otherwise returns false

$font-sizes: (“small”: 12px, “normal”: 18px, “large”: 24px)
map-has-key($font-sizes, “big”) // false

- `map-keys(map)` returns an array of all keys in *map*

$font-sizes: (“small”: 12px, “normal”: 18px, “large”: 24px)
map-keys($font-sizes) // “small”, “normal, “large”

- `map-values(map)` returns all values ​​in *map* and generates a queue

$font-sizes: (“small”: 12px, “normal”: 18px, “large”: 24px)
map-values($font-sizes) // 12px, 18px, 24px

- `map-merge(map1, map2)` merges two maps to form a new map type, that is, *map2* is added to the end of *map1*

$font-sizes: (“small”: 12px, “normal”: 18px, “large”: 24px)
$font-sizes2: (“x-large”: 30px, “xx-large”: 36px)

map-merge($font-sizes, $font-sizes2)
//”small”: 12px, “normal”: 18px, “large”: 24px, “x-large”: 30px, “xx-large”: 36px

- `map.deep-merge($map1, $map2)` will deep merge two nested `map`s

$helvetica-light: (
“weights”: (

"lightest": 100,
"light": 300

)
);
$helvetica-heavy: (
“weights”: (

"medium": 500,
"bold": 700

)
);

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

- `map-remove(map, keys... )` removes the keys in *map*, multiple keys are separated by commas

$font-sizes: (“small”: 12px, “normal”: 18px, “large”: 24px)
map-remove($font-sizes, “small”) // (“normal”: 18px, “large”: 24px)
map-remove($font-sizes, “small”, “large”) // (“normal”: 18px)

- `map.deep-remove($map, $key, $keys...)` Multi-layer nested deletion, the deletion level is based on the number of parameters

$fonts: (
“Helvetica”: (

"weights": (
  "regular": 400,
  "medium": 500,
  "bold": 700
)

)
);

@debug map.deep-remove($fonts, “Helvetica”, “weights”, “regular”);
// (
// “Helvetica”: (
// “weights: (
// “medium”: 500,
// “bold”: 700
// )
// )
// )

- `map.set($map, $keys..., $value)` adds `key` and `value` values, the first is `map`, the last is `value`, the middle is `key`, Nesting multiple `key...`

$fonts: (
“Helvetica”: (

"weights": (
  "regular": 400,
  "medium": 500,
  "bold": 700
)

)
);

@debug map.set($fonts, “Helvetica”, “weights”, “regular”, 300);
// (
// “Helvetica”: (
// “weights”: (
// “regular”: 300,
// “medium”: 500,
// “bold”: 700
// )
// )
// )

case code

@use ‘sass:map’;

// Create a Map, similar to an object
$map: (
key: value,
nextkey: nextvalue
);

// use
.element:before {
content: map-get($map, key);
}

The result of the above compiled output is as follows:

.element:before {
content: value
}

`Map` applied in `@each`

/Define a sass map named $icons/
$icons: (
checkmark: a,
plus: b,
minus: c
);

/Traverse all the keys of the map and create their own classes/
@each $name, $value in $icons {
.icon–#{$name} {

content: $value;

}
}

compile result

/Traverse all the keys of the map and create their own classes/
.icon–checkmark {
content: “a”;
}

.icon–plus {
content: “b”;
}

.icon–minus {
content: “c”;
}

`@each` traverses nested map multiple values
 
- Assign multiple `values` (equivalent to an array) to `map` with a `key`, and separate `values` by commas `,`
- Define a series of `buttons`, the first `value` of each `key` is `background-color`, and the second `value` is `font-color`.
- Iterate through `$buttons` and assign to `$colors` object. Get the first `key` through `nth($colors,1)` (the first parameter is the name of the object, and the second parameter is the value position). If you need to get the second `value`, then change the second parameter to 2.

// _m-buttons.scss
$buttons: (
error: (#d82d2d, #666),
success: (#52bf4a, #fff),
warning: (#c23435, #fff)
);

.m-button {
display: inling-block;
padding: .5em;
background: #ccc;
color: #666;

@each $name, $colors in $buttons {

$bgcolor: nth($colors, 1);
$fontcolor: nth($colors, 2);

&--#{$name} {
  background-color: $bgcolor;
  color: $fontcolor;
}

}
}

compile result

.m-button {
display: inline-block;
padding: .5em;
background: #ccc;
color: #666;
}

.m-button–error {
background-color: #d82d2d;
color: #666;
}

.m-button–success {
background-color: #52bf4a;
color: #fff;
}

.m-button–warning {
background-color: #c23435;
color: #fff;
}

### selector selector function

`selector` related functions can perform some corresponding operations on selecting `css`

- `is-superselector(super, sub)` compares the matching range of the two selectors, that is, judges whether the *super* selector contains the matching range of the *sub* selector, if yes, returns `true`, otherwise returns ` false`

is-superselector(“div”, “div.myInput”) // true
is-superselector(“div.myInput”, “div”) // false
is-superselector(“div”, “div”) // true

- `selector-append(selectors)` appends the second (or multiple) to the first selector.

selector-append(“div”, “.myInput”) // div.myInput
The selector – append (” warning “, “__a”) results:. Warning__a

- `selector-nest(selectors)` returns a new selector that generates a nested list from the provided list selector

selector-nest(“ul”, “li”) // ul li
selector-nest(“.warning”, “alert”, “div”) // .warning div, alert div

- `selector-parse(selector)` converts a string selector *selector* into a list of selectors.

selector-parse(“h1 .myInput .warning”) // (‘h1’ ‘.myInput’ ‘.warning’)

- `selector-replace(selector, original, replacement)` Given a selector, replace `original` with `replacement` and return a new queue of selectors

selector-replace(“p.warning”, “p”, “div”) // div.warning

- `selector-unify(selector1, selector2)` unifies two sets of selectors into one composite selector. Returns a null value if the two selectors cannot be combined.

selector-unify(“myInput”, “.disabled”) // myInput.disabled
selector-unify(“p”, “h1”) // null

- `simple-selectors(selectors) split composite selectors into single selectors

simple-selectors(“div.myInput”) // div, .myInput
simple-selectors(“div.myInput:before”) // div, .myInput, :before

case code

@use ‘sass:selector’;

@debug selector.is-superselector(“a”, “a”); // true

// You can directly use the prefix under @forward
@debug selector-append(“a”, “.disabled”); // a.disabled
@debug selector-extend(“a.disabled”, “a”, “.link”); // a.disabled, .link.disabled

.header {

content: selector-append(".a", ".b", ".c") + '';
content: selector-unify("a", ".disabled") + '';

}

### meta

`meta` provides a `mixin` and some atomic level `function`
- `meta.calc-args` gets the arguments for the method
- `meta.calc-name` gets the method name

**meta.load-css**

`meta.load-css($url, $with:())` includes all `css` styles in `$url`. Note that the functions, variables and `mixins` introduced by `$url` cannot be used in `scss` after `meta.load-css()`, it will only return the compiled `css` code. Its second parameter can modify variables using `!default`

src/corners

$border-contrast: false !default;

code {

background-color: #6b717f;
color: #d2e1dd;
@if $border-contrast {
    border-color: #dadbdf;
}

}


index.scss

@use “sass:meta”;

body.dark {

@include meta.load-css("src/corners", $with: ("border-contrast": true));

}

compiles to

body.dark code {

background-color: #6b717f;
color: #d2e1dd;
border-color: #dadbdf;

}

Related `function`

@use “sass:meta”;

@debug meta.calc-args(calc(100px + 10%)); // unquote(“100px + 10%”)
@debug meta.calc-args(clamp(50px, var(–width), 1000px)); // 50px, unquote(“var(–width)”), 1000px

@debug meta.calc-name(calc(100px + 10%)); // “calc”
@debug meta.calc-name(clamp(50px, var(–width), 1000px)); // “clamp”

### color color function

scss contains many functions for manipulating colors.

- `rgb(red, green, blue)` creates a `Red-Green-Blue (RGB)` color. Where `R` is "red" for red, `G` is "green" for green, and `B` is "blue" for blue

rgb(0, 255, 255);

- `rgba(red, green, blue, alpha)` creates a color based on red, green, blue and **transparency value**

rgba(0, 255, 255, 0.3);

- `hsl(hue, saturation, lightness)` creates a color from the values ​​of hue, saturation and lightness

hsl(120, 100%, 50%); // green
hsl(120, 100%, 75%); // light green
hsl(120, 100%, 25%); // dark green
hsl(120, 60%, 70%); // soft green

- `hsla(hue, saturation, lightness, alpha)` creates a color from the values ​​of hue, saturation, lightness and **transparency (alpha)**

hsl(120, 100%, 50%, 0.3); // green with transparency
hsl(120, 100%, 75%, 0.3); // light green with transparency

- `grayscale(color)` turns a color into gray, equivalent to `desaturate(color,100%)`

grayscale(#7fffd4); // #c6c6c6

- `complement(color)` returns a complementary color, equivalent to `adjust-hue($color,180deg)`

complement(#7fffd4); // #ff7faa

- `invert(*color*, weight)` returns an inverse color, where the red, green, and blue values ​​are reversed, while the transparency remains the same

invert(white); // black

- `red(color)` gets the red value (0-255) from a color, which can be used to get the red value in a `hex` color

red(#7fffd4); // 127
red(red); // 255

- `green(color)` gets the green value (0-255) from a color

green(#7fffd4); // 255
green(blue); // 0

- `blue(color)` gets the blue value (0-255) from a color

blue(#7fffd4); // 212
blue(blue); // 255

- `hue(color)` returns the angle value of the color in the `HSL` color value (0deg - 255deg)

hue(#7fffd4); // 160deg

- `saturation(color)` gets the saturation value of a color (0% - 100%)

saturation(#7fffd4); // 100%

- `lightness(color)` gets the lightness value of a color (0% - 100%)

lightness(#7fffd4); // 74.9%

- `alpha(color)` returns the `alpha` of the color, the return value is `0` or `1`

alpha(#7fffd4); // 1

- `opacity(color)` gets the color opacity value (0-1)

opacity(rgba(127, 255, 212, 0.5); // 0.5

- `mix(color1, color2, weight)` mixes two colors together.

The *weight* parameter must be 0% to 100%. The default weight is 50%, which means that each color takes 50% of the color values ​​of color1 and color2. If the weight is 25%, it means that the color is the sum of the color values ​​of 25% color1 and 75% color2

- `adjust-hue(color, degrees)` creates a new color by changing the hue value of a color (-360deg - 360deg)

adjust-hue(#7fffd4, 80deg); // #8080ff

- `lighten(color, amount)` creates a new color by changing the brightness value of the color (0% - 100%) to lighten the color
- `darken(color, amount)` creates a new color by changing the brightness value of the color (0% - 100%), making the color darker
- `saturate(color, amount)` increases the color saturation of the incoming color. Equivalent to `adjust-color( color, saturation: amount)`

- `desaturate(color, amount)` desaturates a color to produce a new color value. Similarly, the value range of saturation is 0% ~ 100%. Equivalent to `adjust-color(color, saturation: -amount)`
- `opacify(color, amount)` reduces the transparency of the color, the value is between 0-1. Equivalent to `adjust-color(color, alpha: amount)`

- `fade-in(color, amount)` reduces the transparency of the color, the value is between 0-1. Equivalent to `adjust-color(color, alpha: amount)`
- `transparentize(color, amount)` increases the transparency of the color, the value is between 0-1. Equivalent to `adjust-color(color, alpha: -amount)`

- `fade-out(color, amount)` increases the transparency of the color, the value is between 0-1. Equivalent to `adjust-color(color, alpha: -amount)`


case code

.p1 {

// brighten the color
color:scale-color(#5c7a29, $lightness: +30%);

}

.p2 {

// make the color darker
color:scale-color(#5c7a29, $lightness: -15%);

}

.p3 {

// reduce color opacity
color:scale-color(#5c7a29, $alpha: -40%);

}

compiles to

.p1 {

color: #95c249;

}

.p2 {

color: #4e6823;

}

.p3 {

color: rgba(92, 122, 41, 0.6);

}

### Debug related

**@debug**

`@debug` prints the value of the expression, which is convenient for debugging.

$font-sizes: 10px + 20px;

$style: (
    color: #bdc3c7
);

.container {

@debug $style;
@debug $font-sizes;

}

output result

Debug:(color: #bdc3c7)
Debug:30px

**@error**

`@error` display error message

@mixin reflexive-position($property, $value) {
@if $property != left and $property != right {

@error "Property #{$property} must be either left or right.";

}

$left-value: if($property == right, initial, $value);
$right-value: if($property == right, $value, initial);

left: $left-value;
right: $right-value;
[dir=rtl] & {

left: $right-value;
right: $left-value;

}
}

.sidebar {
@include reflexive-position(top, 12px);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Error: Property top must be either left or right.
}

output result

Error: “Property top must be either left or right.”

3 │ @error “Property #{$property} must be either left or right.”;
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

example.scss 3:5 reflexive-position()
example.scss 19:3 root stylesheet

**@warn**

`@warn` displays a warning advice, a stack trace will be displayed.

$known-prefixes: webkit, moz, ms, o;

@mixin prefix($property, $value, $prefixes) {
@each $prefix in $prefixes {

@if not index($known-prefixes, $prefix) {
  @warn "Unknown prefix #{$prefix}.";
}

-#{$prefix}-#{$property}: $value;

}
#{$property}: $value;
}

.tilt {
// Oops, we typo’d “webkit” as “wekbit”!
@include prefix(transform, rotate(15deg), wekbit ms);
}

show warning message

Warning: Unknown prefix wekbit.

example.scss 6:7   prefix()
example.scss 16:3  root stylesheet
### Summarize

There is a lot of content knowledge. By consulting official Sass documents and reading article translations, we collect and sort out commonly used Sass knowledge, which is convenient for reading the source code of `element-plus` component library