本书第四版(英文原版),于 2017 年年中完稿。中文于 2019 年 4 月出版。
简介
1994 年,CSS 第一个提案发布。目标是提供一个简单的声明式样式语言。
1996 年年末,CSS1 制定完成。
CSS2 规范于 1998 年年初定案,后续修订版 CSS 2.1。
此后,CSS 规范被分拆分成多个模块各自发展,不再有能涵盖一切的“CSS3 规范”一说。学习 CSS 特性,要去不同的 CSS 的规范中学习。
元素
HTML 中的常用元素(element)包括 div、span、p、table、a 等。
置换和非置换元素
置换元素
置换元素(replaced element)的内容由外部资源决定。img 和 input 都在其列。
<img src="howdy.gif">
非置换元素
HTML 中的大多数元素都是非置换元素(noreplaced element),即元素内容由用户代理在元素生成的框中显示。
<span>hi there</span>
元素显示方式
除了按照置换和非置换元素角度划分元素,根据显示方式,元素又分为块级和行内两种基本类型。
块级元素
HTML 中最常见的块级元素是 div 和 p。默认自成一行,填满父元素内容区域的框。
行内元素
HTML 中最常见的块级元素是 span、a、strong 和 em。默认行内显示。
注意,在 HTML 中,块级元素不能出现在行内元素中。
<!-- √ 在不改变标记的前提下,可以如此设置显示方式 -->
<style>p {display:inline;} em {display:block;}</style>
<body>
<p>This is a paragraph with <em>an inline element</em> within it.</p>
</body>
<!-- × 调换嵌套关系,就是有问题的了:
违背规则:块级元素不能出现在行内元素中
-->
<em>This is a paragraph with <p>an inline element</p> within it.</em>
未知标记的默认 display 值是 inline。
把 CSS 应用到 HTML
如何在 HTML 文档中关联 CSS?
link 标签
link 标签作用:把其他文档跟当前文档关联起来。
引入外部样式表(external stylesheet)的方式如下:
<link rel="stylesheet" href="style.css">
这里的 rel 属性是“relation”(关系)的简称。
候选样式表(alternate stylesheet):
<!-- 如果浏览器支持的话 -->
<link rel="alternate stylesheet" href="style.css" title="Default">
样式表类型:
- 候选样式表,rel 属性值 “alternate stylesheet”,且有 title 属性(用于分组)。
- 永久样式表,rel 属性值 “stylesheet”,且无 title 属性。
- 首选样式表,rel 属性值 “stylesheet”,且有 title 属性。有多个首选样式表的,只会使用其中一个,规则不明。
style 元素
使用 style 元素直接在文档中使用样式表:
<style>...</style>
style 标签之间的样式称为文档样式表(document stylesheet)或嵌入式样式表(embedded stylesheet)。
@import 指令
@import 指令在 style 标签中使用,跟“link 标签”作用一样,都是用来加载外部样式表的。
<style>
@import url(style.css); /* @import 放在开头 */
h1 {color: gray;}
</style>
@import 指令能够实现在一个样式表中引入另一个外部样式表的功能。
HTTP 链接
鲜为人知的一种方式。以 Apache 为例,修改 .htaccess 文件:
Header add link "</ui/testing.css>;rel=stylesheet;type=text/css"
行内样式
行内样式是通过 HTML 元素的 style 属性设置的:
<p style="color: gray;">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed et est condimentum, interdum arcu id, lobortis nibh. </p>
除了 body 之外的标签(如 head 或 title),所有 HTML 标签都能设定 style 属性。
通常不建议使用 style 标签,除了 HTML,XML 中很少使用这个属性,不过提供了一定的灵活性。
样式表的内容
标记
样式表中不能出现标记。但由于历史原因,style 元素中可以有 HTML 注释(但我用浏览器测试,似乎这个注释标记会被忽略,已经不支持了)。
<style><!--
@import url(style.css);
h1 {color: gray;}
--></style>
规则的结构
- 一个样式表由一系列规则(Rule)构成,
- 规则由两个基本部分构成:选择符(Selector)和声明块(Declaration block),
- 声明块由一个或多个声明(Declaration)组成,
- 一个声明包含属性(Property)和对应的值(Value)。
上图的规则,将 h1 元素设置为黄底红字。
厂商前缀
浏览器厂商通过厂商前缀(vendor prefix)标记实验性或专属的属性、值或其他内容。
常见的厂商前缀包括:
Prefix | Vendor |
---|---|
-epub- | International Digital Publishing Forum ePub format |
-moz- | Mozilla-based browsers (e.g., Firefox) |
-ms- | Microsoft Internet Explorer |
-o- | Opera-based browsers |
-webkit- | Webkit-based browsers (e.g., safari and Chrome) |
厂商前缀出现的目的是为了浏览器厂商测试新特性,这么做既能保证兼容性,又不用担心与其它浏览器不兼容。
处理空白
CSS 对待空白的方式跟 HTML 差不多,连续的空白会被合并成一个空白。
CSS 注释
CSS 中,只能使用 /* */
的方式添加注释,单行多行都可以;且 CSS 注释不能嵌套,否则是无效的。
媒体查询
媒体查询(Media query)定义浏览器在何种媒体环境中使用指定样式表。
用法
媒体查询可以在以下几个地方使用。
- link 元素的 media 属性
- style 元素的 media 属性
- @import 声明的媒体描述符部分
- @media 声明的媒体描述符部分
简单的媒体查询
看一个简单的例子:
h1 {color: maroon;}
@media projection {
body {background: yellow;}
}
上面样式指定,在投影媒体中 body 有一个黄色背景。
媒体类型
媒体类型由 CSS2 引入。包括(但不限于):
- all:指定在所有媒体中应用,
- print:指定在打印和预览文档时应用,
- screen:指定在屏幕媒体上展示文档使用。桌面计算机上运行的所有 Web 浏览器都是屏幕媒体的用户代理。
当一个样式表要在多个媒体类型下使用时,使用逗号分隔媒体类型。
<link rel="stylesheet" href="style.css" media="screen, print">
<style media="screen, print"></style>
@import url(style.css) screen, print;
@media screen, print {...}
媒体描述符
- 一个媒体描述符由一个媒体类型和一个或多个媒体特性列表构成。
- 其中,(媒体)特性描述符要放在圆括号中。
- 如果没有指定媒体类型,就是应用到所有媒体上。
/*下面两个示例是等效的 */
@media all and (min-resolution: 96dpi) {...}
@media (min-resolution: 96dpi) {...}
多个特性描述符使用 and 关键字连接,除此之外,还有 not 和 only 关键字:
- and:当连接的多个媒体同时满足条件,整个查询结果才为真。例如:(color) and (orientation: landscape) and (min-device-width: 800px),这表示当媒体环境是彩色、横放且屏幕宽至少 800px 像素,才会应用样式表。
- not:对整个查询取反。例如:not (color) and (orientation: landscape) and (min-device-width: 800px),这表示只要上述三个条件不同时满足,就会应用样式表。
**not**
关键字只能在媒体查询的开头使用。 - only:表示只在满足媒体查询条件的浏览器中应用。与 not 一样,
**only**
只能在媒体查询的开头使用。
媒体类型描述符和值的类型
截止到 2017 年:
width | max-device-width | min-color-index |
---|---|---|
min-width | aspect-ratio | max-color-index |
max-width | min-aspect-ratio | monochrome |
device-width | max-aspect-ratio | min-monochrome |
min-device-width | device-aspect-ratio | max-monochrome |
max-device-width | min-device-aspect-ratio | resolution |
height | max-device-aspect-ratio | min-resolution |
min-height | color | max-resolution |
max-height | min-color | orientation |
device-height | max-color | scan |
min-device-height | color-index | grid |
还有两种新增的值。
特性查询
特性查询(feature query)是指根据用户代理是否支持特定 CSS 属性及其值来应用一段样式,结构上跟媒体查询很像。
@supports (color: black) {
body {color: black;}
}
上面的意思是,“如果浏览器能识别并处理 color: black”这个声明,就应用这段样式(即将 body 的背景色设置成黑色),否则跳过这段样式。
使用特性查询,可以实现渐进增强样式。
@supports (display: grid) {
#main {display: grid}
}
上述样式,是在支持栅格布局的浏览器中应用。
特性查询还支持嵌套。
@supports (display: flex) {
@media screen {
/* 针对屏幕媒体的弹性盒样式 */
}
@media print {
/* 针对印刷媒体的弹性盒样式 */
}
}
也可能在响应式媒体查询块中使用 @supports() 块:
@media screen and (max-width: 30em) {
@supports (display: flex) {
/* 针对小屏幕的弹性盒样式 */
}
}
@media screen and (min-width: 30em) {
@supports (display: flex) {
/* 针对大屏幕的弹性盒样式 */
}
}
与媒体查询类似,特性查询也支持使用逻辑运算符 and:
@supports (display: flex) and (shape-outside: circle()) {
/* 栅格和形状样式 */
}
/* 等价于 */
@supports (display: flex) {
@supports (shape-outside: circle()) {
/* 栅格和形状样式 */
}
}
还有取反运算符 not:
@supports not (display: flex) {
/* 不支持栅格时使用的样式 */
}
特性查询时,既要写属性也要写值。举个例子,IE 4 就开始支持 display 属性了,但是不支持 flex 布局的。
/* × 这种测试肯定是不行的 */
@supports (display) {
/* 栅格样式 */
}
小结
- CSS 简单一点,只使用 display 属性;复杂一点,则可以为文档关联样式表。
- 借助 @supports() 甚至可以使用纯 CSS 实现基本的渐进增强功能。