你可能不知道的 CSS —— CSS规范阅读分享

栏目: CSS · 发布时间: 5年前

内容简介:也许有人会说,都快 2019 年了怎么还读 CSS2.1 规范。一方面,现在最新的 CSS (core) 规范是 CSS2.2(以下截图来自www.w3.org/TR/CSS/ ),又因为 CSS2.1 有中文的版本,并且和 CSS2.2 规范差异性不是很大,基于偷懒的目的最终选择阅读了 CSS2.1 规范。记得面试的时候,面试官说 “你的 JavaScript 掌握得比大多数人好很多,但你的 CSS 还需要再加强”。今年六月毕业后,我正式成为一名前端工程师,阅读 CSS 规范也因此进入自己今年的 TOD

也许有人会说,都快 2019 年了怎么还读 CSS2.1 规范。一方面,现在最新的 CSS (core) 规范是 CSS2.2(以下截图来自www.w3.org/TR/CSS/ ),又因为 CSS2.1 有中文的版本,并且和 CSS2.2 规范差异性不是很大,基于偷懒的目的最终选择阅读了 CSS2.1 规范。

你可能不知道的 CSS —— CSS规范阅读分享

记得面试的时候,面试官说 “你的 JavaScript 掌握得比大多数人好很多,但你的 CSS 还需要再加强”。今年六月毕业后,我正式成为一名前端工程师,阅读 CSS 规范也因此进入自己今年的 TODO list 中。

前后花了两个月的零散时间,在上周我终于完成了阅读,对 CSS 的理解也稍微更系统全面了一些。在自己阅读的过程中,有些感觉是大家平常容易忽视,但有可能用到或是本身比较有趣的小知识点,便以此为主题,在此基础上适当扩展,整理了一篇文章和大家分享。

只要一杯咖啡的时间,一起来回顾一下规范里那些可能不太能引起你注意的地方吧。

阅读愉快,请多指教。

关键字、属性和标识符

以 - 或 _ 开头的关键字和属性名是为特定供应商扩展保留的。

CSS 中标识符只能包含字符 [a-zA-Z0-9]、ISO10646 字符中 U+00A0 及之后的字符,以及 - 和 _,不能以 1 个数字、2 个连字符、或者后面跟着数字的连字符开头。

这也意味着,选择器可以是中文的(虽然并不推荐)。

<style>
.中文 {
    color: red;
}
</style>
....
<p class="中文">这是一段中文选择器文本。</p>
复制代码

此时, <p> 标签内的文字将变为红色。

@import

用户代理必须忽略所有出现在块内部,或者在除 @charset@import 规则外任何无法忽略的语句后面的 @import 规则。

这也意味着, @import 规则必须先于除 @charset 和其它的 @import 规则外的所有规则。

@import "subs.css"
h1 { color: blue; }
@import "list.css"
复制代码

上述代码中,第二个 @import 语句是非法的,解析器将会忽略这条规则。

另外, @import 规则可以加上媒体查询类型,表示只在满足某个媒体类型时引入样式表。

@import "landscape.css" screen and (orientation:landscape)
复制代码

编码和 @charset

当一个样式表被嵌进其它文档时,比如 HTML 中的 style 元素或者 style 属性,样式表会共享整篇文档的字符编码。

如果一个样式表处于一个独立文件中,则按下列顺序(从最高优先级到最低)确定样式表的字符编码:

  1. HTTP 协议中 Content-type 字段的 charest 参数
  2. 文件的 BOM 编码或 @charset
  3. <link charset=""> 或者来自链接机制的其它元数据
  4. 要引入的样式表或者文档的字符集
  5. 假定为 UTF-8

使用 @charset 规则的编写者必须把该规则放在样式表的开头,前面不允许有任何字符。用户代理必须忽略任何不在样式表开头的 @charset 规则。

:first-letter 伪元素

: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>
复制代码

实际效果如图:

你可能不知道的 CSS —— CSS规范阅读分享

:before 与 :after 伪元素

: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 种不同的来源:编写者、用户和用户代理(如浏览器)。

