CSS中的Cascade——层叠

CSS本质上就是声明规则,即在各种条件下,我们希望产生特定的效果。CSS开发很重要的一点就是以可预测的方式书写规则。但是当多条规则提供了冲突的样式时会发生什么呢?

一、层叠

层叠Cascade指的就是这一系列规则。它决定了如何解决冲突,是CSS语言的基础,让代码能以可预测的方式产生特定效果。
当声明冲突时,会依据三种条件解决冲突:

  • (1) 样式表的来源:样式是从哪里来的,外部文件、内联代码、行内样式、浏览器默认样式或者用户样式;
  • (2) 选择器优先级:哪些选择器比另一些选择器更重要。
  • (3) 代码顺序:规则的声明顺序。

534de323327741f9b630a665474ee5fe.jpg

 声明遇到冲突:先考虑来源,其次考虑优先级,最后考虑源码顺序

  1. 来源:!important(最高级的来源样式) 优先于 作者样式(自己写的样式); 作者样式 优先于 用户代理样式(浏览器默认样式);
  2. 优先级: 先考虑是否行内样式,若不是行内样式在考虑选择器问题;行内样式 优先于 样式表或style标签的样式;选择器:id 优先于 class ;class 优先于 标签选择器;
  3. 源码顺序:前两条都一样的话,出现在后面的样式覆盖出前面样式。

注意:不要混淆CSS的属性property和HTML的属性attribute

//一个规则集ruleset由一个声明块和一个选择器组成

//一个声明块由包含在大括号内的一组声明组成

body {

//一个css声明由一个属性和一个值组成
            color: black;
            font-family: Helvetica;
          }

@规则(at-rules)是指用“@”符号开头的语法。比如@import规则或者@media查询。

1. 样式表的来源

样式表的来源有3种,其优先级由高到低分别是:作者样式表author stylesheets、用户样式表user stylesheets、用户代理样式表(浏览器默认样式)user-agent stylesheets。

User-Agent Style 用户代理样式,浏览器也只是用户代理中的一种。在不同浏览器上稍有差异,但是大体上是在做相同的事情:为标题(<h1>到<h6>)和段落(<p>)添加上下外边距,为列表(<ol>和<ul>)添加左侧内边距,为链接添加颜色,为元素设置各种默认字号。

1.1 用户代理样式

浏览器应用了用户代理样式后才会应用你的样式表,即作者样式表。你指定的声明会覆盖用户代理样式表里的样式(优先级更高,应用层叠的样式来源规则)。

用户代理(User Agent),是指浏览器,还包括搜索引擎。它的信息包括硬件平台、系统软件、应用软件和用户个人偏好。

注意:避免在样式表使用ID选择器,统一在样式表使用类选择器,ID选择器更应该用来作为JavaScript选中元素的钩子将后端传回的数据展现到页面。

1.2 !important声明

标记了!important的声明会被当作更高优先级的来源。通过!important声明后优先级会比内联样式还高,但同时这也体现出它的两面性,一旦使用了该声明,后面的修改就不易修改了。

2. 理解优先级

如果无法用来源解决冲突声明,浏览器会尝试检查它们的优先级。

99%的网站样式是来自同样的源。所以相同的源内的代码样式冲突应考虑优先级来解决。

浏览器将优先级分为两部分:HTML的行内样式和选择器的样式。

2.1 行内样式

行内元素属于“带作用域的”声明,它会覆盖任何来自样式表或者<style>标签的样式。行内样式没有选择器,因为直接作用于当前元素。

若要覆盖行内样式,需在样式表使用!important;但是若行内样式使用了!important就无法覆盖了,最好只在样式表内使用!important。

2.2 选择器优先级

有多层选择器的样式块中,指向越明确越具体的样式块优先级越高。

优先级的准确规则如下:

❑ 如果选择器的ID数量更多,则它会胜出(即它更明确)。

❑ 如果ID选择器数量一致,那么拥有最多类的选择器胜出。

❑ 如果以上两次比较都一致,那么拥有最多标签名的选择器胜出。

注意:伪类选择器(如:hover)和属性选择器(如[type="input"])与一个类选择器的优先级相同。通用选择器(*)和组合器(>、+、~)对优先级没有影响。

2.3 优先级标记

一个常用的表示优先级的方式是用数值形式来标记,通常用逗号隔开每个数。比如,“1,2,2”表示选择器由1个ID、2个类、2个标签组成。优先级最高的ID列为第一位,紧接着是类,最后是标签。

