本文创做于 2018-12-24,2019-12-20 迁移至此
本文基于 CSS 2.1 规范中文版整理。
使用浏览器 Chrome 70 进行测试。
也许有人会说,都快 2019 年了怎么还读 CSS2.1 规范。一方面,如今最新的 CSS (core) 规范是 CSS2.2(如下截图来自 https://www.w3.org/TR/CSS/ ),又由于 CSS2.1 有中文的版本,而且和 CSS2.2 规范差别性不是很大,基于偷懒的目的最终选择阅读了 CSS2.1 规范。css
记得面试的时候,面试官说 “你的 JavaScript 掌握得比大多数人好不少,但你的 CSS 还须要再增强”。今年六月毕业后,我正式成为一名前端工程师,阅读 CSS 规范也所以进入本身今年的 TODO list 中。html
先后花了两个月的零散时间,在上周我终于完成了阅读,对 CSS 的理解也稍微更系统全面了一些。在本身阅读的过程当中,有些感受是你们日常容易忽视,但有可能用到或是自己比较有趣的小知识点,便以此为主题,在此基础上适当扩展,整理了一篇文章和你们分享。前端
只要一杯咖啡的时间,一块儿来回顾一下规范里那些可能不太能引发你注意的地方吧。面试
阅读愉快,请多指教。算法
以 - 或 _ 开头的关键字和属性名是为特定供应商扩展保留的。浏览器
CSS 中标识符只能包含字符 [a-zA-Z0-9]、ISO10646 字符中 U+00A0 及以后的字符,以及 - 和 _,不能以 1 个数字、2 个连字符、或者后面跟着数字的连字符开头。前端工程师
这也意味着,选择器能够是中文的(虽然并不推荐)。ide
<style> .中文 { color: red; } </style> .... <p class="中文">这是一段中文选择器文本。</p>
此时,<p>
标签内的文字将变为红色。wordpress
用户代理必须忽略全部出如今块内部,或者在除 @charset
和 @import
规则外任何没法忽略的语句后面的 @import
规则。函数
这也意味着,@import
规则必须先于除@charset
和其它的 @import
规则外的全部规则。
@import "subs.css" h1 { color: blue; } @import "list.css"
上述代码中,第二个 @import
语句是非法的,解析器将会忽略这条规则。
另外,@import
规则能够加上媒体查询类型,表示只在知足某个媒体类型时引入样式表。
@import "landscape.css" screen and (orientation:landscape)
当一个样式表被嵌进其它文档时,好比 HTML 中的 style
元素或者 style
属性,样式表会共享整篇文档的字符编码。
若是一个样式表处于一个独立文件中,则按下列顺序(从最高优先级到最低)肯定样式表的字符编码:
Content-type
字段的 charest
参数@charset
<link charset="">
或者来自连接机制的其它元数据使用 @charset
规则的编写者必须把该规则放在样式表的开头,前面不容许有任何字符。用户代理必须忽略任何不在样式表开头的 @charset
规则。
:first-letter
伪元素选择一个块的第一行(第一个格式化行块)的第一个字母(或数字),若是这一行中在它前面没有跟着任何其它内容(例如图片或者 inline table)的话。表格单元或者inline-block
元素的首字母不能做为其祖先元素的首字母。
<style> .description:first-letter { color: white; } </style> <p class="description">“some text”</p> <p class="description">some text</p> <p class="description"><img src="" />some text</p>
实际效果如图:
:before
和 :after
伪元素会从文档树中它们附着的元素上继承全部可继承的属性。对于不可继承的元素,将取其初始值。
用法示例:
p { color: red; display: block; } p:before { content: 'T'; }
如上例,此时,:before 伪元素将呈现红色。由于 display
属性不可继承,将取其初始值 inline
。
CSS3 选择器草案中区分了伪元素和伪类(CSS-Selectors Level 4),伪类仍以一个引号开头,伪元素则以两个引号开头。对于 CSS1 和 CSS2 中存在的 :before
、:after
、:first-line
和 :first-letter
伪元素,用户代理必须同时支持它们单引号和双引号的形式,对于其它新引入的伪类,用户代理将不支持其单引号的形式。
选择器中,文档语言元素名的大小写敏感性取决于文档语言,例如在 HTML 中元素名是大小写不敏感的,而在 XML 中元素名是大小写敏感的。
样式表可能有 3 种不一样的来源:编写者、用户和用户代理(如浏览器)。
为了找出一个元素或属性组合的值,用户代理必须按照下列(步骤)排序:
根据重要性(@important)规则和来源排序,优先级从低到高为:
@import
引入的样式表中的声明被认为在样式表自身的全部声明以前一个选择器的特殊性(a-b-c-d)根据下列规则计算(a到d权重依次递减):
style
属性而不是一条选择器样式规则,算1,不然就是0(=a)* {} /*a=0, b=0, c=0, d=0*/ li {} /*a=0, b=0, c=0, d=1*/ .description {} /*a=0, b=0, c=1, d=0*/ *[rel=up] {} /*a=0, b=0, c=1, d=0*/ #element {} /*a=0, b=1, c=0, d=0*/ style="" /*a=1, b=0, c=0, d=0*/
也就是说,尽管 #p123
比 [id=p123]
选中的对象相同,但ID 选择器比属性选择器拥有更高的特殊性。
以前看过一些博客,在提到层叠的特殊性的时候,用 1000, 100, 10, 1 的权重去描述上述的 a-b-c-d 的计算方式。实际上这并不许确。咱们能够经过简单的实验推翻上述的说法。
以下例,咱们定义了类名为 zero
的 div
,里面嵌套了十层 div
,最内的一层指定了 id 为last
。若是按照10倍递增的算法,嵌套十一层的 class
的特殊性为 110,使用一个 id 的特殊性为 100,背景呈现黑色。若是按照 a-b-c-d 的算法,使用前者的特殊性为 0-0-11-0,后者特殊性为 0-1-0-0,背景将呈现红色。
经过观察连用十一个 class 和一个 id 的表现,便可得出结论。
<style> #last { background: red; } .zero .one .two .three .four .five .six .seven .eight .nine .ten { background: black; height: 100px; width: 100%; } </style> <div class="zero"> <div class="one"> <div class="two"> <div class="three"> <div class="four"> <div class="five"> <div class="six"> <div class="seven"> <div class="eight"> <div class="nine"> <div class="ten" id="last"></div> </div> </div> </div> </div> </div> </div> </div> </div> </div> </div>
如图所示,背景呈现红色,因此 1000, 100, 10, 1 的计算方式是不许确的。
不过,因为实现上的问题,可能会存在有限多个 class
优先级比一个 id
高的状况。张鑫旭在12年分享过一篇《有趣:256个class选择器能够干掉1个id选择器》。主要是由于写这篇文章的时候有些浏览器使用了8位计数器对 class
的数量进行计算,当 class
达到256个时因为发生进位将会出现权重比 id
高的状况。以后的浏览器使用了更高位数的计数器,理论上仍可能存在边界值,但将很难达到。
content: attr(X)
attr(X)
函数返回一个字符串,字符串的值为该选择器选中对象的 X 属性的值。若是该对象没有 X 属性,则返回一个空字符串。
用法示例:
p:after { content: ", " attr(data-name); }
<p data-name="Thorn">Hello</p>
此时将会渲染出 “Helo, Thorn”。
计数器使用大小写敏感的标识符。自动编号经过 counter-increment
和 counter-reset
属性控制。
若是给同一个计数器指定了屡次 counter-reset
或者 counter-increment
的值,计数器的每次重置或递增会按指定的顺序处理。
/* 第二个 section 省略了重置的值,会被置默认值 0, section 将先重置为 2,最终重置为 0 */ h1 { counter-reset: section 2 section; } /* 第一个 section 省略了递增的值,会被置默认值 1, section 先递增 1, 再递增 2, 至关于递增 3*/ h1 { counter-increment: section section 2; }
另外,counter-reset
属性遵循层叠原则,若是要同时重置两个计数器,它们必须同时指定。
h1 { counter-reset: section 0 image 0; } /* 下面的写法会发生层叠致使只有一个计数器生效 */ h1 { counter-reset: section 0; } h1 { counter-reset: image 0; }
计数器是自嵌套的,若是重置一个位于后代元素或伪元素的中的计数器,则会自动建立一个新的计数器实例。计数器的做用域从文档中具备 “counter-reset
+ 该计数器” 的第一个元素开始,包括该元素的后代和后续兄弟及其后代,但不包括处于同名计数器做用域中的任何元素。
<style> ol { counter-reset: section; list-style-type: none; } li:before { counter-increment: section; content: "第" counters(section, ".") "章"; } </style> <ol> <li>item</li> <!--第1章--> <li> <!--第2章--> <ol> <li>item</li> <!--第2.1章--> </ol> </li> <li>item</li> <!--第3章--> </ol>
效果如图所示
display:none
的元素中的计数器一个 display
值设置为 none
的元素不会让计数器递增或重置,没法生成的伪元素也不会让计数器递增或重置,然而 visibility
被设置 hidden
的元素会让计数器递增或重置。
一个具备display: list-item
的元素会为该元素的内容生成一个主块盒,还可能生成一个标记盒做为可视化指示,说明该元素是一个列表项。
background
属性只适用于主盒,外部的标记盒是透明的。(不过,若是将 list-style-position
的值设置为 inside
的话,因为标记盒的背景是透明的,主盒设置的背景将会透过来,视觉上也至关于同时给主盒和标记盒加上了背景)。
根据盒模型,背景指的是内容,内边距和边框区的背景。边框颜色和样式能够经过边框属性来设置,而外边距老是透明的。
<style> .transparent-border { border: 10px solid rgba(0, 0, 0, 0); color: white; background: blue; } </style> <p class="transparent-border">将 border 的颜色设置为透明时,背景的颜色将透过来。</p>
背景属性是不可继承的,但由于 background-color
的初始值为 transparent
,父级盒的背景将透过来。
另外,当同时设置 background-image
属性和 background-color
属性时,若是图像可用则将被渲染在背景色之上。这也意味着,在图像的透明部分,背景色是可见的。
outline
)outline
与 border
的区别:
outline
不占空间,显示或隐藏不会致使重排或者溢出outline
能够不是矩形的outline
都相同,与 border
相比,不存在 outline-top
或 outline-left
属性border
相比,outline
在行框的开始或者结束出不是断开的,而是总会尽可能彻底链接起来(效果以下图)outline
不影响格式化,它可能会与页面上的其余元素重叠outline-width
与 background-width
接受相同的值(hidden 除外)。
outline-style
与 background-style
接受相同的值(hidden 除外)。
outline-color
与 background-color
接受相同的值。此外 outline-color
还能够设置为 invert
,用来对屏幕的像素取反色(但不是全部浏览器都支持该属性)。
在不指定字体大小的状况下,标题字号略粗于常规字体,h4
的字体大小和常规字体大小相同,h5
和 h6
字体略小于常规字体。
h1, h2, h3, h4, h5, h6 { font-weight: bolder; } h1 { font-size: 2em; margin: .67em 0; } h2 { font-size: 1.5 em; margin: .75em 0; } h3 { font-size: 1.17em; margin: .83em 0; } h4 { margin: 1.12em 0; } h5 { font-size: .83em; margin:1.5em 0; } h6 { font-size: .75em; margin: 1.67em 0; }