CSS进阶笔记上
介绍
费曼学习法最重要的部分,即把知识教给一个完全不懂的孩子——或者小白。
为了更好的自我学习,也为了让第一次接触某个知识范畴的同学快速入门,我会把我的学习笔记整理成电子幽灵系列。
提示:文章的是以解释-代码块-解释的结构呈现的。当你看到代码块并准备复制复现的时候,最好先保证自己看过了代码块前后的解释。
CSS进阶笔记上
本篇笔记主要来源于对 菜鸟教程:HTML教程的学习。
简介
在前两次笔记当中,我们已经学习了CSS的基础用法和很多常用的属性,这些足以让我们搭建起一个美观而现代化的网页了;但是CSS还有一些更高级的用法,而且我们的网页还缺乏必要的交互手段。在CSS中属性如此多样的前提下,如果我们想快速上手构建一个相对成熟而实用的网页,一些常用的实现框架可以帮到我们。在这个笔记当中,我们会看到选择器的更多高级用法,更多的实例和框架会在下一个笔记中给出。
约定规范
- 虽然对于伪元素而言,"选择器:伪元素"和"选择器::伪元素"的形式都有相同的结果,但是为了与伪类区分开来,同时和最新版本CSS3中的新实现同步,在实际使用时,请使用"选择器::伪元素"这一形式。
- 随便用!important是一种非常不好的习惯。如果不加规范地随便使用,会让后续的优化和维护难度增加;而且在编程过程中也会造成不必要的混乱。如果一定要用!important规范,应当遵守以下规则:
- 先考虑问题是否则可以通过使用优先级来解决,如果不行再考虑用!important。
- 永远不要在插件中使用!important。
- 只有当某样式需要覆盖全站或者某特定页面时使用!important。
CSS选择器高级用法
选择器:组合选择符
在CSS基础笔记下中,我们曾提到CSS的OOP思想。HTML中的元素是互相嵌套的,我们也可以把元素看做是一个个大大小小的对象;他们之间的嵌套可以看做继承。这种思想在选择器中得到了充分发挥——我们可以利用组合选择符达成样式共用/继承的目的。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS组合选择符示例</title>
<style>
/* 后代选择符 */
div p {
color: blue;
}
/* 子选择符 */
div > p {
font-weight: bold;
}
/* 相邻兄弟选择符 */
h2 + p {
text-decoration: underline;
}
/* 后续兄弟选择符 */
h3 ~ p {
font-style: italic;
}
</style>
</head>
<body>
<h1>CSS组合选择符示例</h1>
<div>
<p>这是一个在div中的段落。使用后代选择符(div p)会应用蓝色字体。</p>
<p>这也是一个在div中的段落。使用子选择符(div > p)会应用加粗字体。</p>
<span><p>但是,由于这个p元素不是直接被div所嵌套的,所以它是div的后代,但并不是子代。</p></span>
</div>
<h2>这是一个标题</h2>
<p>这是一个紧跟在h2后面的p。使用相邻兄弟选择符(h2 + p)会应用下划线。</span>
<p>这就不是紧跟在h2后面的p。不会应用下划线。</p>
<h3>这是另一个标题</h3>
<p>这是一个跟在h3后面的段落。使用通用兄弟选择符(h3 ~ p)会应用斜体字体。</p>
<p>这是另一个跟在h3后面的段落。同样会应用斜体字体。</p>
<span><p>这个段落虽然也跟在h3后面,但是它和h3并不是同级(兄弟),所以不会应用斜体字体。</p></span>
<p>这是另一个跟在h3后面的段落。同样会应用斜体字体。</p>
</body>
</html>
- 后代选择符: 选择器1 选择器2 {[样式]}
任何嵌套在选择器1中的选择器2都应用某样式
- 子代选择符: 选择器1 > 选择器2 {[样式]}
任何直接嵌套在选择器1中的选择器2都应用某样式
- 相邻兄弟选择符: 选择器1 + 选择器2 {[样式]}
在同一个块中,紧跟在选择器1后的同级选择器2都应用某样式
- 后续兄弟选择符: 选择器1 ~ 选择器2 {[样式]}
在同一个块中,选择器1后的所有同级选择器2都应用某样式
伪类、伪元素
元素有很多种细分状态,可以把这些状态看做是元素的继承类——即伪类。而元素中有很多经典的实现只涉及元素的一部分,所以可以把某些部分单独拿出来当做元素处理——即伪元素。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>伪类和伪元素示例</title>
<style>
/* 伪类示例 */
a:link {
color: blue;
}
a:visited {
color: purple;
}
a:hover {
color: red;
text-decoration: underline;
}
a:active {
color: green;
}
/* 伪元素示例 */
p::first-line {
font-weight: bold;
}
p::first-letter {
font-size: 2em;
color: red;
}
p::before {
content: ">> ";
color: blue;
}
p::after {
content: " <<";
color: blue;
}
p:hover{
background-color: yellow;
}
</style>
</head>
<body>
<h1>伪类和伪元素示例</h1>
<h2>伪类示例</h2>
<p>这是一个链接伪类示例:</p>
<a href="https://www.example.com">访问示例网站</a>
<h2>伪元素示例</h2>
<p>这是一个伪元素示例。第一行会被加粗,第一个字母会变大且变红。在段落前后会添加箭头符号。</p>
</body>
</html>
伪类
伪类的格式是"选择器:伪类"。最常用的伪类莫过于链接常用的几种:普通链接(正常情况):link、访问(点击)过:visited、光标悬于其上:hover、点击时active。虽然链接常用这些,但是其他元素也可以使用。
还有一些伪类,比如first-child,可以控制选择器所嵌套的第一个元素中的内容;lang,可以根据元素中的lang属性来控制元素(比如,p:lang(no)就是当出现 < p lang = “no” >时起作用)。
伪类可以和其他选择器使用手段一同出现,比如CSS选择器类、选择器id、组合选择符等等。
伪元素
伪元素的格式是"选择器::伪元素"。约定规范1
常见的伪元素有:
- first-line:为首行设置特殊样式
- first-letter:为首字母/第一个字设置特殊样式
- before/after:在元素前/后添加新内容
等等…
媒体类型
为了让网页的兼容性更高,让它在每一种媒体上都能有适应性的样式,我们可以选择在不同的网页上有不同的实现;媒体类型选择器让我们能够做到这一点。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>媒体类型选择器示例</title>
<style>
/* 默认样式 */
body {
font-family: Arial, sans-serif;
background-color: #f0f0f0;
color: #333;
}
.container {
padding: 20px;
background-color: #fff;
margin: 20px;
border-radius: 5px;
}
/* 打印样式 */
@media print {
body {
background-color: #fff;
color: #000;
}
.container {
border: 1px solid #000;
margin: 0;
padding: 10px;
}
}
/* 屏幕样式 */
@media screen {
.container {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
}
/* 小屏幕设备样式 */
@media screen and (max-width: 600px) {
.container {
margin: 10px;
padding: 10px;
}
}
/* 大屏幕设备样式 */
@media screen and (min-width: 1200px) {
.container {
max-width: 1000px;
margin: 20px auto;
}
}
</style>
</head>
<body>
<div class="container">
<h1>媒体类型选择器示例</h1>
<p>这是一个展示媒体类型选择器用法的示例页面。根据不同的媒体类型和屏幕尺寸,页面样式会有所不同。</p>
<p>尝试调整浏览器窗口大小或打印预览,观察样式的变化。</p>
</div>
</body>
</html>
媒体类型的语法是 @media 媒体类型。声明不同的媒体类型可以允许我们在同一个元素上根据媒体不同设置不同的实现。
媒体类型总表
媒体类型 | 描述 |
---|---|
all | 所有设备 |
aural | 语音/音频合成器 |
braille | 盲人用点字法触觉回馈设备 |
embossed | 分页式盲人用点字法打印机 |
handheld | 小型手持设备 |
打印机 | |
projection | 幻灯片等 |
screen | 电脑显示器 |
tty | 使用固定密度字母栅格的媒体,如电传打字机和终端。 |
tv | 电视机等 |
属性选择器
除了上述的元素选择、class选择、id选择、组合选择符外,还有根据元素所具有的属性进行选择的属性选择器。不同的属性选择器对应着不同的字符串匹配规则。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>属性选择器示例</title>
<style>
/* 存在属性选择器 */
[title] {
color: blue;
font-weight: bold;
}
/* 属性等于特定值选择器 */
[type="text"] {
border: 2px solid green;
}
/* 属性包含特定值选择器 */
[class*="example"] {
background-color: yellow;
}
/* 属性以特定值开头选择器 */
[href^="https"] {
color: red;
text-decoration: underline;
}
/* 属性以特定值结尾选择器 */
[src$=".png"] {
border: 2px dashed purple;
}
/* 属性值为特定单词选择器 */
[class~="highlight"] {
font-style: italic;
}
/* 属性值为特定前缀选择器 */
[data-info|="prefix"] {
text-transform: uppercase;
}
</style>
</head>
<body>
<h1>属性选择器示例</h1>
<div title="存在属性选择器示例">这是一个存在属性选择器示例</div>
<input type="text" placeholder="属性等于特定值选择器示例">
<div class="example-class">这是一个属性包含特定值选择器示例</div>
<a href="https://www.example.com">这是一个属性以特定值开头选择器示例</a>
<img src="example.png" alt="属性以特定值结尾选择器示例">
<div class="highlight">这是一个属性值为特定单词选择器示例</div>
<div data-info="prefix-example">这是一个属性值为特定前缀选择器示例</div>
</body>
</html>
不同的语法对应的属性选择方式也不同;使用方式如下表。
属性选择器用法表
格式 | 控制 |
---|---|
[某属性] | 所有具有某属性的元素 |
[某属性 = value] | 所有具有某属性且值为value的元素 |
[某属性 ~= value] | 所有具有某属性且包含独立单词value的元素 |
[某属性 *= value] | 所有具有某属性且值字符串中可拆分出单词value的元素 |
[某属性 | = value] | 所有具有某属性且值以单词value的元素(完整且唯一的单词、或者用-和其他词分开) |
[某属性 ^= value] | 所有具有某属性且值的前几个字母为value的元素 |
[某属性 $= value] | 所有具有某属性且值的最后几个字母为value的元素 |
!important规则
有时候为了让一组网页的样式统一起来,我们可以设置一个最高级规则。如果要把某个/组样式的优先级提到最高,可以使用!important规则。 约定规范2
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>!important 规则示例</title>
<style>
/* 默认样式 */
.example {
color: blue;
font-size: 16px;
}
/* 使用 !important 覆盖默认样式 */
.important-example {
color: red !important;
font-size: 20px !important;
}
/* 内联样式 */
.inline-example {
color: green;
}
</style>
</head>
<body>
<h1>!important 规则示例</h1>
<div class="example">这是一个默认样式的示例</div>
<div class="example important-example">这是一个使用 !important 覆盖默认样式的示例</div>
<div class="example inline-example" style="color: purple !important;">这是一个内联样式使用 !important 覆盖其他样式的示例</div>
</body>
</html>
如果元素被含有!important规则的样式所影响,含有!important规则的属性值的优先级会被提到最高。如果更具体的实现和网页的整体风格可能发生冲突,用!important来进行规范不失为一种好选择。
CSS选择器优先级计算方式
当某一个元素被多个选择器所影响的时候,最终它是以什么样式出现在网页上,就要取决于影响它的各个选择器的优先级。在编程的时候,为了能够大体确认当前的样式是什么样子的,我们应当先自己计算一下各个选择器的优先级,并给它们排个序。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>选择器优先级示例</title>
<style>
#unique {
color: blue;
}
.example {
color: green;
}
div {
color: purple;
}
* {
color: black;
}
</style>
</head>
<body>
<div id="unique" class="example" style="color: red;">这是一个综合示例</div>
</body>
</html>
除!important规则外,选择器优先级分为四级,优先级从高到低分别是:
- 内联样式,即直接写在HTML元素中的style。
- ID选择器(#id)
- 类选择器(.class)、属性选择器([attribute])、伪类选择器(:class?)
- 元素选择器(element)、伪元素选择器(::element)
根据这四个优先级,可以为每一个选择器设置一个四元组(a,b,c,d)。其中
a
表示内联样式的数量。b
表示ID选择器的数量。c
表示类选择器、属性选择器和伪类选择器的数量。d
表示元素选择器和伪元素选择器的数量。
例如:
div
的优先级是(0, 0, 0, 1)
。.example
的优先级是(0, 0, 1, 0)
。#unique
的优先级是(0, 1, 0, 0)
。div#unique.example
的优先级是(0, 1, 1, 1)
。
对于影响一个元素的所有选择器,列出它们所有的四元组,从最高优先级(即a,第一个)开始比较,一直比较到最低优先级(即d,最后一个),就可以根据优先级为他们进行排序,然后从最低优先级开始确定样式,高级覆盖低级即可。
总结
根据不同的需要,有不同的方式来对元素进行控制。CSS在使用时要注意的大概就是记住选择器优先级、各种常用属性的用法,还有不要忘记查资料。在下一篇笔记当中,我们将看到一些常见网页实现的实例框架(其实是为了早点回家打黑猴鸽了一半);在这之后,就将进入到前端三大件最后一个:JavaScript的学习当中。
每一次工业革命都是一次先认同、再颠覆、最后重新认同的过程;使用电气的人颠覆了了使用蒸汽的人、使用计算机的人颠覆了使用电气的人、以后使用AI的人恐怕也会颠覆使用计算机的人。第一次是从人到机器的革命,自动化思想从此深入人心;第二次是能源革命,从此开始了人类寻找新能源、寻找高新材料的历史;第三次是思想革命,人类适应、习惯了黑箱,逐步创造出科技为基底的魔法;第四次是存续革命,人类需要寻找到驯化神明的方法,并逐渐解读祂,并想办法进化成曾经心目中的"神明",或"超级个体"。