为了找出一个元素或属性组合的值,用户代理必须按照下列(步骤)排序:

  1. 找出目标媒体类型下,所有适用于该元素和目标属性的声明
  2. 根据重要性(@important)规则和来源排序,优先级从低到高为:
    • 用户代理声明
    • 用户常规声明
    • 编写者常规声明
    • 编写者重要声明
    • 用户重要声明
  3. 相同重要性和来源的规则根据选择器的特殊性(specificity)排序,更特殊的选择器将重写一般的。伪元素和伪类被分别算作常规元素和类
  4. 最后,根据指定顺序排序:如果两个声明的权重,来源和特殊性都相同,后制定的生效。 @import 引入的样式表中的声明被认为在样式表自身的所有声明之前

计算选择器的特殊性(specificity)

一个选择器的特殊性(a-b-c-d)根据下列规则计算(a到d权重依次递减):

style
* {} /*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 的计算方式。实际上这并不准确。我们可以通过简单的实验推翻上述的说法。

如下例,我们定义了类名为 zerodiv ,里面嵌套了十层 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 的计算方式是不准确的。

你可能不知道的 CSS —— CSS规范阅读分享

不过,由于实现上的问题,可能会存在有限多个 class 优先级比一个 id 高的情况。张鑫旭在12年分享过一篇 《有趣:256个class选择器可以干掉1个id选择器》 。主要是因为写这篇文章的时候有些浏览器使用了8位计数器对 class 的数量进行计算,当 class 达到256个时由于发生进位将会出现权重比 id 高的情况。之后的浏览器使用了更高位数的计数器,理论上仍可能存在边界值,但将很难达到。

content 中的 attr 属性

content: attr(X)
复制代码

attr(X) 函数返回一个字符串,字符串的值为该选择器选中对象的 X 属性的值。如果该对象没有 X 属性,则返回一个空字符串。

用法示例:

p:after { content: ", " attr(data-name); }
复制代码
<p data-name="Thorn">Hello</p>
复制代码

此时将会渲染出 “Helo, Thorn”。

计数器

计数器使用大小写敏感的标识符。自动编号通过 counter-incrementcounter-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>
复制代码

效果如图所示

你可能不知道的 CSS —— CSS规范阅读分享

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>
复制代码
你可能不知道的 CSS —— CSS规范阅读分享

背景属性是不可继承的,但因为 background-color 的初始值为 transparent ,父级盒的背景将透过来。

另外,当同时设置 background-image 属性和 background-color 属性时,如果图像可用则将被渲染在背景色之上。这也意味着,在图像的透明部分,背景色是可见的。

轮廓( outline

outlineborder 的区别:

  • outline 不占空间,显示或隐藏不会导致重排或者溢出
  • outline 可以不是矩形的
  • 所有方向的 outline 都相同,与 border 相比,不存在 outline-topoutline-left 属性
  • 如果元素被拆分成了多行,与 border 相比, outline 在行框的开始或者结束出不是断开的,而是总会尽量完全连接起来(效果如下图)
  • 因为 outline 不影响格式化,它可能会与页面上的其他元素重叠
你可能不知道的 CSS —— CSS规范阅读分享

outline-widthbackground-width 接受相同的值(hidden 除外)。

outline-stylebackground-style 接受相同的值(hidden 除外)。

outline-colorbackground-color 接受相同的值。此外 outline-color 还可以设置为 invert ,用来对屏幕的像素取反色(但不是所有浏览器都支持该属性)。

默认样式

在不指定字体大小的情况下,标题字号略粗于常规字体, h4 的字体大小和常规字体大小相同, h5h6 字体略小于常规字体。

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; }
复制代码
你可能不知道的 CSS —— CSS规范阅读分享

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Code Reading

Code Reading

Diomidis Spinellis / Addison-Wesley Professional / 2003-06-06 / USD 64.99

This book is a unique and essential reference that focuses upon the reading and comprehension of existing software code. While code reading is an important task faced by the vast majority of students,......一起来看看 《Code Reading》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具