第1章 层叠、优先级和继承

层叠

CSS 本质上就是声明规则,即在各种条件下,我们希望产生特定的效果。浏览器会根据这些规则,判断每个规则应该用在哪里,并使用它们去渲染页面。

对同一个元素应用多个规则时,规则中可能会包含冲突的声明。

<header class="page-header">
	<h1 id="page-title" class="title">Wombat Coffee Roasters</h1>
	
	<nav>
		<ul id="main-nav" class="nav">
			<li><a href="/">Home</a></li>
			<li><a href="/coffees">Coffees</a></li>
			<li><a href="/brewers">Brewers</a></li>
			<li><a href="/specials" class="featured">Specials</a></li>
		</ul>
	</nav>

</header>
h1 {
	font-family: serif;
}

#page-title {
  	font-family: sans-serif;
}

.title {
  	font-family: monospace;
}

三个规则集尝试给标题设置不同的字体,哪一个会生效呢?浏览器为了解决这个问题会遵循一系列规则,因此最终的效果可以预测,规则决定了第二个声明(即ID选择器)生效,因此标题采用sans-serif字体。

层叠指的就是这一系列规则。它决定了如何解决冲突,是CSS语言的基础。

当声明冲突时,层叠会依据三种条件解决冲突。

在这里插入图片描述

  • (1) 样式表的来源:样式是从哪里来的,包括你的样式和浏览器默认样式等。
  • (2) 选择器优先级:哪些选择器比另一些选择器更重要。
  • (3) 源码顺序:样式在样式表里的声明顺序。

样式表的来源

你的样式表属于作者样式表,除此之外还有用户代理样式表,即浏览器默认样式。用户代理样式表优先级低,你的样式会覆盖它们。

有些浏览器允许用户定义一个用户样式表。这是第三种来源,它的优先级介于用户代理样式表和作者样式表之间。用户样式表很少见,并且不受网站作者控制。

用户代理样式

浏览器应用了用户代理样式后才会应用你的样式表,即作者样式表。你指定的声明会覆盖用户代理样式表里的样式。

用户代理样式表设置了用户普遍需要的样式,不会做一些完全超出预期的事情。当你不喜欢默认样式时,可以在自己的样式表里设置别的值。

<header class="page-header">
	<h1 id="page-title" class="title">Wombat Coffee Roasters</h1>
	
	<nav>
		<ul id="main-nav" class="nav">
			<li><a href="/">Home</a></li>
			<li><a href="/coffees">Coffees</a></li>
			<li><a href="/brewers">Brewers</a></li>
			<li><a href="/specials" class="featured">Specials</a></li>
		</ul>
	</nav>

</header>
h1 {
	color: #2f4f4f;
	margin-bottom: 10px;
}

#main-nav {
	margin-top: 10px;
	list-style: none;
	padding-left: 0;
}

#main-nav li {
  	display: inline-block;
}

#main-nav a {
	color: white;
	background-color: #13a4a4;
	padding: 5px;
	border-radius: 2px;
	text-decoration: none;
}
! important声明

样式来源规则有一个例外:标记为重要(important)的声明。

在声明的后面、分号的前面加上!important,该声明就会被标记为重要的声明。如:color: red ! important

标记了!important的声明会被当作更高优先级的来源。

理解优先级

如果无法用来源解决冲突声明,浏览器会尝试检查它们的优先级。浏览器将优先级分为两部分:HTML的行内样式和选择器的样式。

行内样式

如果用HTML的 style 属性写样式,这个声明只会作用于当前元素。实际上行内元素属于“带作用域的”声明,它会覆盖任何来自样式表(.css)或者 <style> 标签的样式。行内样式没有选择器,因为它们直接作用于所在的元素。

为了在样式表里覆盖行内声明,需要为声明添加!important,这样能将它提升到一个更高优先级的来源。但如果行内样式也被标记,就无法覆盖它了。最好不要在行内样式用!important

选择器优先级

