CssandSass
学习视频:https://www.youtube.com/watch?v=_a5j7KoflTs&list=WL&index=6
Documentation:https://sass-lang.com/documentation
引用的一些教程: w3cschool,菜鸟教程
Install/Setup Live Sass Compiler VS Code Extension
Live Sass Compiler
在setting.json中添加设置
1 | "liveSassCompile.settings.formats": [ |
新建dist文件夹,里面新建index.html文件,引入css/main.css
1 |
|
然后新建scss文件夹,里面新建一个main.css文件
点击 下面的sass watching,那么就会在dist文件夹下自动生成编译好的css文件,这样在scss中做了改变,main.css中也会同步编译,转换成html读得懂的css文件
Folder Structure / Sass Syntax
Variables
sass
让人们受益的一个重要特性就是它为css
引入了变量。你可以把反复使用的css
属性值定义成变量,然后通过变量名来引用它们,而无需重复书写这一属性值。或者,对于仅使用过一次的属性值,你可以赋予其一个易懂的变量名,让人一眼就知道这个属性值的用途。
sass
使用是多半因为!highlight-color
看起来太丑了。),比如符号呢?因为它好认、更具美感,且在CSS中并无他用,不会导致与现存或未来的css
语法冲突。
sass
变量的声明和css
属性的声明很像:
1 | $highlight-color: #F90; |
这意味着变量$highlight-color
现在的值是#F90
。任何可以用作css
属性值的赋值都可以用作sass
的变量值,甚至是以空格分割的多个属性值,如$basic-border: 1px solidblack;
,或以逗号分割的多个属性值,如$plain-font: "Myriad Pro"、Myriad、"HelveticaNeue"、Helvetica、"Liberation Sans"、Arial和sans-serif; sans-serif;
。这时变量还没有生效,除非你引用这个变量——我们很快就会了解如何引用。
与CSS
属性不同,变量可以在css
规则块定义之外存在。当变量定义在css
规则块内,那么该变量只能在此规则块内使用。如果它们出现在任何形式的{...}
块中(如@media
或者@font-face
块),情况也是如此:
1 | $nav-color: #F90; |
在这段代码中,$nav-color
这个变量定义在了规则块外边,所以在这个样式表中都可以像nav
规则块那样引用它。$width
这个变量定义在了nav
的{ }
规则块内,所以它只能在nav
规则块内使用。这意味着是你可以在样式表的其他地方定义和使用$width
变量,不会对这里造成影响。
凡是css
属性的标准值可存在的地方,变量就可以使用。css
生成时,变量会被它们的值所替代。之后,如果你需要一个不同的值,只需要改变这个变量的值,则所有引用此变量的地方生成的值都会随之改变。
1 | $highlight-color: #F90; |
看上边示例中的$highlight-color
变量,它被直接赋值给border
属性,当这段代码被编译输出css
时,$highlight-color
会被#F90
这一颜色值所替代。产生的效果就是给selected
这个类一条1像素宽、实心且颜色值为#F90
的边框。
在声明变量时,变量值也可以引用其他变量。当你通过粒度区分,为不同的值取不同名字时,这相当有用。下例在独立的颜色值粒度上定义了一个变量,且在另一个更复杂的边框值粒度上也定义了一个变量:
1 | $highlight-color: #F90; |
这里,$highlight-border
变量的声明中使用了$highlight-color
这个变量。产生的效果就跟你直接为border
属性设置了一个1px
$highlight-color solid
的值是一样的。
Maps
Sass Maps的函数 : map-get($map,$key)
map-get($map,$key)
函数的作用是根据 $key 参数,返回 $key 在 $map 中对应的 value 值。如果 $key 不存在 $map
中,将返回 null 值。此函数包括两个参数:
$map:
定义好的 map。$key:
需要遍历的 key。
1 | //我这里定义了四个变量,其中最后一个是一个map |
在main.css 中编译结果为:
1 | body { |
Nesting
父选择器的标识符&
一般情况下,sass
在解开一个嵌套规则时就会把父选择器(#content
)通过一个空格连接到子选择器的前边(article
和aside
)形成(#content article
和#content aside
)。这种在CSS里边被称为后代选择器,因为它选择ID为content
的元素内所有命中选择器article
和aside
的元素。但在有些情况下你却不会希望sass
使用这种后代选择器的方式生成这种连接。
最常见的一种情况是当你为链接之类的元素写:hover
这种伪类时,你并不希望以后代选择器的方式连接。比如说,下面这种情况sass
就无法正常工作:
1 | article a { |
这意味着color: red
这条规则将会被应用到选择器article a :hover
,article
元素内链接的所有子元素在被hover
时都会变成红色。这是不正确的!你想把这条规则应用到超链接自身,而后代选择器的方式无法帮你实现。
解决之道为使用一个特殊的sass
选择器,即父选择器。在使用嵌套规则时,父选择器能对于嵌套规则如何解开提供更好的控制。它就是一个简单的&
符号,且可以放在任何一个选择器可出现的地方,比如h1
放在哪,它就可以放在哪。
& 就代表着父选择器, & = article a
1 | article a { |
当包含父选择器标识符的嵌套规则被打开时,它不会像后代选择器那样进行拼接,而是&
被父选择器直接替换:
1 | article a { color: blue } |
在为父级选择器添加:hover
等伪类时,这种方式非常有用。同时父选择器标识符还有另外一种用法,你可以在父选择器之前添加选择器。举例来说,当用户在使用IE浏览器时,你会通过JavaScript
在``标签上添加一个ie的类名,为这种情况编写特殊的样式如下:
1 | #content aside { |
sass
在选择器嵌套上是非常智能的,即使是带有父选择器的情况。当sass
遇到群组选择器(由多个逗号分隔开的选择器形成)也能完美地处理这种嵌套。
Example
main.scss
&_paragraph
在编译完成后 是.main_paragraph
但是从index.html中我们可以看到我们想选择的是 class = main包含着的 class= main_paragraph 的段落
所以我们可以这么修改
#{&}_paragraph
这叫 interpolation 现在 css文件中 变成了 .main .main_paragraph
此外我们还可以在嵌套中利用嵌套,那么就是在 #{&}_paragraph
中再用 &
因为这里只是设置一个伪类,那么不需要 #{&},直接相连结即可, &:hover
效果如下
.main .main_paragraph:hover
也就是现在当我鼠标移动到这段文字上的时候,文字会变成粉色
1 | .main { |
index.html
1 |
|
main.css
1 | body { |
群组选择器的嵌套
在CSS
里边,选择器h1
h2
和h3
会同时命中h1元素、h2元素和h3元素。与此类似,.button
button
会命中button元素和类名为.button的元素。这种选择器称为群组选择器。群组选择器的规则会对命中群组中任何一个选择器的元素生效。
1 | .button, button { |
当看到上边这段代码时,你可能还没意识到会有重复性的工作。但会很快发现:如果你需要在一个特定的容器元素内对这样一个群组选择器进行修饰,情况就不同了。css
的写法会让你在群组选择器中的每一个选择器前都重复一遍容器元素的选择器。
1 | .container h1, .container h2, .container h3 { |
非常幸运,sass
的嵌套特性在这种场景下也非常有用。当sass
解开一个群组选择器规则内嵌的规则时,它会把每一个内嵌选择器的规则都正确地解出来:
1 | .container { |
首先sass
将.container
和h1
.container
和h2
.container
和h3
分别组合,然后将三者重新组合成一个群组选择器,生成你前边看到的普通css
样式。
对于内嵌在群组选择器内的嵌套规则,处理方式也一样:
1 | nav, aside { |
首先sass
将nav
和a
aside
和a
分别组合,然后将二者重新组合成一个群组选择器:
1 | nav a, aside a {color: blue} |
处理这种群组选择器规则嵌套上的强大能力,正是sass
在减少重复敲写方面的贡献之一。尤其在当嵌套级别达到两层甚至三层以上时,与普通的css
编写方式相比,只写一遍群组选择器大大减少了工作量。
有利必有弊,你需要特别注意群组选择器的规则嵌套生成的css
。虽然sass
让你的样式表看上去很小,但实际生成的css
却可能非常大,这会降低网站的速度。
关于选择器嵌套的最后一个方面,我们看看sass
如何处理组合选择器,比如>、+和~的使用。你将看到,这种场景下你甚至无需使用父选择器标识符。
子组合选择器和同层组合选择器:>、+和~
上边这三个组合选择器必须和其他选择器配合使用,以指定浏览器仅选择某种特定上下文中的元素。
1 | article section { margin: 5px } |
你可以用子组合选择器>选择一个元素的直接子元素。上例中,第一个选择器会选择article下的所有命中section选择器的元素。第二个选择器只会选择article下紧跟着的子元素中名为section选择器的元素。
在下例中,你可以用同层相邻组合选择器+
选择header
元素后紧跟的p
元素:
1 | header + p { font-size: 1.1em } |
你也可以用同层全体组合选择器~
,选择所有跟在article
后的同层article
元素,不管它们之间隔了多少其他元素:
1 | article ~ article { border-top: 1px dashed #ccc } |
这些组合选择器可以毫不费力地应用到sass
的规则嵌套中。可以把它们放在外层选择器后边,或里层选择器前边:
1 | article { |
sass
会如你所愿地将这些嵌套规则一一解开组合在一起:
1 | article ~ article { border-top: 1px dashed #ccc } |
在sass
中,不仅仅css
规则可以嵌套,对属性进行嵌套也可以减少很多重复性的工作。
嵌套属性
在sass
中,除了CSS选择器,属性也可以进行嵌套。尽管编写属性涉及的重复不像编写选择器那么糟糕,但是要反复写border-style
border-width
border-color
以及border-*
等也是非常烦人的。在sass
中,你只需敲写一遍border
:
1 | nav { |
嵌套属性的规则是这样的:把属性名从中划线-的地方断开,在根属性后边添加一个冒号:,紧跟一个{ }
块,把子属性部分写在这个{ }
块中。就像css
选择器嵌套一样,sass
会把你的子属性一一解开,把根属性和子属性部分通过中划线-连接起来,最后生成的效果与你手动一遍遍写的css
样式一样:
1 | nav { |
对于属性的缩写形式,你甚至可以像下边这样来嵌套,指明例外规则:
1 | nav { |
这比下边这种同等样式的写法要好:
1 | nav { |
属性和选择器嵌套是非常伟大的特性,因为它们不仅大大减少了你的编写量,而且通过视觉上的缩进使你编写的样式结构更加清晰,更易于阅读和开发。
即便如此,随着你的样式表变得越来越大,这种写法也很难保持结构清晰。有时,处理这种大量样式的唯一方法就是把它们分拆到多个文件中。sass
通过对css
原有@import
规则的改进直接支持了这一特性。
Partials
当通过@import
把sass
样式分散到多个文件时,你通常只想生成少数几个css
文件。那些专门为@import
命令而编写的sass
文件,并不需要生成对应的独立css
文件,这样的sass
文件称为局部文件。对此,sass
有一个特殊的约定来命名这些文件。
此约定即,sass
局部文件的文件名以下划线开头。这样,sass
就不会在编译时单独编译这个文件输出css
,而只把这个文件用作导入。当你@import
一个局部文件时,还可以不写文件的全名,即省略文件名开头的下划线。举例来说,你想导入themes/_night-sky.scss
这个局部文件里的变量,你只需在样式表中写@import
"themes/night-sky";
。
比如,我们新建 _reset.scss
和_variable.scss
1 | * { |
1 | $primary-color: #272727; |
在main.scss中通过 @import 引入
1 | @import "./reset"; |
局部文件可以被多个不同的文件引用。当一些样式需要在多个页面甚至多个项目中使用时,这非常有用。在这种情况下,有时需要在你的样式表中对导入的样式稍作修改,sass
有一个功能刚好可以解决这个问题,即默认变量值。
默认变量值
一般情况下,你反复声明一个变量,只有最后一处声明有效且它会覆盖前边的值。举例说明:
1 | $link-color: blue; |
在上边的例子中,超链接的color
会被设置为red
。这可能并不是你想要的结果,假如你写了一个可被他人通过@import
导入的sass
库文件,你可能希望导入者可以定制修改sass
库文件中的某些值。使用sass
的!default
标签可以实现这个目的。它很像css
属性中!important
标签的对立面,不同的是!default
用于变量,含义是:如果这个变量被声明赋值了,那就用它声明的值,否则就用这个默认值。
1 | $fancybox-width: 400px !default; |
在上例中,如果用户在导入你的sass
局部文件之前声明了一个$fancybox-width
变量,那么你的局部文件中对$fancybox-width
赋值400px
的操作就无效。如果用户没有做这样的声明,则$fancybox-width
将默认为400px
。
接下来我们将学习嵌套导入,它允许只在某一个选择器的范围内导入sass
局部文件。
嵌套导入
跟原生的css
不同,sass
允许@import
命令写在css
规则内。这种导入方式下,生成对应的css
文件时,局部文件会被直接插入到css
规则内导入它的地方。举例说明,有一个名为_blue-theme.scss
的局部文件,内容如下:
1 | aside { |
然后把它导入到一个CSS规则内,如下所示:
1 | .blue-theme {@import "blue-theme"} |
被导入的局部文件中定义的所有变量和混合器,也会在这个规则范围内生效。这些变量和混合器不会全局有效,这样我们就可以通过嵌套导入只对站点中某一特定区域运用某种颜色主题或其他通过变量配置的样式。
有时,可用css
原生的@import
机制,在浏览器中下载必需的css
文件。sass
也提供了几种方法来达成这种需求。
原生的CSS导入
由于sass
兼容原生的css
,所以它也支持原生的CSS@import
。尽管通常在sass
中使用@import
时,sass
会尝试找到对应的sass
文件并导入进来,但在下列三种情况下会生成原生的CSS@import
,尽管这会造成浏览器解析css
时的额外下载:
- 被导入文件的名字以
.css
结尾; - 被导入文件的名字是一个URL地址(比如http://www.sass.hk/css/css.css),由此可用谷歌字体API提供的相应服务;
- 被导入文件的名字是
CSS
的url()值。
这就是说,你不能用sass
的@import
直接导入一个原始的css
文件,因为sass
会认为你想用css
原生的@import
。但是,因为sass
的语法完全兼容css
,所以你可以把原始的css
文件改名为.scss
后缀,即可直接导入了。
文件导入是保证sass
的代码可维护性和可读性的重要一环。次之但亦非常重要的就是注释了。注释可以帮助样式作者记录写sass
的过程中的想法。在原生的css
中,注释对于其他人是直接可见的,但sass
提供了一种方式可在生成的css
文件中按需抹掉相应的注释。
静默注释
css
中注释的作用包括帮助你组织样式、以后你看自己的代码时明白为什么这样写,以及简单的样式说明。但是,你并不希望每个浏览网站源码的人都能看到所有注释。
sass
另外提供了一种不同于css
标准注释格式/* ... */
的注释语法,即静默注释,其内容不会出现在生成的css
文件中。静默注释的语法跟JavaScript``Java
等类C
的语言中单行注释的语法相同,它们以//
开头,注释内容直到行末。
1 | body { |
实际上,css
的标准注释格式/* ... */
内的注释内容亦可在生成的css
文件中抹去。当注释出现在原生css
不允许的地方,如在css
属性或选择器中,sass
将不知如何将其生成到对应css
文件中的相应位置,于是这些注释被抹掉。
1 | body { |
Functions
font-weights 是上面导入中的map变量
1 | @function weight($weight-name) { |
然后我们调用这个function即可
1 | #{&}_paragraph { |
Mixin
利用混合器,可以很容易地在样式表的不同地方共享样式。如果你发现自己在不停地重复一段样式,那就应该把这段样式构造成优良的混合器,尤其是这段样式本身就是一个逻辑单元,比如说是一组放在一起有意义的属性。
判断一组属性是否应该组合成一个混合器,一条经验法则就是你能否为这个混合器想出一个好的名字。如果你能找到一个很好的短名字来描述这些属性修饰的样式,比如rounded-corners
fancy-font
或者no-bullets
,那么往往能够构造一个合适的混合器。如果你找不到,这时候构造一个混合器可能并不合适。
混合器在某些方面跟css
类很像。都是让你给一大段样式命名,所以在选择使用哪个的时候可能会产生疑惑。最重要的区别就是类名是在html
文件中应用的,而混合器是在样式表中应用的。这就意味着类名具有语义化含义,而不仅仅是一种展示性的描述:用来描述html
元素的含义而不是html
元素的外观。而另一方面,混合器是展示性的描述,用来描述一条css
规则应用之后会产生怎样的效果。
在之前的例子中,.notice
是一个有语义的类名。如果一个html
元素有一个notice
的类名,就表明了这个html
元素的用途:向用户展示提醒信息。rounded-corners
混合器是展示性的,它描述了包含它的css
规则最终的视觉样式,尤其是边框角的视觉样式。混合器和类配合使用写出整洁的html
和css
,因为使用语义化的类名亦可以帮你避免重复使用混合器。为了保持你的html
和css
的易读性和可维护性,在写样式的过程中一定要铭记二者的区别。
有时候仅仅把属性放在混合器中还远远不够,可喜的是,sass
同样允许你把css
规则放在混合器中。
混合器中的CSS规则
混合器中不仅可以包含属性,也可以包含css
规则,包含选择器和选择器中的属性,如下代码:
1 | @mixin no-bullets { |
当一个包含css
规则的混合器通过@include
包含在一个父规则中时,在混合器中的规则最终会生成父规则中的嵌套规则。举个例子,看看下边的sass
代码,这个例子中使用了no-bullets
这个混合器:
1 | ul.plain { |
sass
的@include
指令会将引入混合器的那行代码替换成混合器里边的内容。最终,上边的例子如下代码:
1 | ul.plain { |
混合器中的规则甚至可以使用sass
的父选择器标识符&
。使用起来跟不用混合器时一样,sass
解开嵌套规则时,用父规则中的选择器替代&
。
如果一个混合器只包含css
规则,不包含属性,那么这个混合器就可以在文档的顶部调用,写在所有的css
规则之外。如果你只是为自己写一些混合器,这并没有什么大的用途,但是当你使用一个类似于Compass
的库时,你会发现,这是提供样式的好方法,原因在于你可以选择是否使用这些样式。
接下来你将学习如何通过给混合器传参数来让混合器变得更加灵活和可重用。
给混合器传参
混合器并不一定总得生成相同的样式。可以通过在@include
混合器时给混合器传参,来定制混合器生成的精确样式。当@include
混合器时,参数其实就是可以赋值给css
属性值的变量。如果你写过JavaScript
,这种方式跟JavaScript
的function
很像:
1 | @mixin link-colors($normal, $hover, $visited) { |
当混合器被@include
时,你可以把它当作一个css
函数来传参。如果你像下边这样写:
1 | a { |
当你@include混合器时,有时候可能会很难区分每个参数是什么意思,参数之间是一个什么样的顺序。为了解决这个问题,sass
允许通过语法$name: value
的形式指定每个参数的值。这种形式的传参,参数顺序就不必再在乎了,只需要保证没有漏掉参数即可:
1 | a { |
尽管给混合器加参数来实现定制很好,但是有时有些参数我们没有定制的需要,这时候也需要赋值一个变量就变成很痛苦的事情了。所以sass
允许混合器声明时给参数赋默认值。
默认参数值
为了在@include
混合器时不必传入所有的参数,我们可以给参数指定一个默认值。参数默认值使用$name: default-value
的声明形式,默认值可以是任何有效的css
属性值,甚至是其他参数的引用,如下代码:
1 | @mixin link-colors( |
如果像下边这样调用:@include link-colors(red)
$hover
和$visited
也会被自动赋值为red
。
Mixin Example 1
Mixin Example 1
display
https://www.runoob.com/cssref/pr-class-display.html
justify-content
https://www.runoob.com/cssref/css3-pr-justify-content.html
align-items
https://www.runoob.com/cssref/css3-pr-align-items.html
margin
https://www.runoob.com/cssref/pr-margin.html
flex-direction
https://www.runoob.com/cssref/css3-pr-flex-direction.html
没用mixin之前,我们可以这样设置
1 | .main { |
但是我们不想重复敲打 display,justify-content 之类的,所以我们使用mixin改造
1 | @mixin flexCenter($direction) { |
现在他们在同一列中了
如果传入的参数是row,
Mixin Example 2
首先在html中把body改成 < body class="light" >
我们可以 像下面这样传入参数,也可以 @include theme();
1 | //默认传参为true |
现在变成了白底黑字了
Mixin Example 3
当我们的screen 小于800px的时候,文字就会从
变成这样
1 | $moblie: 800px; |
Extend
混合器只是sass
样式重用特性中的一个。我们已经了解到混合器主要用于样式展示层的重用,如果你想重用语义化的类呢?这就涉及sass
的另一个重要的重用特性:选择器继承。
何时使用继承
之前介绍了混合器主要用于展示性样式的重用,而类名用于语义化样式的重用。因为继承是基于类的(有时是基于其他类型的选择器),所以继承应该是建立在语义化的关系上。当一个元素拥有的类(比如说.seriousError
)表明它属于另一个类(比如说.error
),这时使用继承再合适不过了。
这有点抽象,所以我们从几个方面来阐释一下。想象一下你正在编写一个页面,给html
元素添加类名,你发现你的某个类(比如说.seriousError
)另一个类(比如说.error
)的细化。你会怎么做?
- 你可以为这两个类分别写相同的样式,但是如果有大量的重复怎么办?使用
sass
时,我们提倡的就是不要做重复的工作。 - 你可以使用一个选择器组(比如说
.error
.seriousError
给这两个选择器写相同的样式。如果.error的所有样式都在同一个地方,这种做法很好,但是如果是分散在样式表的不同地方呢?再这样做就困难多了。 - 你可以使用一个混合器为这两个类提供相同的样式,但当
.error
的样式修饰遍布样式表中各处时,这种做法面临着跟使用选择器组一样的问题。这两个类也不是恰好有相同的样式。你应该更清晰地表达这种关系。 - 综上所述你应该使用
@extend
。让.seriousError
从.error
继承样式,使两者之间的关系非常清晰。更重要的是无论你在样式表的哪里使用.error``.seriousError
都会继承其中的样式。
现在你已经更好地掌握了何时使用继承,以及继承有哪些突出的优点,接下来我们看看一些高级用法。
继承的高级用法
任何css
规则都可以继承其他规则,几乎任何css
规则也都可以被继承。大多数情况你可能只想对类使用继承,但是有些场合你可能想做得更多。最常用的一种高级用法是继承一个html
元素的样式。尽管默认的浏览器样式不会被继承,因为它们不属于样式表中的样式,但是你对html
元素添加的所有样式都会被继承。
接下来的这段代码定义了一个名为disabled
的类,样式修饰使它看上去像一个灰掉的超链接。通过继承a这一超链接元素来实现:
1 | .disabled { |
假如一条样式规则继承了一个复杂的选择器,那么它只会继承这个复杂选择器命中的元素所应用的样式。举例来说, 如果.seriousError@extend.important.error
, 那么.important.error
和h1.important.error
的样式都会被.seriousError
继承, 但是.important
或者.error
下的样式则不会被继承。这种情况下你很可能希望.seriousError
能够分别继承.important
或者.error
下的样式。
如果一个选择器序列(#main .seriousError
)@extend
另一个选择器(.error
),那么只有完全命中#main .seriousError
这个选择器的元素才会继承.error
的样式,就像单个类名继承那样。拥有class="seriousError"
的.main
元素之外的元素不会受到影响。
像#main .error
这种选择器序列是不能被继承的。这是因为从#main .error
中继承的样式一般情况下会跟直接从.error
中继承的样式基本一致,细微的区别往往使人迷惑。
现在你已经了解了通过继承能够做些什么事情,接下来我们将学习继承的工作细节,在生成对应css
的时候,sass
具体干了些什么事情。
继承的工作细节
跟变量和混合器不同,继承不是仅仅用css
样式替换@extend处的代码那么简单。为了不让你对生成的css
感觉奇怪,对这背后的工作原理有一定了解是非常重要的。
@extend
背后最基本的想法是,如果.seriousError @extend .error
, 那么样式表中的任何一处.error
都用.error
.seriousError
这一选择器组进行替换。这就意味着相关样式会如预期那样应用到.error
和.seriousError
。当.error
出现在复杂的选择器中,比如说h1.error``.error a
或者#main .sidebar input.error[type="text"]
,那情况就变得复杂多了,但是不用担心,sass
已经为你考虑到了这些。
关于@extend
有两个要点你应该知道。
- 跟混合器相比,继承生成的
css
代码相对更少。因为继承仅仅是重复选择器,而不会重复属性,所以使用继承往往比混合器生成的css
体积更小。如果你非常关心你站点的速度,请牢记这一点。 - 继承遵从
css
层叠的规则。当两个不同的css
规则应用到同一个html
元素上时,并且这两个不同的css
规则对同一属性的修饰存在不同的值,css
层叠规则会决定应用哪个样式。相当直观:通常权重更高的选择器胜出,如果权重相同,定义在后边的规则胜出。
混合器本身不会引起css
层叠的问题,因为混合器把样式直接放到了css
规则中,而继承存在样式层叠的问题。被继承的样式会保持原有定义位置和选择器权重不变。通常来说这并不会引起什么问题,但是知道这点总没有坏处。
使用继承的最佳实践
通常使用继承会让你的css
美观、整洁。因为继承只会在生成css
时复制选择器,而不会复制大段的css
属性。但是如果你不小心,可能会让生成的css
中包含大量的选择器复制。
避免这种情况出现的最好方法就是不要在css
规则中使用后代选择器(比如.foo .bar
)去继承css
规则。如果你这么做,同时被继承的css
规则有通过后代选择器修饰的样式,生成css
中的选择器的数量很快就会失控:
1 | .foo .bar { @extend .baz; } |
在上边的例子中,sass
必须保证应用到.baz的样式同时也要应用到.foo .bar
(位于class=”foo”的元素内的class=”bar”的元素)。例子中有一条应用到.bip .baz
(位于class=”bip”的元素内的class=”baz”的元素)的css
规则。当这条规则应用到.foo .bar
时,可能存在三种情况,如下代码:
1 | <!-- 继承可能迅速变复杂 --> |
为了应付这些情况,sass
必须生成三种选择器组合(仅仅是.bip .foo .bar不能覆盖所有情况)。如果任何一条规则里边的后代选择器再长一点,sass
需要考虑的情况就会更多。实际上sass
并不总是会生成所有可能的选择器组合,即使是这样,选择器的个数依然可能会变得相当大,所以如果允许,尽可能避免这种用法。
值得一提的是,只要你想,你完全可以放心地继承有后代选择器修饰规则的选择器,不管后代选择器多长,但有一个前提就是,不要用后代选择器去继承。
Example
index.html
1 | <!--//...--> |
1 | #{&}_paragraph1 { |
Math Operations
在原生css中,我们要计算必须这样 cal(80%-40%)
但在scss中可以直接这么写。但要保持单位相同!
1 | .main { |