1、CSS基础知识
1.1、CSS的工作机制
当浏览器展示一个文件的时候,它必须兼顾文件的内容和文件的样式信息,下面我们会了解到它处理文件的标准的流程。需要知道的是,下面的步骤是浏览加载网页的简化版本,而且不同的浏览器在处理文件的时候会有不同的方式,但是下面的步骤基本都会出现。
浏览器载入HTML文件(比如从网络上获取)。
将HTML文件转化成一个DOM(Document Object Model),DOM是文件在计算机内存中的表现形式,下一节将更加详细的解释DOM。
接下来,浏览器会拉取该HTML相关的大部分资源,比如嵌入到页面的图片、视频和CSS样式。JavaScript则会稍后进行处理,简单起见,同时此节主讲CSS,所以这里对如何加载JavaScript不会展开叙述。
浏览器拉取到CSS之后会进行解析,根据选择器的不同类型(比如element、class、id等等)把他们分到不同的“桶”中。浏览器基于它找到的不同的选择器,将不同的规则(基于选择器的规则,如元素选择器、类选择器、id选择器等)应用在对应的DOM的节点中,并添加节点依赖的样式(这个中间步骤称为渲染树)。
上述的规则应用于渲染树之后,渲染树会依照应该出现的结构进行布局。
网页展示在屏幕上(这一步被称为着色)。
结合下面的图示更形象:
1.2、什么是DOM?
DOM是CSS样式和文件内容的结合,它是一个树形结构,标记语言中的每一个元素、属性以及每一段文字都对应着结构树中的一个节点(Node/DOM或DOM node)。节点由节点本身和其他DOM节点的关系定义,有些节点有父节点,有些节点有兄弟节点(同级节点)。
一个真实的DOM案例
不同于很长且枯燥的案例,这里我们通过一个HTML片段来了解HTML怎么转化成DOM
以下列HTML代码为例:
<p>
Let's use:
<span>Cascading</span>
<span>Style</span>
<span>Sheets</span>
</p>
在这个DOM中,
元素对应了父节点,它的子节点是一个text节点和三个对应了元素的节点,SPAN节点同时也是他们中的Text节点的父节点。
P
├─ "Let's use:"
├─ SPAN
| └─ "Cascading"
├─ SPAN
| └─ "Style"
└─ SPAN
└─ "Sheets"
上图就是浏览器怎么解析之前那个HTML片段——它生成上图的DOM树形结构并将它按照如下输出到浏览器:
特别地,当浏览器遇到无法解析的CSS代码时,会跳过自动解析下一个CSS样式;当有新版本不兼容时,也会这样处理,优点:容错性杠杠滴。
1.3、一些CSS的样式
样式就是该内容的属性,你想呈现的样式效果:字体大小,颜色,字体是否斜体,或者字体是否为标题…等等;
font-family
color
border-bottom
font-weight
font-size
text-decoration
也可以许多不同的选择器(样式元素),如h1和h2,建立了一个类别。
2、CSS的高级技巧
2.1、层叠、优先级和继承
层叠
Stylesheets cascade(样式表层叠) —当应用两条同级别的规则到一个元素的时候,写在后面的就是实际使用的规则。
例如,我们有两个关于 h1 的规则。h1 最后显示蓝色 — 这些规则有相同的优先级,所以顺序在最后的生效。
优先级
**浏览器是根据优先级来决定当多个规则有不同选择器对应相同的元素的时候需要使用哪个规则。**它基本上是一个衡量选择器具体选择哪些区域的尺度:
一个元素选择器不是很具体 — 会选择页面上该类型的所有元素 — 所以它的优先级就会低一些。
一个类选择器稍微具体点 — 它会选择该页面中有特定 class 属性值的元素 — 所以它的优先级就要高一点。
举例时间! 下面我们再来介绍两个适用于 h1 的规则。下面的 h1 最后会显示红色 — 类选择器有更高的优先级,因此就会被应用——即使元素选择器顺序在它后面。
继承
继承也需要在上下文中去理解 —— 一些设置在父元素上的css属性是可以被子元素继承的,有些则不能。
举一个例子,如果你设置一个元素的 color 和 font-family ,每个在里面的元素也都会有相同的属性,除非你直接在元素上设置属性。
一些属性是不能继承的 — 举个例子如果你在一个元素上设置 width 50% ,所有的后代不会是父元素的宽度的50% 。如果这个也可以继承的话,CSS就会很难使用了!
2.2、层叠、优先级和继承的协同
2.2.1、继承
理解继承
像 widths (上面提到的), margins, padding, 和 borders 不会被继承。如果borders可以被继承,每个列表和列表项都会获得一个边框 — 可能就不是我们想要的结果!
哪些属性属于默认继承很大程度上是由常识决定的。
控制继承
CSS 为控制继承提供了四个特殊的通用属性值。每个css属性都接收这些值。
inherit
设置该属性会使子元素属性和父元素相同。实际上,就是 “开启继承”.
initial
设置属性值和浏览器默认样式相同。如果浏览器默认样式中未设置且该属性是自然继承的,那么会设置为 inherit 。
unset
将属性重置为自然值,也就是如果属性是自然继承那么就是 inherit,否则和 initial一样
2.2.2、层叠
我们已经知道:为什么嵌套在html结构中的段落和应用于正文中的css颜色相同,了解了如何将文档中的任何修改应用于某个对象的css,
层叠如何定义在不止一个元素的时候怎么应用css规则?
有三个因素需要考虑,根据重要性排序如下,前面的更重要:
重要程度
优先级
资源顺序
我们从下往上,看看浏览器是如何决定该应用哪个css规则的。
资源顺序
我们已经看到了顺序对于层叠的重要性。如果你有超过一条规则,而且都是相同的权重,那么最后面的规则会应用。可以理解为后面的规则覆盖前面的规则,直到最后一个开始设置样式。
2.2.3、优先级
在你了解了顺序的重要性后,会发现在一些情况下,有些规则在最后出现,但是却应用了前面的规则。这是因为前面的有更高的优先级 — 它范围更小,因此浏览器就把它选择为元素的样式。
就像前面看到的,类选择器的权重大于元素选择器,因此类上定义的属性将覆盖应用于元素上的属性。
这里需要注意虽然我们考虑的是选择器,以及应用在选中对象上的规则,但不会覆盖所有规则,只有相同的属性。
这样可以避免重复的 CSS。一种常见的做法是给基本元素定义通用样式,然后给不同的元素创建对应的类。举个例子,在下面的样式中我给2级标题定义了通用样式,然后创建了一些类只修改部分属性的值。最初定义的值应用于所有标题,然后更具体的值通过对应类来实现。
CSS位置的影响
最后,也很有用,CSS声明的重要性取决于样式表中指定的——它让用户可以设置自定义样式表来覆盖开发人员定义的样式。例如用户可能视力受损,并想在所有网页上设置两倍的正常字体大小,以便更容易进行阅读。
3、CSS选择器
3.1、标签类型、类、ID选择器
3.1.1、类型选择器
类型选择器有时也叫做“标签名选择器”或者是”元素选择器“,因为它在文档中选择了一个HTML标签/元素的缘故。在下面的示例中,我们已经用了span、em和strong选择器,、和元素的所有实例这样就都被样式化了。
这个选择器组,第一个是指向了所有HTML元素
。
h1 { }
3.1.2、类选择器
类选择器以一个句点(.)开头,会选择文档中应用了这个类的所有物件。在下面的实时示例中,我们已经建立了一个名为.highlight的类,把它应用到了我的文档中的几个地方。所有包含此类的元素都被高亮了。
指向特定元素的类
你能建立一个指向应用一个类的特定元素。在下一个示例里面,我们将会用不同方式高亮一个带有highlight类的和带有 highlight类的
标题。我们通过使用附加了类的欲选元素的选择器做到这点,其间没有空格。
多个类被应用的时候指向一个元素
你能对一个元素应用多个类,然后分别指向它们,或者仅仅在选择器中存在所有这些类的时候选择这一元素。在你的站点上,构建可以以不同方式组合起来的组件的时候,这会有用。
在下面的示例中,有一个包含了一条笔记的
为了告诉浏览器我们只想匹配带有所有这些类的元素,我们可以将这些类不加空格地连成一串。
它也包含了一个class的选择器:
.box { }
3.1.3、ID选择器
一个id选择器:
ID选择器开头为#而非句点,不过基本上和类选择器是同种用法。可是在一篇文档中,一个ID只会用到一次。它能选中设定了id的元素,你能把ID放在类型选择器之前,只指向元素和ID都匹配的类。在下面的示例里,你可以看看这两种用法。
#unique { }
3.2、标签属性选择器
3.2.1、存否和值选择器
这组选择器根据一个元素上的某个标签的属性的存在以选择元素的不同方式:
选择器 | 示例 | 描述 |
---|---|---|
[attr] | a[title] | 匹配带有一个名为attr的属性的元素——方括号里的值。 |
[attr=value] | a[href=“https://example.com”] | 匹配带有一个名为attr的属性的元素,其值正为value——引号中的字符串。 |
[attr~=value] | p[class~=“special”] | 匹配带有一个名为attr的属性的元素 ,其值正为value,或者匹配带有一个attr属性的元素,其值有一个或者更多,至少有一个和value匹配。注意,在一列中的好几个值,是用空格隔开的。 |
[attr | =value] | div[lang |
a[title] { }
或者根据一个有特定值的标签属性是否存在来选择:
a[href="https://example.com"] { }
使用li[class],我们就能匹配任何有class属性的选择器。这匹配了除了第一项以外的所有项。
li[class=“a”]匹配带有一个a类的选择器,不过不会选中一部分值为a而另一部分是另一个用空格隔开的值的类,它选中了第二项。
li[class~=“a”]会匹配一个a类,不过也可以匹配一列用空格分开、包含a类的值,它选中了第二和第三项。
3.2.2、子字符串匹配选择器
这些选择器让更高级的属性的值的子字符串的匹配变得可行。例如,如果你有box-warning和box-error类,想把开头为“box-”字符串的每个物件都匹配上的话,你可以用[class^=“box-”]来把它们两个都选中。
选择器 | 示例 | 描述 |
---|---|---|
[attr^=value] | li[class^=“box-”] | 匹配带有一个名为attr的属性的元素,其值开头为value子字符串。 |
[attr$=value] | li[class$="-box"] | 匹配带有一个名为attr的属性的元素,其值结尾为value子字符串 |
[attr*=value] | li[class*=“box”] | 匹配带有一个名为attr的属性的元素,其值的字符串中的任何地方,至少出现了一次value子字符串。 |
下个示例展示了这些选择器的用法:
li[class^=“a”]匹配了任何值开头为a的属性,于是匹配了前两项。
li[class$=“a”]匹配了任何值结尾为a的属性,于是匹配了第一和第三项。
li[class*=“a”]匹配了任何值的字符串中出现了a的属性,于是匹配了所有项。
3.2.3、大小写敏感
如果你想在大小写不敏感的情况下,匹配属性值的话,你可以在闭合括号之前,使用i值。这个标记告诉浏览器,要以大小写不敏感的方式匹配ASCII字符。没有了这个标记的话,值会按照文档语言对大小写的处理方式,进行匹配——HTML中是大小写敏感的。
下面的示例中,第一个选择器将会匹配一个开头为a的值,这样它只匹配了第一项,因为另外两项开头是大写的A。第二个选择器使用了大小写不敏感的标记,于是匹配了所有项。
3.3、伪类与伪元素
3.3.1、伪类是什么?
这组选择器包含了伪类,用来样式化一个元素的特定状态。例如:hover伪类会在鼠标指针悬浮到一个元素上的时候选择这个元素:
伪类是一个选择处于特定状态的元素的选择器,比如它们是这一类型的第一个元素的时候,或者是鼠标指针悬浮在上面的时候。它们表现得会像是你向你的文档的某个部分应用了一个类一样,帮你在你的标记文本中减少多余的类,让你的代码更灵活、更易于维护。
伪类就是开头为冒号的关键字:
:pseudo-class-name
3.3.2、用户行为伪类
一些伪类只会在用户以某种方式和文档交互的时候应用。这些用户行为伪类,有时叫做动态伪类,表现得就像是一个类在用户和元素交互的时候加到了元素上一样。案例包括:
:hover——上面提到过,只会在用户将指针挪到元素上的时候才会激活,一般就是链接元素。
:focus——只会在用户使用键盘控制,选定元素的时候激活。
a:hover { }
它还可以包含了伪元素,选择一个元素的某个部分而不是元素自己。例如,::first-line是会选择一个元素(下面的情况中是
)中的第一行,类似包在了第一个被格式化的行外面,然后选择这个。
p::first-line { }
3.3.3、伪元素是什么?
伪元素以类似方式表现,不过表现得是像你往标记文本中加入全新的HTML元素一样,而不是向现有的元素上应用类。伪元素开头为双冒号::。
::pseudo-element-name
备注:一些早期的伪元素曾使用单冒号的语法,所以你可能会在代码或者示例中看到。现代的浏览器为了保持后向兼容,支持早期的带有单双冒号语法的伪元素。
例如,如果你想选中一段的第一行,你可以把它用一个元素包起来,然后使用元素选择器;不过,如果包起来的单词/字符数目长于或者短于父元素的宽度,这样做会失败。由于我们一般不会知道一行能放下多少单词/字符——因为屏幕宽度或者字体大小改变的时候这也会变——通过改变HTML的方式来可预测地这么做是不可能的。
::first-line伪元素选择器会值得信赖地做到这件事——即使单词/字符的数目改变,它也只会选中第一行。
3.3.4、把伪类和伪元素组合起来
如果你想让第一段的第一行加粗,你需要把:first-child和::first-line选择器放到一起。试着编辑前面的实时示例,让它使用下面的CSS。这里的意思是,我们想选择一个
元素的第一行。
article p:first-child::first-line {
font-size: 120%;
font-weight: bold;
}
3.3.5、生成带有::before和::after的内容
有一组特别的伪元素,它们和content属性一同使用,使用CSS将内容插入到你的文档中中。
你能用这些插入一个文本字符串,和在下面的实时示例里那样。试着改变content属性的文本值,看看输出是怎么改变的。你也能改变::before伪元素为::after,看到这段文本插入到了元素的末尾而不是开头。