不同类型的选择器有不同的优先级。如果选择器的ID数量更多,则它会胜出(即它更明确)。如果ID数量一致,那么拥有最多类的选择器胜出。如果以上两次比较都一致,那么拥有最多标签名的选择器胜出。

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

优先级标记

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

比如:选择器#page-header #page-title有2个ID,没有类,也没有标签,它的优先级可以用“2,0,0”表示。

有时,人们还会用4个数的标记,其中将最重要的位置用0或1来表示,代表一个声明是否是用行内样式添加的。此时,行内样式的优先级为“1,0,0,0”。

关于优先级的思考

优先级容易发展为一种“军备竞赛”。在大型项目中这一点尤为突出。通常最好让优先级尽可能低,这样当需要覆盖一些样式时,才能有选择空间。

源码顺序

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

面对一个样式问题时,我经常分两个步骤来解决它。首先确定哪些声明可以实现效果。其次,思考可以用哪些选择器结构,然后选择最符合需求的那个。

继承

如果一个元素的某个属性没有层叠值,则可能会继承某个祖先元素的值。
在这里插入图片描述
但不是所有的属性都能被继承。默认情况下,只有特定的一些属性能被继承,通常是我们希望被继承的那些。它们主要是跟文本相关的属性:color、font、font-family、font-size、font-weight、font-variant、font-style、line-height、letter-spacing、text-align、text-indent、text-transform、white-space以及word-spacing。

还有一些其他的属性也可以被继承,比如列表属性:list-style、list-style-type、list-style-position以及list-style-image。表格的边框属性border-collapse和border-spacing也能被继承。

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

使用开发者工具能够看到哪些元素应用了哪些样式规则,以及为什么应用这些规则。层叠和继承都是抽象的概念,使用开发者工具是最好的追踪方式。在一个页面元素上点击鼠标右键,选择弹出菜单上的检查元素,就能打开开发者工具,示例如下所示。

在这里插入图片描述

特殊值

使用inherit关键字

有时,我们想用继承代替一个层叠值。这时候可以用inherit关键字。可以用它来覆盖另一个值,这样该元素就会继承其父元素的值。

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

使用initial关键字

有时,你需要撤销作用于某个元素的样式。这可以用initial关键字来实现。每一个CSS属性都有初始(默认)值。如果将initial值赋给某个属性,那么就会有效地将其重置为默认值,这种操作相当于硬复位了该值。

这么做的好处是不需要思考太多。如果想删除一个元素的边框,设置border:initial即可。如果想让一个元素恢复到默认宽度,设置width: initial即可。

注意:initial重置为属性的初始值,而不是元素的初始值。

简写属性

简写属性是用于同时给多个属性赋值的属性。比如font是一个简写属性,可以用于设置多种字体属性。它指定了font-style、font-weight、font-size、font-height以及font-family。

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

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

理解简写值的顺序

简写属性会尽量包容指定的属性值的顺序。可以设置border: 1px solid black或者border: black 1px solid,两者都会生效。这是因为浏览器知道宽度、颜色、边框样式分别对应什么类型的值。

但是有很多属性的值很模糊。在这种情况下,值的顺序很关键。

上、右、下、左

当遇到像margin、padding这样的属性,还有为元素的四条边分别指定值的边框属性时。这些属性的值是按顺时针方向,从上边开始的。

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

水平、垂直

还有一些属性只支持最多指定两个值,这些属性包括background-position、box-shadow、text-shadow(虽然严格来讲它们并不是简写属性)。

这些属性值的顺序跟padding这种四值属性的顺序刚好相反。比如,padding: 1em 2em先指定了垂直方向的上/下属性值,然后才是水平方向的右/左属性值,而background-position: 25% 75%则先指定水平方向的右/左属性值,然后才是垂直方向的上/下属性值。

这两个值代表了一个笛卡儿网格。笛卡儿网格的测量值一般是按照x, y(水平,垂直)的顺序来的。第一个值指定了水平方向的偏移量,第二个值指定了垂直方向的偏移量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值