![aa5eb00c25a479bc3a7817b2e6b92f0e.png](https://i-blog.csdnimg.cn/blog_migrate/cd0a6067e819adf95d2ec2dd5a51d002.jpeg)
思来想去,写了这么个标题;其实前面已经把重要的样式都讲到了,重点在如何应用上面,要知道 CSS 是典型的易上手难精通的一种语言(非开发语言),有的时候看起来很正常的写法,到最后居然发现浏览器是不会给渲染的,其中有很多原因,这里就一起看看 CSS 有哪些坑,要怎么避免。
1 一些常见的不必要样式
我们有时候写的 CSS 样式会与浏览器默认的 CSS 样式一致,有时候自己都可能没有意识到,常见的例子有:
(1)
div
留意上面代码里面的 height: auto; ,很显然,这段样式是没有必要的,默认的任何块状元素的高度几乎都是 auto,浏览器遇到这样的 CSS 代码,会与默认样式比较,最后却不进行渲染。
那什么时候应该使用这个样式呢?这要记住,只有在使用 CSS 优先级抹掉之前的 height 定值的样式的时候使用,其他时候就不要显示的设置了。
(2)
body
对于body, p, h1~6这些标签,本身的 padding 值就是 0,所以 padding: 0; 是多余的,只需要 margin:0; 就可以了。
找到个反面例子,是2009年的人人网样式表,开头就是这么设置的(为了容易看,我分了行,原来是没有分行的):
body
这段代码的问题是,为了省事,把所有元素都统一设置了,但其实只要把需要的样式独立出来进行设置就好了,反正都是要独立设置的,为什么就要省这几行代码呢?
毕竟常用的元素当中,也就是 ol,ul 这些有默认的 padding,所以可以这样写:
body
(3)
span
如果对 HTML 有了解,应该是知道 span 元素本来就是内联的,给它设置 display: inline; 纯属多此一举。当然如果是祖传代码的话,有可能是因为与 IE 6 的浮动双边距bug有关,我们可以用设置 display: inline; 的方法修复 IE 6 的这个bug,但是,现如今微软自己都已经放弃了 IE,而 Chrome,Safari,Firefox这些现代浏览器一统天下,对于span,a,em,cite,i,b,strong等设置 display: inline; 完全是多此一举。
类似的问题还有给本来就是块状元素设置 display: block; :
li
尽量留意这样的问题。
(4)其他类似的问题
div
2 样式覆盖
有时候在写 CSS 的过程中,某些限制总是不起作用,这就涉及了 CSS 样式覆盖的问题,如下样例:
#
上面的代码当中,.current_block 的样式声明是无效的,这是为什么?
CSS 部分的第一章(CSS从零开始——介绍)就提到了这个顺序问题,这里列出来回忆一下:
浏览器使用如下顺序来检查样式属性值,并进行渲染:
- 内联样式:HTML 元素上的 style 属性所定义的样式
- 嵌入式样式:在 style 元素当中定义的样式
- 外部样式:使用 link 元素导入的样式
- 用户样式:由用户自己在浏览器当中定义的样式(比较少用到)
- 浏览器样式:浏览器的默认样式
2.1 同源样式覆盖
这个属于样式加载的顺序,其实还有些隐藏的检查顺序,即使同在样式表(外部样式)当中,也会有顺序的问题,看了别的站点信息加上自己的测试,大致如下:
- 样式表的元素选择器选择越精确,则其中的样式优先级越高:
id选择器指定的样式 > 类选择器指定的样式 > 元素类型选择器指定的样式
所以上例中,#navigator 的样式优先级大于 .current_block 的优先级,所以就算 .current_block 是最新添加的,也不起作用
- 对于相同类型选择器制定的样式,在样式表文件中,越靠后的优先级越高:
注意,这里是样式表文件中越靠后的优先级越高,而不是在元素 class 出现的顺序。比如 .class2 在样式表中出现在 .class1 之后:
.
而某个元素指定 class 时采用 class="class2 class1" 这种方式指定,此时虽然 class1 在元素中指定时排在 class2 的后面,但因为在样式表文件中 class1 处于 class2 前面,此时仍然是 class2 的优先级更高,color 的属性为 red,而非 black。
- 如果要让某个样式的优先级变高,可以使用 !important 来指定:
.
如上所示,这样设置的时候 color 的属性为 black,而非 red。
所以本节最开头的例子,可以用两种方法解决:
- 把 #navigator 的 border 样式单独拿出来,放在另一个选择器且与 .current_block 没有范围重合,并且放在 .current_block 之前:
#
这种方式相对复杂,而且要同时修改 HTML。
- 在 .current_block 的样式后增加 !important:
#
其他部分无需修改,相对来说更简单。
2.2 覆盖规则
(1)规则一:由于继承而发生样式冲突时,最近祖先获胜。
CSS 的继承机制使得元素可以从包含它的祖先元素中继承样式,考虑下面这种情况:
<!DOCTYPE html>
![609581c7363d6d4e2698df0ce46e4d3c.png](https://i-blog.csdnimg.cn/blog_migrate/c6741ec127e72871d765c13c54e82582.png)
strong 分别从 body 和 p 中继承了 color 属性,但是由于 p 在继承树上离 strong 更近,因此 strong 中的文字最终继承 p 的蓝色。
(2)规则二:继承的样式和直接指定的样式冲突时,直接指定的样式获胜
在上面的例子中,假如还指定了 strong 元素的样式,如:
<!DOCTYPE html>
![ae1e39d960d814d0c5e2c795da22da28.png](https://i-blog.csdnimg.cn/blog_migrate/69cac6a41932eda0e85769b022cbfcd6.png)
根据规则二,strong 中的文字最终显示为海蓝色。
(3)规则三:直接指定的样式发生冲突时,样式权值高者获胜
样式的权值取决于样式的选择器,权值定义如下表(Excel 做的,将就一下):
![fcd839376b7c34a62dc165c53504594c.png](https://i-blog.csdnimg.cn/blog_migrate/52ceaa21dba2b499893f86593a4cf1a9.png)
![22b7d8495b75046a5d0df20f0833c493.png](https://i-blog.csdnimg.cn/blog_migrate/f3b55e87bb8b176d0e0cd1f4c8ee1a33.png)
可以看到,内联样式的权值 > ID选择器 > 类选择器 > 标签选择器,除此以外,后代选择器的权值为每项权值之和,比如 #nav .current a 的权值为 100 + 10 + 1 = 111;CSS 会对选择器的权值计算后得出结果。
(4)规则四:样式权值相同时,后者获胜
上面已经给了一个例子,这里还有一个简单的例子:
<
.byline a 与 p .email都直接指定了上面的 a 元素,且权值都为11,根据规则四,最终显示蓝色。
由于样式表可以是外部的,也可以是内部的,规则四提醒我们要注意外部样式表引入的顺序(及 <link> 元素的顺序),以及外部样式表与内部样式表的出现位置。一般来说,内部样式表出现在所有外部样式表的引入之后,一般是在 </head> 之前。
(5)规则五:!important的样式属性不被覆盖。
!important 可以看做是万不得已的时候,打破上述四个规则的“金手指”。如果一定要采用某个样式属性,而不让它被覆盖的,可以在属性值后加上 !important,以规则四的例子为例,.byline a {color: red !important;} 可以强行使链接显示红色。
但大多数情况下都可以通过其他方式来控制样式的覆盖,不能滥用 !important,假设用了太多这个关键字,在样式出现相互重叠的时候,关键字的作用就几乎等于没有了。
3 CSS Hack
我自己对这一方面已经不熟悉了,自从N年前公司将 Chrome 作为标准浏览器之后,我基本没有再考虑过 IE 9 以下的兼容代码。
所以为了凑数,大家可以考虑看看 CSS hacks 这篇文章,讲解的非常清楚了。如果一定要 IE 兼容(譬如面向公网的产品),也可以考虑:
<
这种条件语句方式来兼容对应版本的 IE(我承认这一节划水了)。
主要是因为 CSS 更多需要的是实践,只依靠几篇文章肯定是没有办法全面了解的,而且我也仅仅是把 CSS 当作必须了解和使用的知识,主要的精力还是在开发语言上的,所以 CSS 这个部分这就是最后一章节了。
从下个章节开始,终于要来看看框架了,因为 Vue.js、React越来越流行,所以先从 Vue.js 开始(虽然我本来是想先从 jQuery 开始的,毕竟老 jQ 党了),正好我的学习路径也到了 Vue.js,一起学起来!