c92a710384524804a7943aa2905c1b6c.jpg

 有时还会用4个数的标记,其中将最重要的位置用0或1来表示,代表一个声明是否是用行内样式添加的。此时,行内样式的优先级为“1,0,0,0”。它会覆盖通过选择器添加的样式,比如优先级为“0,1,2,0”(1个ID和2个类)的选择器。

2.4 关于优先级的思考

  1. 谨慎使用!important:它可能会解决当前问题,但是在后续更改时又容易引入新问题。若修改时使用!important又会重新比较两处!important代码的来源,再比较两处代码的优先级规则,又会进入新一轮的比较,最好利用选择器优先级解决当前问题。
  2. 尽量降低样式代码块的总体优先级,在后续更改时才有更多空间。

3. 源码顺序

如果两个声明的来源和优先级相同,其中一个声明在样式表中出现较晚,或者位于页面较晚引入的样式表中,则该声明胜出。

面对一个样式问题时,将其分两个步骤来解决它。首先确定哪些声明可以实现效果。其次,思考可以用哪些选择器结构,然后选择最符合需求的那个。限制样式的范围,避免在不需要该样式的地方出现。

3.1 链接样式和源码顺序

链接样式中的四个状态优先级相同,当元素同时处于多个状态,最后个样式会覆盖前面样式。这个顺序的记忆口诀是“LoVe/HAte”(“爱/恨”),即link(链接)、visited(访问)、hover(悬停)、active(激活)。

3.2 层叠值

浏览器遵循三个步骤,即来源、优先级、源码顺序,来解析网页上每个元素的每个属性。如果一个声明在层叠中“胜出”,它就被称作一个层叠值。元素的每个属性最多只有一个层叠值。

层叠值——作为层叠结果,应用到一个元素上的特定属性的值。如果始终未指定一个属性,那这个属性就没有层叠值。

4. 两条经验法则

  • 不要使用id选择器;
  • 不要使用 !important;

当创建一个用于分发的JavaScript模块(比如NPM包)时,强烈建议尽量不要在JavaScript里使用行内样式。如果这样做了,就是在强迫使用该包的开发人员要么全盘接受包里的样式,要么给每个想修改的属性加上!important。

正确的做法是在包里包含一个样式表。如果组件需要频繁修改样式,通常最好用JavaScript给元素添加或者移除类。这样用户就可以在使用这份样式表的同时,在不引入优先级竞赛的前提下,按照自己的喜好选择编辑其中的样式。(《JavaScript高级程序设计》有提到)


  • 如何处理优先级
  • 在哪里可以放心使用 !important

二、继承

如果一个元素的某个属性没有层叠值,则可能会继承某个祖先元素的值。继承属性从DOM树的父节点传递到后代节点。

但不是所有的属性都能被继承。默认情况下,只有特定的一些属性能被继承,通常是我们希望被继承的那些,比如与文本相关的部分属性、与列表相关的部分属性、与表格相关的部分属性。

继承属性会顺序传递给后代元素,直到它被层叠值覆盖。

如何使用开发工具追踪层叠值和覆盖值?

使用浏览器开发者工具能够看到哪些元素应用了哪些样式规则,以及为什么应用这些规则。下图是某个元素的规则集示例

48ea5985f3554a0da06d24c8e89b11ce.jpg

  •  该元素上的选择器按优先级从高到低排列,靠近顶部的样式覆盖下面的样式,被覆盖的属性用删除线表示;
  • 在选择器下方是继承inherited属性,可以看到该元素继承了哪些属性以及继承属性的来源;
  • 右侧可以显示这些规则集的来源和位置,比如是用户代理样式、用户样式还是作者样式,以及在对应样式表的行号。

三、特殊值

有两个特殊值可以赋给任意属性,用于控制层叠:inherit(继承其父元素的值)和initial(恢复元素初始值)。

1. inherit关键字

如果想用继承代替一个层叠值,这时候可以用inherit关键字。

还可以使用inherit关键字强制继承一个通常不会被继承的属性,比如边框和内边距。

2. initial关键字

每一个CSS属性都有初始(默认)值。如果将initial值赋给某个属性,那么就会有效地将其重置为默认值,这种操作相当于硬复位了该值。

initial 恢复的是该属性的默认值,而非某个元素的原始值,两者不一定在所有场合下保持一致。

