Scss浅学

Scss浅学

Sass是目前非常成熟的CSS扩展语言。在Less中和Sass决定选择学习Sass,因为Sass更加强大吧,而且看到BootStrap从4.0开始,弃用Less使用Sass,我就觉得Less应该不太行了。而且问了师兄,他实习的公司用的也是Sass,最终决定学习Sass。自己的CSS基础非常的薄弱,相当于没有,所以学习Sass的目的,也是为了后面练习各种CSS实例打下基础。Sass从4.0之后,改叫Scss,因为本文肯定学的是最新的知识,所以统一就叫Scss。

学习网址:Sass中文网

安装:安装vscode插件Live Sass Compiler的,可以实时将Scss文件转换成css文件

1、变量

$来标识变量。

$highlight-color: #F90;
// 多个变量赋值
$basic-border: 1px solid black;

// 可以嵌套引用
$highlight-color: #F90;
$highlight-border: 1px solid $highlight-color;
.selected {
  border: $highlight-border;
}

注意:中划线声明的变量可以使用下划线的方式引用,反之亦然。(这个有点艹)

$link-color: blue;
a {
  color: $link_color;
}

2、嵌套规则

这个特性其实是这些css扩展语言总重要的功能了。

可以在规则中嵌套规则块,有层级关系了,好用!

