层叠样式表 (Cascading Style Sheets,缩写为 CSS),是一种 样式表 语言,用来描述 HTML 或 XML(包括如 SVG、MathML、XHTML 之类的 XML 分支语言)文档的呈现。CSS 描述了在屏幕、纸质、音频等其它媒体上的元素应该如何被渲染的问题。
CSS 加载方式
外部样式表
外部样式表是指将 CSS 编写在扩展名为.css
的单独文件中,并从 HTML <link>
元素引用它的情况。这是将css附加到文档中的最常的方法。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My CSS experiment</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Hello World!</h1>
<p>This is my first CSS example</p>
</body>
</html>
内部样式表 (在<style>
标签中加载)
内部样式表是指不使用外部CSS文件,而是将CSS放在HTML文件<head>
标签里的<style>
标签之中。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My CSS experiment</title>
<style>
h1 {
color: blue;
background-color: yellow;
border: 1px solid black;
}
p {
color: red;
}
</style>
</head>
<body>
<h1>Hello World!</h1>
<p>This is my first CSS example</p>
</body>
</html>
内联样式(使用style
属性加载)
内联样式表存在于HTML元素的style属性之中。其特点是每个CSS表只影响一个元素。除非特殊情况(如邮件),一般不使用这种方法。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My CSS experiment</title>
</head>
<body>
<h1 style="color: blue;background-color: yellow;border: 1px solid black;">Hello World!</h1>
<p style="color:red;">This is my first CSS example</p>
</body>
</html>
CSS 语法
CSS 用于定义网页中特定元素样式的一组规则。比如“我希望页面中的主标题是红色的大字”在 CSS 中写成:
h1 {
color: red;
font-size: 5em;
}
一个规则由一个选择器(selector)起头。它被用于选择要被添加样式的 HTML 元素。如上面例子中的h1
就选定了为一级标题添加样式。
在选择器之后是一对大括号,其中包含了一个或多个形式为 属性(property): 值(value);
的声明(decalaration)。每条声明定义了所选元素的一个属性。
一个 CSS 样式表包含了一个或者多个规则。
CSS 选择器
选择器是 CSS 规则的第一部分,被用于选择要被添加样式的 HTML 元素。选择器所选择的元素,被称为选择器的对象(subject of the selector)。
类型选择器 (type selector)
类型选择器通过node节点名称来匹配元素,单独使用时会匹配所有此类型的元素。
其语法为:
element { style properties }
如:
span {
background-color: skyblue;
}
类选择器 (class selector)
在一个HTML文档中,CSS类选择器会根据元素的类属性中的内容匹配元素。类属性被定义为一个以空格分隔的列表项,在这组类名中,必须有一项与类选择器中的类名完全匹配,此条样式声明才会生效。
其语法为:
.class_name { style properties }
(等效于[class~=class_name] { style properties }
,见标签属性匹配器)
如:
.red {
color: #f33;
}
.yellow-bg {
background: #ffa;
}
作用于如下 HTML:
<p class="red">This paragraph has red text.</p>
<p class="red yellow-bg">This paragraph has red text and a yellow background.</p>
ID选择器 (ID selector)
在一个HTML文档中,CSS ID 选择器会根据该元素的 ID 属性中的内容匹配元素,元素 ID 属性名必须与选择器中的 ID 属性名完全匹配,此条样式声明才会生效。
语法:
#id_value { style properties }
等效于:
[id=id_value] { style properties }
示例:
#demo {
background-color: DodgerBlue;
}
<p id="identified">Here's a span with some text.</p>
通配选择器 (universal selector)
在CSS中,一个星号(*
)就是一个通配选择器.它可以匹配任意类型的HTML元素。(通常不使用通配选择器因为它是性能最低的选择器。)
示例:
* {color:red;}
标签属性匹配器 (attribute selector)
CSS 标签属性匹配器通过匹配元素的特定属性值来选择元素。
/* 存在title属性的<a> 元素 */
a[title] {
color: purple;
}
/* 存在href属性并且属性值匹配"https://example.org"的<a> 元素 */
a[href="https://example.org"] {
color: green;
}
/* 存在href属性并且属性值包含"example"的<a> 元素 */
a[href*="example"] {
font-size: 2em;
}
/* 存在href属性并且属性值结尾是".org"的<a> 元素 */
a[href$=".org"] {
font-style: italic;
}
/* 存在class属性并且属性值包含"logo"的<a>元素 */
a[class~="logo"] {
padding: 2px;
}
attribute 与 value 间的运算符有:
运算符 | 说明 |
---|---|
= | 有以 attr 命名的属性,且属性值为 value 的元素 |
~= | 有以 attr 命名的属性的元素,并且该属性是一个以空格作为分隔的值列表,其中至少有一个值为 value |
|= | 有以 attr 命名的属性的元素,属性值为“value”或是以“value-”为前缀 (常用于匹配语言,如 zh-CN,zh-TW 可以用 zh 作为 value) |
^= | 有以 attr 命名的属性,且属性值是以 value 开头的元素。 |
$= | 有以 attr 命名的属性,且属性值是以 value 结尾的元素 |
*= | 有以 attr 命名的属性,且属性值包含有 value 的元素。 |
伪类 (pseudo-classes) 与 伪元素 (pseudo-elements)
CSS 伪类 是添加到选择器的关键字,指定要选择的元素的特殊状态。例如,:hover 可被用于在用户将鼠标悬停在按钮上时改变按钮的颜色。
/* 所有用户指针悬停的按钮 */
button:hover {
color: blue;
}
伪元素 是一个附加至选择器末的关键词,允许你对被选择元素的特定部分修改样式。下例中的 ::first-line 伪元素可改变段落首行文字的样式。
/* 每一个 <p> 元素的第一行。 */
p::first-line {
color: blue;
text-transform: uppercase;
}
完整的伪类与伪元素列表可参见:
选择器的组合
可以使用运算符来将多个选择器组合起来,来用更复杂的规则选择元素。下面的示例用运算符(>)选择了<article>
元素的初代<p>
子元素。
article > p { }
选择器 | 示例 | 说明 |
---|---|---|
后代选择器 | article p |
满足第二个选择器且有一个祖先(父亲,父亲的父亲…)满足第一个选择器的元素 |
子代选择器 | article > p |
满足第二个选择器且父祖先元素满足第一个选择器的元素 |
相邻兄弟选择器 | h1 + p |
选中一个元素相邻的兄弟元素。例如,p + img 选中所有紧随<p> 元素之后的<img> 元素 |
通用兄弟选择器 | h1 ~ p |
选中一个元素的兄弟元素,即使它们不直接相邻。例如,p ~ img 选中所有的<p> 元素后任何地方的<img> 元素 |
选择器列表
如果有多个使用相同样式的CSS选择器,那么这些单独的选择器可以被混编为一个选择器列表。多个选择器间使用逗号分隔。例如如下的规则
h1 {
color: blue;
}
.special {
color: blue;
}
可以写为 (换行是可选的):
h1,
.special {
color: blue;
}
CSS 层叠与优先级
当 CSS 的多条规则发生冲突时,浏览器需要决定应用哪个规则,而这套机制被称为 层叠 (cascade) 与 优先级 (specificity)。
层叠
层叠 (cascade) 简单来说就是当两条同级别的规则应用到同一个元素时,会采用写在后面的规则。例如下面的例子中有两条关于h1
的规则,而h1
最终呈蓝色——也就是写在后面的规则。
h1 {
color: red;
}
h1 {
color: blue;
}
<h1>This is my heading.</h1>
优先级
浏览器是根据优先级来决定当 多个规则 有不同选择器 对应相同的元素 的时候需要使用哪个规则。它总体来说取决于选择器的具体程度,如:
- 一个元素选择器不是很具体 — 会选择页面上该类型的所有元素 — 所以它的优先级就会低一些
- 一个类选择器稍微具体点 — 它会选择该页面中有特定 class 属性值的元素 — 所以它的优先级就要高一点。
因此在下面的例子中,最终会呈现红色——也就是更具体的类选择器指定的规则:
.main-heading {
color: red;
}
h1 {
color: blue;
}
<h1 class="main-heading">This is my heading.</h1>
效果:
This is my heading.
优先级的计算方法简单来说:
- 每个类型(元素)、伪元素选择器权重为 1
- 类、伪类及标签属性选择器权重为 10
- ID 选择器权重为 100
- 内联样式权重为 1000
!important
(可以添加到CSS属性值的末尾,如border: none !important;
) 权重为 10000
当选择器为多个选择器组合时,则取所有选择器权重的和。
比如 #myDiv li.class a[href]
有一个ID选择器 (myDiv
) ,两个类/元素选择器 (.class
, [href]
) 以及两个类型选择器 (li
, a
) 所以其优先级为 122。可以参见 CSS SPECIFISHITY。
CSS 继承
一些设置在父元素上的css属性(例如 color
和 font-family
) 可以被子元素继承。下面的例子中 <span>
内的内容就继承了 <p>
的颜色,同样变成了蓝色。
p {
color: blue;
}
<p>We can change the color by targetting the element with a selector, such as this <span>span</span>.</p>
We can change the color by targetting the element with a selector, such as this span.
一些属性是不能被继承的,例如 width
, margins
, padding
, 和 borders
。哪些属性属于默认继承很大程度上是由常识决定的。
控制继承
CSS 为控制继承提供了四个特殊的通用属性值。每个css属性都接收这些值。
- inherit
设置该属性会使子元素属性和父元素相同。实际上,就是 “开启继承”. -
initial
设置属性值和浏览器默认样式相同。如果浏览器默认样式中未设置且该属性是自然继承的,那么会设置为 inherit 。 -
unset
将属性重置为自然值,也就是如果属性是自然继承那么就是 inherit,否则和 initial一样 -
revert (只有部分浏览器支持)
将属性重置于没有应用当前属性源(style origin
, 有user-agent origin
,user origin
及author origin
)时的样式。目前只在 Firefox 以及 Safari 中被支持
CSS 的缩写属性 all 可以用于同时将这些继承值中的一个应用于(几乎)所有属性。这是一种撤销对样式所做更改的简便方法。
示例:
.my-class {
color: inherit;
}
.fix-this {
all: unset;
}
CSS 盒模型
在 CSS 中,所有的元素都被一个个的“盒子(box)”包围着,理解这些“盒子”的基本原理,是我们使用CSS实现准确布局、处理元素排列的关键。
在 CSS 中我们广泛地使用两种“盒子” —— 块级盒子 (block box) 和 内联盒子 (inline box)。这两种盒子会在页面流(page flow)和元素之间的关系方面表现出不同的行为:
块级盒子 (block box)
一个被定义成块级的(block)盒子会表现出以下行为:
- 盒子会在内联的方向上扩展并占据父容器在该方向上的所有可用空间,在绝大数情况下意味着盒子会和父容器一样宽
- 每个盒子都会换行
width
和height
属性可以发挥作用- 内边距(padding), 外边距(margin) 和 边框(border) 会将其他元素从当前盒子周围“推开”
除非特殊指定,诸如标题(<h1>
等)和段落(<p>
)默认情况下都是块级的盒子。
内联盒子 (inline box)
如果一个盒子对外显示为 inline,那么他的行为如下:
- 盒子不会产生换行。
width
和height
属性将不起作用。- 垂直方向的内边距、外边距以及边框会被应用但是不会把其他处于 inline 状态的盒子推开。
- 水平方向的内边距、外边距以及边框会被应用而且也会把其他处于 inline 状态的盒子推开。
用做链接的 <a>
元素、 <span>
、 <em>
以及 <strong>
都是默认处于 inline 状态的。
我们也可以通过对盒子display 属性的设置,比如 inline 或者 block ,来控制盒子的外部显示类型。
盒模型
CSS中组成一个块级盒子需要:
- Content box: 这个区域是用来显示内容,大小可以通过设置 width 和 height.
- Padding box: 包围在内容区域外部的空白区域; 大小通过 padding 相关属性设置。
- Border box: 边框盒包裹内容和内边距。大小通过 border 相关属性设置。
- Margin box: 这是最外面的区域,是盒子和其他元素之间的空白区域。大小通过 margin 相关属性设置。
如下图:
[]
在上图的标准盒模型中, width
和 height
设定了 content box
的大小,而最终盒子的大小还需要加上 padding 以及 border (margin 不计入实际大小)。CSS 还有一个替代盒模型,在这种模式下 width
和 height
指定了盒子可见区域的大小 (border 的大小):
[]
浏览器默认使用标准模型,如果要使用替代模型,可以设置元素的 box-sizing
为 border-box
:
.box {
box-sizing: border-box;
}
可以用下面的写法使所有元素都使用替代模型:
html {
box-sizing: border-box;
}
*, *::before, *::after {
box-sizing: inherit;
}
(这里使用 *::before
, *::after
是因为伪元素并不能被 *
直接选中。)