说明:display: initial等价于display: inline。不管应用于哪种类型的元素,它都不会等于display: block。这是因为initial重置为属性的初始值,而不是元素的初始值。inline才是display属性的初始值。

属性默认值与元素的样式属性默认值有区别,相同属性在不同元素上初始值可能不同。

四、简写属性

简写属性是用于同时给多个属性赋值的属性。

比如font、background、border、border-width等。

简写属性是用于某一类属性的样式设置,省略的属性值会被设置成默认值,有可能覆盖其他地方的样式。

1. 简写属性会默默覆盖其他样式

大多数简写属性可以省略一些值,只指定我们关注的值。但是要知道,这样做仍然会设置省略的值,即它们会被隐式地设置为初始值。这会默默覆盖在其他地方定义的样式。

在所有的简写属性里,font的问题最严重,因为它设置的属性值太多了。因此,要避免在<body>元素的通用样式以外使用font。

简写属性主要是简单明了的用处。虽然在一定程度上可以缩减css文件大小,有利于提升网络交互速度,但是缩减的体积几乎可以忽略不计。

2. 理解简写值的顺序

简写属性会尽量包容指定的属性值的顺序。可以设置border: 1px solid black或者border: black 1px solid,两者都会生效。

使用简写属性时,如果属性值的类型各不相同,那么顺序无关紧要,反之,很重要。

2.1 上右下左

这些属性的值是按顺时针方向,从上边开始的。

这种模式下的属性值还可以缩写。如果声明结束时四个属性值还剩一个没指定,没有指定的一边会取其对边的值。指定三个值时,左边和右边都会使用第二个值。指定两个值时,上边和下边会使用第一个值。如果只指定一个值,那么四个方向都会使用这个值。

大多数情况只需要指定两个值。尤其对于较小的元素,左右的内边距最好大于上下内边距。这种样式很适合网页的按钮或者导航链接。

2.2 水平垂直

还有一些属性只支持最多指定两个值,这些属性包括background-position、box-shadow、text-shadow(虽然严格来讲它们并不是简写属性)。这两个值代表了一个笛卡儿网格。笛卡儿网格的测量值一般是按照x, y(水平,垂直)的顺序来的。

如果属性需要指定从一个点出发的两个方向的值,就想想“笛卡儿网格”。如果属性需要指定一个元素四个方向的值,就想想“时钟”。

五、总结

  • 控制选择器的优先级
  • 不要混淆层叠和继承
  • 继承的一般是与文本、列表、表格相关的部分属性
  • 不要混淆initial和auto,auto只是某些属性的默认值,比如width
  • 简写属性注意顺时针方向和笛卡尔坐标系方向

 

  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Key Features The problems of CSS at scale - specificity, the cascade and styles intrinsically tied to element structure. The shortfalls of conventional approaches to scaling CSS. The ECSS methodology and the problems it solves. How to develop consistent and enforceable selector naming conventions with ECSS. How to organise project structure to more easily isolate and decouple visual components. Considerations of CSS tooling and processing: Sass/PostCSS and linting. Addressing the notion of CSS selector speed with hard data and browser representative insight. Book Description Learn with me, Ben Frain, about how to really THINK about CSS and how to use CSS for any size project! I'll show you how to write CSS that endures continual iteration, multiple authors, and yet always produces predictable results. Enduring CSS, often referred to as ECSS, offers you a robust and proven approach to authoring and maintaining style sheets at scale. Enduring CSS is not a book about writing CSS, as in the stuff inside the curly braces. This is a book showing you how to think about CSS, and be a smarter developer with that thinking! It's about the organisation and architecture of CSS: the parts outside the braces. I will help you think about the aspects of CSS development that become the most difficult part of writing CSS in larger projects. You ll learn about the problems of authoring CSS at scale - including specificity, the cascade and styles intrinsically tied to document structure. I'll introduce you to the ECSS methodology, and show you how to develop consistent and enforceable selector naming conventions. We'll cover how to apply ECSS to your web applications and visual models. And how you can organise your project structure wisely, and handle visual state changes with ARIA, providing greater accessibility considerations. In addition, we'll take a deep look into CSS tooling and process considerations. Finally we will address performance considerations by examining topics such as CSS selector speed with hard data and browser-representative insight. Enduring CSS is a book for considering how to write CSS in the most effective manner, and how you too can create an enduring CSS code base, regardless of project size. Take a journey with me if you want to explore these topics and deepen your thinking as a CSS author.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值