CSS 中那些大大小小的坑
· 20 min read
中国读者不是不善于交流,而是对基础知识掌握不够牢固,不敢交流。就如同有人提到用英文写作时所说的,最难的不是怎么写,而是写什么。英文语法错误其实是别人最容易纠正的,但你到底想要表达什么则是别人无法知道的。具体到CSS,虽然不难学,但真正彻底把原理和基本概念全搞通也不是一件容易的事。 —— 李松峰
最近读完了Charles Wyke-Smith的《CSS设计指南》,上面那段话是节选的译者李松峰的序(在这多说一句,觉得李松峰翻译的书质量都很高,现在的我基本在遍历)。越来越觉得只读书不思考是毫无用处的,于是把笔记整理出来,并加上了自己思考过的感悟。
CHAPTER 1 HTML标记与文档结构
用HTML标记内容的目的是为了赋予网页语义(semantic)。换句话说,就是要给你的网页内容赋予某些用户代理(user agent)能 够理解的含义。 浏览器、屏幕阅读器,以及搜索引擎放出的web爬虫都是用户代理,它们需要显示、朗读和分析网页。
-
文本用闭合标签,引用内容用自闭合标签。
- 闭合标签与自闭合标签的区别在于,闭合标签包含的是会显示的实际内容,而自闭合标签只是给浏览器提供一个对要显示内容的引用。浏览器会在HTML页面加载时候,额外向服务器发送请求,以取得自闭合标签引用的内容。
- 属性alt(alternative),定义的是在图片因故未能加载成功时候在屏幕上显示的文本。视障用户的屏幕阅读器会大声读出alt属性的内容,因此一定要给
<img>
标签的alt
属性添加让人一听(或一看)就能明白的内容。 <h1>
被搜索引擎视为仅次于<tittle>
标签的另一个搜索关键词重要来源。- 只要有不适合放在其他文本标签中的文本,都可以把它放在一个段落里。
- 某些标签,如
<ol>
要求其他标签,如<li>
与之共同出现。 <!DOCTYPE html>
是DTD(文档类型定义),声明:“以下是一个HTML文档。”<html>
只有两个直接的子标签:<head>
和<body>
。帮助浏览器理解页面的信息都包含在<head>
标签中。- 块级标签:标题、段落、列表、独立引用等,如文档流一般上下堆叠显示;行内标签:链接、图片、字体样式、简写
<abbr>
、引证<cite>
、文本内引用<q>
相互并列显示,只有在空间不足以并列的情况下才会折到下一行。 - 块级元素盒子会拓展到与父元素同宽。
- 行内元素盒子会“收缩包裹”其内容,并且会尽可能包紧。
- DOM(文档对象模型)是从浏览器的视角来观察页面中的元素及每个元素的属性,由此得出这些元素的一个家族树。通过DOM,可以确定元素之间的相互关系。在CSS中引用DOM中特定的位置,就可以选中相应的HTML元素,并修改其样式属性。CSS修改了元素后,这些变化会立即在DOM中发生,并体现在页面上。
CHAPTER 2 CSS工作原理
当元素的同一个样式属性有多种样式值的时候,CSS靠层叠机制来决定最终应用哪种样式。
- 为文档添加样式的三种方法:
- 行内样式 :
<p style="font-size: 12px; font-weight: bold;">Adding inline CSS styling</p>
作用范围:只影响它所在的标签,而且总会覆盖嵌入样式和链接样式。 - 嵌入样式: 嵌在
head
元素中。如<head><style type="text/css">...</style></head>
作用范围仅限于当前页面。会覆盖外部样式表,但被行内样式覆盖。 - 链接样式:把样式集中在一个单独文件——样式表(一个拓展名为.css的文本文件)。
在多个HTML中连接同一个样式表:
<link href="style.css" rel="stylesheet" type="text/css" />
作用范围:有<link>
标签的页面。 - @import指令:一种@规则,可以在样式表中链接其他样式表。
import url(css/style2.css)
注意:@import必须出现在样式表其他样式之前,否则不会被加载。(见link css与@import css 的区别)
- 行内样式 :
- 一般上下文选择符。 基于祖先或同胞元素选择一个元素。
tag1 tag2 {statements}
只要tag2在整个结构层次中有个tag1的祖先元素,无论上下文之间隔着多少层次没有关系。 - 子选择符
>
tag1 > tag2
标签2必须是标签1的子元素。 - 紧邻同胞选择符
+
tag1 + tag2
标签2必须紧跟在其同胞标签1后面。 - 一般同胞选择符
~
tag1 ~ tag2
标签2必须跟(不一定紧跟)在其同胞标签1后面。 - 通用选择符
*
匹配任何元素。* {color: green;}
color
属性设定的是前景色,前景色既影响文本也影响边框,但一般用来设定文本颜色。 故p * {color: red;}
改变p包含的所有元素的文本变成红色。 构成非子选择符:section * a {font-size: 1.3em}
任何是section孙子元素,而非子元素的a标签都会被选中。 - 多类选择符。
<p class="specialtext featured">...</p>
选择同时存在这两个类名的元素:.specialtext.featured {statements}
注意两个类名之间没有空格,因为选择同时具有这个类名的那个元素。 - ID属性:ID用于页内导航链接。
-
<h3 id="bio">Biography</h3>
<p>....</p>
`href`属性值开头的`#`表示链接的目标在当前页面中,因而不会触发浏览器加载页面(如果没有#,浏览器会尝试加载bio目录下的默认页面)。会跳到h3元素的位置。
`<a href="#">Back to Top</a>` 点击该链接返回页面顶部。
另外,如果不知道href放什么URL,可以用#作为占位符,但不能留空,因为href属性值为空的链接行为跟正常链接不一样。 -
- ID是为了唯一的标识一个元素。每个ID名在页面中只能用一次。给页面中每个顶级区域都添加一个ID,得到明确的上下文。
- 类是为了标识一组具有相同特征的元素。
- 属性名选择符
标签名[属性名]
,选择任何带有属性名的标签名。 什么时候使用?一般经常给alt和title属性设定相同的值。alt属性中的文本会在图片因故未能加载时显示,或者由屏幕朗读器朗读出来。而title属性会在用户鼠标移动到图片上时,显示一个包含相应文本的提示。 - 属性值选择符
标签名[属性名="属性值"]
,选择任何带有值为属性值的属性名的标签名。 - UI伪类在HTML元素处于某种状态时应用CSS。
- 链接伪类。
::link/::visited / ::hover / ::active
:focus
伪类。e:focus
在单击它获得焦点时候改变CSS。:target
伪类。e:target
如果用户点击一个指向页面中其他元素的链接,则那个元素就是目标(target),可以用:target伪类选中它。
那么规则<a href="#more_info">More Information</a>
<h2 id="more_info">This is the information you are looking for.</h2>#more_info:target {background: #eee;}
会在用户单击链接转向ID为more_info的元素时候,为该元素(h2)添加浅灰色背景,以便在一大堆引证中识别。(实例见Wikipedia) - 链接伪类。
- 结构伪类
li:frist-child
&li:last-child
代表一组同胞元素中第一个或最后一个元素。e:nth-child(n)
e为元素名,n表示一个数值(也可以使用odd或even)。用于提高表格的可读性,对表格的所有行交替应用不同颜色。
- 伪元素(CSS3 new)
e::first-letter
首字符。e::first-line
文本段落第一行,长度会随着浏览器窗口大小变换而改变。::before
和::after
伪元素,可用在特定元素前后添加特殊内容。(见用CSS伪类绘制各种图形 CSS trick)
- 继承:文本样式(颜色)及字体(字号)。不继承元素盒子的定位和显示方式(边距、边框等)。所以使用相对字体单位(em和百分比)要格外小心!
- 层叠:样式在文档层次中逐层叠加。
- 层叠顺序:浏览器默认CSS->用户CSS->作者链接CSS(按照它们链接到页面的先后顺序)->作者嵌入CSS->作者行内CSS。
- 层叠规则:
- 找到应用给每个元素和属性的所有声明。
- 按顺序和权重排序。
!important;
用于加重声明的权重。 - 按特指度(specificity)排序。ID>类>标签名。但设定的样式胜过继承的样式。
- 顺序决定权重。位置靠下或者后声明的规则胜出。
- em和ex都是字体大小的单位。但它们作为长度单位适用于任何元素。
- em表示一种字体中字母M的宽度,因此它的具体大小取决于你使用的字体。
- ex等于给定字体中字母x的高度(小写字母x代表一种字体的字母中间部分的高度,不包括字母上下突出的部分——如d、p上下出头)。
- 百分比非常适合设定被包含元素的宽度,此时的百分比是相对于宽度而言。可以把HTML结构元素宽度设定为body宽度的百分比,“流式”设计的关键,可以根据浏览器窗口大小而成比例伸缩。
- 饱和度设定有多少颜色,灰色的饱和度低,而强烈色彩饱和度高。亮度设定颜色的明暗,0%就是黑色,100%就是白色。