【Sass初级】嵌套选择器规则
在CSS中,我们都知道所有代码都在一个“根级别”的选择器中,每个CSS的样式声明都写嵌套的话,那意客味需要写很多的代码。
今天我要带领大家进入到Sass的最基本原则中。这就是所谓的“基础规则(Inception rule)”。此规则可以帮助你避免一些常见错误(使用Sass的常见错误),不管是你Sass的初学者,还是中级或者高级Sass开发者。
就拿下面的代码为例:
.post {
border-radius: 3px;
background: #FFF8FF;
border: 1px solid #EFC6F3;
padding: 15px;
color: #333333;
}
.post .title, .post .alt-title {
color: #000000;
font-size:20px;
}
.post .alt-title {
border-bottom:1px solid #EFC6F3;
}
奇怪的是,你在使用CSS的时候,一旦你被卡住的时候,你会考虑加载其它的类名,如此一来,你的HTML就看不到明于,你是否在你的结构中同时加过五个类名呢?
<div class="post complete highlight rounded clearfix">...</div>
这难道就是你日常生活中所说的,面包和奶油我都要吗?其实我认为这样让我无法享受CSS开发的乐趣。然而,只要Sass进入你的生活中,你会发现这样使用CSS太过时了。
结合Sass使用很容易,但也很容易的错误使用它。
当你在工作中开始使用Sass的时候,第一个让你喜欢的特性就是“选择器嵌套”。如果能根据选择嵌套让你节省少敲键盘等事情,这将是一个很奇特事情。
我们来的看下面的一个示例,这就是Sass中的选择器的嵌套:
$border: 1px solid #EFC6F3;
.post {
border-radius: 3px;
background: #FFF8FF;
border: 1px solid $border;
padding: 15px;
color: #333333;
.title {
color: #000000;
font-size:20px;
}
.alt-title {
@extend .title;
border-bottom:1px solid $border;
}
}
上面的代码会输出相同的CSS。下面的代码就是Sass编译出来的CSS,所以你可以看看是如何转换成CSS的。
.post {
border-radius: 3px;
background: #FFF8FF;
border: 1px solid 1px solid #efc6f3;
padding: 15px;
color: #333333;
}
.post .title, .post .alt-title {
color: #000000;
font-size: 20px;
}
.post .alt-title {
border-bottom: 1px solid 1px solid #efc6f3;
}
所以这些就像孩子玩他的玩具一样,我们开始使用他们的功能,认为是他们的“最大潜力”。但实际情况是什么时候应该这样调用,这又将是CSS选择器的一个噩梦。
CSS选择器的噩梦
对于前端工程师来说,其噩梦就是样式臃肿,而且下DOM紧密耦合在一起,你修改有关于结构的内容就会影响破坏前端的呈现。
让我们来看一个不怎么好的HTML结构:
<body>
<div class="container">
<div class="content">
<div class="articles">
<div class="post">
<div class="title">
<h1><a href="#">Hello World</a>
</div>
<div class="content">
<p></p>
<ul>
<li>...</li>
</ul>
</div>
<div class="author">
<a href="#" class="display"><img src="..." /></a>
<h4><a href="#">...</a></h4>
<p>
<a href="#">...</a>
<ul>
<li>...</li>
</ul>
</p>
</div>
</div>
</div>
</div>
</div>
</body>
因为Sass给你提供了这方面的功能,你可以让你的选择器嵌套在里面,你的代码封装在一起,避免了与其他样式的冲突问题。你可能发现在Sass中的代码类似于你的DOM结构的嵌套。(这是不好的一种想法)。
来看一段不合理的Sass代码,类似不好的HTML的DOM结构:
body {
div.container {
div.content {
div.articles {
& > div.post {
div.title {
h1 {
a {
}
}
}
div.content {
p { ... }
ul {
li { ... }
}
}
div.author {
a.display {
img { ... }
}
h4 {
a { ... }
}
p {
a { ... }
}
ul {
li { ... }
}
}
}
}
}
}
}
这样都好,对吗?使用上面的选择器,你百分之百的可以预测到什么时候会发生什么?没有级联可以击败选择器的权重。
有关于CSS选择器权重的相关知识,可以阅读@99早前根据Vitaly Friedman的《CSS Specificity: Things You Should Know》所译的文章《你应该知道的一些事情——CSS权重》,文章中详细介绍了选择器权重相关知识。——@大漠
Sass编译之后,我们看到这样的一个结果,你会发现我们创建了一个极差劲的CSS。唉!
body { ... }
body div.content div.container { ... }
body div.content div.container div.articles { ... }
body div.content div.container div.articles > div.post { ... }
body div.content div.container div.articles > div.post div.title { ... }
body div.content div.container div.articles > div.post div.title h1 { ... }
body div.content div.container div.articles > div.post div.title h1 a { ... }
body div.content div.container div.articles > div.post div.content { ... }
body div.content div.container div.articles > div.post div.content p { ... }
body div.content div.container div.articles > div.post div.content ul { ... }
body div.content div.container div.articles > div.post div.content ul li { ... }
body div.content div.container div.articles > div.post div.author { ... }
body div.content div.container div.articles > div.post div.author a.display { ... }
body div.content div.container div.articles > div.post div.author a.display img { ... }
body div.content div.container div.articles > div.post div.author h4 { ... }
body div.content div.container div.articles > div.post div.author h4 a { ... }
body div.content div.container div.articles > div.post div.author p { ... }
body div.content div.container div.articles > div.post div.author p a { ... }
body div.content div.container div.articles > div.post div.author ul { ... }
body div.content div.container div.articles > div.post div.author ul li { ... }
有很多原因可以证明,这完全是错误的,从渲染到文件的大小等都足以说明。试想想,这是加了多少的字节,文件大小直接受影响,或许你会保守的说:
嘿,电脑速度很快。互联网下载速度也比较快!——用户谁不喜欢前端工程师
但是,这并不是唯一的一个问题,你的样式非常类似于DOM结构,可维护就变成一个问题。
你的结构做任何的修改都需要告诉Sass,反之也是如此。这也意味着,样式和结构完全违背了“级联”的部分宗旨。也就是所说的“层叠样式表”。
如果你这样写,还不如回到当初的年代,把CSS直接写到HTML的结构中。(请不要这样做)。
满足简单规则
为了防止你陷入这样的噩梦之中,我创建了一些简单的规则。到现在为止,这个规则虽然还不成文,但还是有蛮多人跟着使用。
这个规则就是:不要让你的嵌套层级超过四个层级。
这也就意味着你不需要一味的模仿DOM结构中的任何一点。如果你发现你的嵌套的层级忆超过四层,那这将是一个危险的信号。当然,有时候你为了需要,而不得不这样做,但你不能像这样做得太多。
让嵌套在四层或更少层级内
一旦你理解选择器的具体问题之后,你需要考虑的是如何让你的代码更通用,需要改善你的环境,对象和交互状态等。
网站内容
如果你的结构没有类名或ID,那么你至少需要一个标签。很好的例子就是,像h1
~h6
,ul
和p
有一个默认的样式。
有可能在一些环境下,你需要覆盖一些样式,这时你可能要增加几个选择器。当涉及到网站内容上下文时,使用具有一定特色的选择。
页面内容(布局、侧边栏宽度和高度)
如果你是写布局的样式(侧边栏和内容维度,也就是根据页面上下内容元素而有所不同),那么你讨论的将是在页面中的上下文。通常你需要两个级别的缩进来达到你需要的目的。但是请记住,你应该只指定样式,而不是对象自身。下一节我们将讨论对像。
下面的示例就是我想要说的意思:
.cart {
#sidebar { width: 150px; }
#content { width: 850px; }
}
对象
一个元素就是一个对象,他有可能就是自身,也有可能带有子元素(或后代元素),通常使用一个类名或ID来定义这个对象。这也是你代码中常见的一种类型。对象可以是任何东西,应该被当作一个整体传到你的页面中。你也可以将对象作为一个基本样式,然后需要的时候使用页面内容来修改他。
下面是常用的一些元素当对象使用的示例:
#sideabr
#content
#footer
.blog-post
.comment
.widget
.logo
.user
.button
你通常会设置一个顶层的类来识别对象,并将其做为一个基本的选择器,在那你应该使用最普通的选择器来写样式:
ul.special-deal {
...
li {...}
a {...}
}
请注意,对象最多只能是四层嵌套。大多数时候你只写两到三层嵌套,至少要留一个层级给交互。
交互状态
当你与对象有交互状态时,交互状态会包括什么。当你有交互的时候,你的对象层级嵌套有可能接近或超过四层。这是预期的,并且是可以接受的。
切记
- 聪明:想想编译器是如何创建你的代码,并问自己,它生成的代码是自己真正需要的CSS吗?我总是问自己,这种风格还有更简单的选择器来实现?
- 灵巧:使用编译器为你提供的一切。例如,使用
@extend
指令或mixin。每一个都有其自身的意义。 - 记录:如果添加一个声明会影响你全局的HTML标签,你应该留一个言,将其记录下来。当数周或数月后,你再看你的代码,你知道发生了什么。注释是你很好的朋友,如果你要嵌套
article
、aside
、section
和h3
这样的,你最好有一个很好的理由。 - 创意:有没有一种方法,在没有增加额外的类名能使HTML与CSS更好的一起工作呢?如果有,他不影响语义做到这一点。我的意思是使用相邻选择器或子选择器等等来实现。只有知道你Sass中嵌套的层级才知道你的CSS规则。
- 适度:任何事情滥用都是不好的。有疑问时要用你的常识来判断。
译者手语:整个翻译依照原文线路进行,并在翻译过程略加了个人对技术的理解。如果翻译有不对之处,还烦请同行朋友指点。谢谢!
如需转载,烦请注明出处:
英文出处:http://thesassway.com/beginner/the-inception-rule
中文译文:http://www.w3cplus.com/preprocessor/beginner/the-inception-rule.html