#content {
  article {
    h1 { color: #333 }
    p { margin-bottom: 1.4em }
  }
  aside { background-color: #EEE }
}
 /* 编译后 */
#content article h1 { color: #333 }
#content article p { margin-bottom: 1.4em }
#content aside { background-color: #EEE }

父选择器的标识符&

类似伪类的东西,需要用到这个&符号,其实就是相当于展开的时候,&就是父选择器

article a {
  color: blue;
  &:hover { color: red }
}

会变成如下

article a { color: blue }
article a:hover { color: red }

群组选择器的嵌套

对命中群组中任何一个选择器的元素生效。相当于乘法交换律一样。

下面这种情况是外面一个,里面三个,相当于a*(b+c+d)

.container {
  h1, h2, h3 {margin-bottom: .8em}
}

//相当于css里面的
.container h1, .container h2, .container h3 { margin-bottom: .8em }

下面这种情况外面两个,里面一个,相当于(a+b)*c

nav, aside {
  a {color: blue}
}
//相当于css里面
nav a, aside a {color: blue}

注意:群组选择器的规则嵌套生成的css。虽然scss让你的样式表看上去很小,但实际生成的css却可能非常大,这会降低网站的速度。

子或同层组合选择器

针对>+~这三类。重新提一下这几个,都忘了。

选择器 写法 示例 示例描述
后代选择器 空格 div p 选择 <div> 元素内的所有 <p> 元素。
子元素选择器 > div > p 选择其父元素是 <div> 元素的所有子元素 <p>
(不包括后代元素孙元素这类,只包括后代元素的子元素) 。
相邻兄弟选择器 + div + p 选择所有紧随 <div> 元素之后的 <p> 元素。
兄弟元素紧邻的一个元素)
通用兄弟选择器 ~ p ~ ul 选择 <p> 元素后面的每个 <ul> 元素。
兄弟元素的的所有元素)
article {
  ~ article { border-top: 1px dashed #ccc }
  > section { background: #eee }
  dl > {
    dt { color: #333 }
    dd { color: #555 }
  }
  nav + & { margin-top: 0 }
}

// 转换成三级
article ~ article { border-top: 1px dashed #ccc }
article > footer { background: #eee }
article dl > dt { color: #333 }
article dl > dd { color: #555 }
nav + article { margin-top: 0 }

嵌套属性

这个也蛮实用的,简写属性前面相同的名称,例如:border-*

nav {
  border: {
  style: solid;
  width: 1px;
  color: #ccc;
  }
}

//相当于CSS中的,将border乘进去了
nav {
  border-style: solid;
  border-width: 1px;
  border-color: #ccc;
}

甚至下面这种写法更加变态

nav {
  border: 1px solid #ccc {
  left: 0px;
  right: 0px;
  }
}

//相当于CSS中
nav {
  border: 1px solid #ccc;
  border-left: 0px;
  border-right: 0px;
}

所以嵌套我的感觉就是,想要乘以什么东西,套个规则块就完事了,反正都能乘进去

3、导入SCSS文件

css导入其他css样式,用的@import,但是只有执行到这条语句的时候才去下载其他css文件,导致资源加载较慢。

sccc的@import规则会在生成css文件的时候就把相关文件导入进来,无需另外加载。

使用scss的@import不需要致命导入文件的全名,可以省略.sass或者.scss文件后缀。例如 @import “sidebar”这条命令就把sidebar.scss文件中的所有样式添加到当天样式表中。

Scss部分文件

被导入的部分scss文件,如果你不想单独生成css文件,只是想被其他文件scss引用的话,就可以用特殊的约定,scss局部文件的文件名以下划线开头。这样子编译时,这种文件就不会被单独编译成css。

@import一个局部文件时,还可以不写文件的全名,即省略文件名开头的下划线。例如,导入themes/_night-sky.scss这个局部文件里的变量,你只需在样式表中写@import "themes/night-sky";

默认变量值

在下面这种情况,后面的会覆盖掉前面的值,如果不想这样子的话,就使用默认变量值 !default

$link-color: blue;
$link-color: red;
a {
	color: $link-color;
}

不同的是!default用于变量,含义是:如果这个变量被声明赋值了,那就用它声明的值,否则就用这个默认值。这个!default用在引用别人文件的那一块,而不是被引用的那一块。意思是如果我引用的文件有这个参数的话,我这个就作废了,用别人默认指定的吧。

$fancybox-width: 400px !default;
.fancybox {
	width: $fancybox-width;
}

嵌套导入

这个简单,相当于在规则体内用上直接引入语句。

//blue-theme.scc文件
aside {
  background: blue;
  color: white;
}

//引入的文件
.blue-theme {@import "blue-theme"}

// 最后相等于这种
.blue-theme {
  aside {
    background: blue;
    color: #fff;
  }
}

CSS引入

这块我看sass中文网说的不够详细,如果直接使用原生css的导入方式的话,他会认为引用的方式为原生的方法,也就是之前那种只有当加载到这行的时候,才会再引用。

@import "theme.css"
@import "http://fonts.googleapis.com/css?family=Droid+Sans"
@import url(theme)
@import "landscape" screen and (orientation: landscape)

上述的会被编译成css文件

@import url(theme.css);
@import "http://fonts.googleapis.com/css?family=Droid+Sans";
@import url(theme);
@import "landscape" screen and (orientation: landscape);

但是如果scss想要引入原生css的话,可以直接省略名称,他会直接把这些css当做文本,直接弄进来

// code.css
code {
  padding: .25em;
  line-height: 0;
}
// style.sass
@import code
.body {
  background-color: skyblue;
}

编译出来的css文件就是如下

code {
  padding: .25em;
  line-height: 0;
}
.body {
  background-color: skyblue;
}

所以注意上述两点的不同,@import 'theme'@import 'theme.css'两句实现的效果完全不同,一个是原生css方式引入css文件,一种是scss引入纯css文本文件

4、使用use导入文件

在查阅引入css样式的时候,发现官方文档并不推荐使用@import了,因为有以下几点问题

  • @import使所有变量、混音和函数可全局访问。这使得人们(或工具)很难分辨出任何东西的定义在哪里。
  • 由于所有内容都是全局的,因此库必须为其所有成员添加前缀以避免命名冲突。
  • @extend规则也是全局的,这使得很难预测哪些样式规则将被扩展。
  • 每次编辑时都会执行每个样式表并发出其CSS,这会增加编译时间并产生臃肿的输出。
  • 无法定义下游样式表无法访问的私有成员或占位符选择器。

我的理解就是,引入的文件都是全局的,达咩,应该像es6的模块化一样,scss也应该模块。当然这个模块,出来的还是比较新的,好像是19年底才出来的,中文我看没有文章说这个东西,估计是不好用或者存在局限性,或者目前支持性还不够好,所以应该还是以@import为主。

@use的差异

  • 该文件只导入一次,无论您在项目中导入了多少次。
  • 以下划线 (_) 或连字符 (-) 开头的变量、mixin 和函数(Scss 称之为“成员”)被认为是私有的,而不是导入的。
  • 来自使用过的文件(在本例中为 button.scss)的成员仅在本地可用,但不会传递给未来的导入。
  • 同样,@extends只会向上链应用;扩展导入文件中的选择器,但不扩展导入此文件的文件。
  • 默认情况下,所有导入的成员都是命名空间的。

使用@use导入文件

会根据导入的文件自动生成一个命名空间

@use 'buttons'; // 生成一个buttons的命名空间
@use 'forms'; // 生成一个forms的命名空间

访问的话必须要通过命名空间加句子分隔符的方式

// 变量: <namespace>.$variable
$btn-color: buttons.$color;
$form-border: forms.$input-border;

// 方法: <namespace>.function()
$btn-background: buttons.background();
$form-border: forms.border();

// 混入: @include <namespace>.mixin()
@include buttons.submit();
@include forms.input();

也可以通过as来更改或者删除命名空间。

@use 'buttons' as *; // the star removes any namespace
@use 'forms' as f;

$btn-color: $color; // buttons.$color without a namespace
$form-border: f.$input-border; // forms.$input-border with a custom namespace

@forward传递文件

在 SCSS 中加载样式表可以做更多的事情,但与@use相关的最有用的样式表之一是@forward规则。它允许您通过另一个文件访问成员。下面是一个简单示例。

// _button.scss
$padding: 1rem;


//_box.scss
@use 'button';
.boxButton {
    padding: button.$padding; // 1rem;
}


//_newBox.scss
@use 'box';
.newBoxButton {
    padding: button.$padding; // ???这里显示不出来
}

_newBox.scss 无法从 _button.scss 访问该变量。我们需要明确地向前传递样式。@forward规则加载样式,就好像它们是在目标文件中定义的一样。

//_box.scss
@use 'button';
@forward 'button'; // 从_button.scss中重新创建变量到当前文件中
.boxButton {
    padding: button.$padding; // 1rem;
}

//_newBox.scss
@use 'box';
.newBoxButton {
    padding: box.$padding // 1rem;
}

当然还有一些其他的用法,在这浅尝辄止,毕竟目前还没实战过,更多可以看Sass模块简介或者官方文档。

5、静默注释

静默注释,就是能在scss文件中看到,但是编译后的css文件中并没有这些注释,用双斜杠就是静默注释

body {
  color: #333; // 这种注释内容不会出现在生成的css文件中
  padding: 0; /* 这种注释内容会出现在生成的css文件中 */
}

还有一种,就是/**/出现在css中不合适的地方,也会被抹掉,比如下面这种,这种注释就不能写在css中

body {
  color /* 这块注释内容不会出现在生成的css中 */: #333;
  padding: 1; /* 这块注释内容也不会出现在生成的css中 */ 0;
}

6、混合器

粗浅理解,可以类同成JS的函数(简单理解),就是把某一段可以复用的抽取出来,并且用@mixin来定义,然后用@include来调用。这个也算得上是scss的精髓吧。

@mixin rounded-corners {
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  border-radius: 5px;
}

// 调用上面的混合器
notice {
  background-color: green;
  border: 2px solid #00aa00;
  @include rounded-corners;
}

注意:缺点就是太好用了,导致最终生成的样式表过大,导致加载过慢,所以应该控制一下

甚么时候可以使用

经验法则:能够为这个混合器想出一条很好的简短名字,比如rounded-corners fancy-font或者no-bullet。如果不行,那么可能不是很合适。名字最好是展示性语句,能够直接体现外观样式等。

混合器中的CSS规则

比如li没有前面的圆点,就可以这么写

@mixin no-bullets {
  list-style: none;
  li {
    list-style-image: none;
    list-style-type: none;
    margin-left: 0px;
  }
}

ul.plain {
  color: #444;
  @include no-bullets;
}

最终生成以下的文件。

ul.plain {
  color: #444;
  list-style: none;
}
ul.plain li {
  list-style-image: none;
  list-style-type: none;
  margin-left: 0px;
}

给混合器传参

跟js的function很像,还能给定默认参数值

// 也可以设置默认的参数值
@mixin link-colors(
    $normal,
    $hover: $normal,
    $visited: $normal
  )
{
  color: $normal;
  &:hover { color: $hover; }
  &:visited { color: $visited; }
}

a {
  // 调用传参
  @include link-colors(blue, red, green);
}

//Scss最终生成的是:
a { color: blue; }
a:hover { color: red; }
a:visited { color: green; }

7、选择器继承

可以通过@extend继承另一个选择器定义所有的样式。

//通过选择器继承继承样式
.error {
  border: 1px solid red;
  background-color: #fdd;
}
.seriousError {
  @extend .error;
  border-width: 3px;
}

而且不仅会继承.error的所有样式,任何和.error有关的组合选择器样式也会被.seriousError以组合选择器的形式继承。

//.seriousError从.error继承样式
.error a{  //应用到.seriousError a
  color: red;
  font-weight: 100;
}
h1.error { //应用到hl.seriousError
  font-size: 1.2rem;
}

When使用

没看懂,和混合的具体使用场景没有一个非常明确的边界。到时候看自己的感觉来选择使用好了。

继承有一个特点,就是不能够使用分配法,用的全都是精准匹配(大概,没细究)。

举例来说, 如果.seriousError @extend .important.error , 那么.important.errorh1.important.error 的样式都会被.seriousError继承, 但是.important或者.error下的样式则不会被继承。

如果一个选择器序列(#main .seriousError@extend另一个选择器(.error),那么只有完全匹配#main .seriousError这个选择器的元素才会继承.error的样式,就像单个类名继承那样。拥有class="seriousError"#main元素之外的元素不会受到影响。

  • 跟混合器相比,继承生成的css代码相对更少。因为继承仅仅是重复选择器,而不会重复属性,所以使用继承往往比混合器生成的css体积更小。如果你非常关心你站点的速度,请牢记这一点。
  • 继承遵从css层叠的规则。当两个不同的css规则应用到同一个html元素上时,并且这两个不同的css规则对同一属性的修饰存在不同的值,css层叠规则会决定应用哪个样式。相当直观:通常权重更高的选择器胜出,如果权重相同,定义在后边的规则胜出。

最佳实践:一句话,可以继承有后代选择器修饰规则的选择器,不管后代选择器多长,但不要用后代选择器去继承。

8、其他

dart-sass和node-sass的区别

都是用来将sass编译成css的工具。

  • node-sass 是用 node(调用 cpp 编写的 libsass)来编译 sass;
    dart-sass 是用 drat VM 来编译 sass;
  • node-sass是自动编译实时的,dart-sass需要保存后才会生效
    推荐 dart-sass 性能更好(也是 sass 官方使用的),而且 node-sass 因为国情问题经常装不上。

现在npm管理的sass包,用的就是dart-sass,所以现在默认就是dart-sass。不建议使用node-sass库了,久而久之就不会维护了。

sass-loader是什么东西

是webpack加载scss文件并将他们编译为css文件。

⚠ Node Sass不支持@use rule。

顺带讲一下自己之前看过不理解的两个东西,一个是css-loader,另一个是style-loader。

在js中引用css文件,会用到css-loader,他会处理css文件,解析成对应的文本,然后style-loader根据这些文本,创建style标签,并且挂载到html标签上,所以这两个基本上是合在一块使用,不分开的。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