跳至主要內容

css、css选择器

xmut-lby2024年3月8日大约 14 分钟

css、css选择器

加点颜色?

我相信很多人开始动手之后就会想好好装饰一下自己的页面,比如加个彩色,加粗之类的。

于是百度之后你可能很容易能得到这些代码:

    <h1><font color="red">Hello World!</font></h1>
    <p>Nice to <b>meet</b> you</p>
    <p>How <font size="40px">are</font> you?</p>

并且非常欣慰地看到他们在浏览器里生效。

遗憾的是,这些用法都是不对(准确说,不再推荐)的。

早期的html确实提供类似的写法,但经过几个版本的迭代、规范、进化之后,有些写法已经被废弃。

浏览器保持对早期代码的支持是情分,不支持是本分。

你知道吗?

为什么现在的html叫html5,你知道吗?

那么正确的做法是什么呢?我们先看看排版工具是怎么做的。

内容和样式

回忆一下你是如何操作word这类排版工具的。

  1. 你输入文字(内容)。
  2. 你选中某段文字。
  3. 你点击工具栏上的颜色,将颜色改为红色(样式)。
在word里改变样式
在word里改变样式

在这个操作过程中,你先输入文字(内容),再通过所见即所得的工具为你输入的内容添加排版的样式。

这两者可以认为是独立的两个部分。实际上我们经常遇到给你一份文字稿让你为其排版的要求。

这种设计的优点非常明显,写稿子的就负责写稿子,排版的就负责排版,这样工作就可以合理的被分配给不同的人做。也有利于把人培养成某方面的专精。

计算机领域一般管这种处理方式叫:解耦合。

网页设计也遵循这一原则。HTML负责给出页面的内容——有几个块,分别是什么,哪些在前哪些在后。

而由CSS(Cascade Style Sheet,层叠样式表)来告诉浏览器,这些块和内容应该用何种方式来呈现

引入CSS

在HTML里申明

如果你要让<h1>显示为红色,那么你可以为<header>这个块增加新的一段代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        h1{
            color: red;
        }
    </style>
    <title>Document</title>
</head>
<body>
    <h1>Hello World!</h1>
    <h2>Nice to meet you!</h2>
    <p>How are you!</p>
</body>
</html>





 
 
 
 
 








此时h1块就会变成红色。

注意这个配置对页面里的所有<h1>标记都会生效,试试。

试一下!

把第二行的<h2>变成绿色试试。

这里稍微注意一下css的语法。每个css规则集包括选择器和申明两个部分,选择器是其中最开始的h1部分。说明下面的规则的适用范围。 接下来用括号括起来的范围是对应的风格规则,每条规则都包括两部分,用冒号分隔。冒号前面是对应的属性,冒号后面是属性的取值。规则需要以分号结束。

上面这个css覆盖了页面里的所有<h1>标记。有两条规则,分别是color:red;font-size:14px;

可以发现发现css的语法和C语言有很多相似之处——包括注释。css也可以用/* */进行注释。

以独立文件引入

另一种更常用的方法是,把css代码写在独立的文件里,然后以资源的形式引入html里。

新建style.css文件,内容为:

h1{
    color: red;
}

然后HTML里这样写:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Document</title>
</head>
<body>
    <h1>Hello World!</h1>
    <h2>Nice to meet you!</h2>
    <p>How are you!</p>
</body>
</html>





 








就是把原来的<style>块改为<link>引入style.css文件。css规则也可以生效。

要怎么办?

假如我们统一将css文件放入根目录下的style目录。这里应该如何处理?

inline css

还有一种比较少见的设置方式,就是直接在标记上写:

<h1 style="color:red;">Hello World!</h1>

这种写法只会在当前标记上生效,而不会影响页面内的其他标记。

而且这种写法有最高的优先级,会覆盖其他规则的实现。

你可能会觉得这简直太棒了,但实际上这种写法非常不推荐,因为其违背了将HTML和CSS分离的初衷:分离内容和样式,降低整体耦合度。

因此这种方式一般只在JavaScript对页面样式进行动态调整时使用。

color和background-color

你已经看过如何改变元素的字体颜色了,这个颜色有个术语叫前景色。可以通过color规则来设置。

有前景色就有背景色,他可以通过background-color来设置,设置属性和color类似。

试试:

h2{
    background-color: red;
}

除此之外,还可以通过backgound-imagebackgound-repeat来为标记设置背景图片。不过我要提醒一下,初学者往往喜欢把背景塞满花里胡哨的图片。 但良好的页面设计在使用背景图片时往往非常克制,防止喧宾夺主。所以说,除了技术之外,审美也是本课程需要培养的能力。

颜色的表达

你应该注意到可以通过redgreen这种名词来告诉浏览器你要使用的颜色。但要如何获得你想要的颜色(例如,五彩斑斓的黑)呢?

颜色名

首先,可以速查颜色名称表:颜色查找表open in new window

实际上当你在vscode里输入color:时,vscode也会给你提示能用的所有颜色。

RGB颜色

如果你需要更精细颜色控制,你需要对计算机如何表示颜色有一些了解。

你小学美术老师应该告诉过你,色彩由红黄蓝三原色组成。其他颜色都可以通过这三种颜色来组合,比如橙色可以由红色和黄色混合组成。

计算机系统内对颜色的表示也是类似的,用红绿蓝也就是RGB三种颜色来混合出所有的颜色(这种说法不准确,还有其他色彩空间,但RGB是应用最广泛的)。

下面这张图的色光三原色即是计算机内的RGB表示法。

从图上你可以看出RGB表示法和你学过的色彩三原色还是不同的,最大的不同就是当你把三种颜色混合在一起时,RGB色系呈现出白色,而另外两种呈现出黑色。

这是因为这两种系统呈现色彩的方式是不同的。

我们都知道你看到的白光实际上是各种颜色光的组合。颜料呈现某种颜色的方式是将除了此种颜色之外的颜色都吸收来实现的,通过漫反射看到的颜色都是这个原理。换句话说,叶子之所以呈现绿色,并不是因为他对绿色光的吸收效果最好,反而是因为叶子把绿色以外的光都吸收了,所以你看上去是绿色的。这也很好解释为什么颜料越混合,颜色越暗。

而计算机表示颜色的方式是假定颜色通过发光实现的。早期的CRT显示器,通过电子束击中特定的发光材料来发出颜色。电子束越强,这种颜色的光强就越强。所以当所有光混合在一起之后,他应该呈现白色。

换句话说,颜料的颜色是减法,RGB色彩系统则是加法。

了解了这些基本原理,我们就可以通过调整RGB三种颜色的分量来实现所有颜色了,在这个系统里,三种分量的取值范围从0~255,即占据一个字节8位的空间。 三种颜色共占据3个字节24位空间,这里的24有时候会称为位深。 有时候还会加上一个Alpha通道,构成4字节32位。我们把这种颜色系统称为真彩色。真彩色有 2242^{24} 共16万种颜色。

既然是真的彩色,那就有假的彩色了?

确实有,了解一下16位增强色。但这已是过去式了。

不过实际上假彩色(伪彩色)是可视化里的一个专门术语,有兴趣的可以了解一下。

RGB表示法有两种表示方式,比较旧式的表示方式是用#RRGGBB这样的形式,每两位表示一个16进制的颜色分量值,以RGB的顺序排列。

例如:#E44D26,表示red=0xE4=228green=0x4D=77blue=0x26=38。你会得到这个颜色。

现在比较建议的表示法是使用rgb函数式表示法,直接用rgb(228,77,38)来表示。 旧式的表示方式需要的字符较少,比较适合过去对流量比较敏感的环境,但显然其不够直观。 而现在对流量不(那么)敏感的情况下,越来越多的页面使用后一种方式,这种方式比较直观,对开发人员比较友好。

类选择器和id选择器

类选择器

你应该发现h1这种选择器最大的问题,就是范围太广了,整个页面的所有h1都会生效。多数情况下我们会需要更精细一些的控制方式。

这时就需要用类选择器class:

<h1 class="red">class red</h1>
<h1 class="green">class green</h1>
<h1>空白</h1>
h1{
    background-color:cornflowerblue;
}
.red{
    color: red;
}
.green{
    color: green;
}

当选择器以.开始时,表示这是一个类选择器。标记里增加class属性用来给出该标记哪个类。

这样.red的规则只会在第一个h1生效,.green的规则只会在第二个h1生效。而h1的规则所有三个h1都可以生效。

标记的类属性可以有多个,之间用空格隔开:

<h1 class="a b c">测试</h1> <!-- a,b,c三个类都会生效 -->

id选择器

对于id属性,也可以用id选择器来选择,以#开始即可。

<h1 id="p1">id选择器</h1>
#p1{
    color: blue;
}

更复杂的选择器

上面的选择器可以组合起来使用,以实现更为精细的控制。

例如:

  • h1.red:属于red类的h1标记。
  • h1#p1:id为#p1h1标记。

实际上css的选择器远比上面所说的复杂得多。大家可以延伸阅读以下的内容:

元素选择器open in new window

选择器分组open in new window

类选择器详解open in new window

ID 选择器详解open in new window

属性选择器详解open in new window

后代选择器open in new window

子元素选择器open in new window

相邻兄弟选择器open in new window

选择器的优先级

善于思考的同学一定已经想到了,这么多选择器,很容易会出现冲突。例如有这么两条规则:

h1{
    color: red;
}

.blue {
    color: blue;
}

那么对于属于blue类的h1标记,哪条规则会生效呢?

<h1 class="blue">什么颜色?</h1> <!-- 会是什么颜色? -->

当前阶段你可以用一个比较粗略的规则来判断,当然最好的方式还是试一下

css优先级规则

id选择器 > 类选择器 > 标记选择器

这个规则是有内在逻辑的,即计算机领域解决这类问题常用的思路:就近原则

回想一下C语言里的全局变量和局部变量,如果在函数体内部存在与全局变量重名的局部变量,那么局部变量会生效,全局变量会被遮蔽(即你无法访问)。

这一原则的逻辑非常清楚:没有理由要求编写函数的人必须掌握所有全局变量的命名,如果他不是刻意引用某个全局变量,那么他不需要去了解有哪些全局变量。

显然这一原则允许局部编写者只掌握自己范围内的知识,有利于大型工程的展开。

对于css选择器,也是遵循这一原则的:越是具体的规则,优先级越高。这里的逻辑也是相似的:规则越具体,说明他越贴近相关标记设计者的想法。

举例来说,如果类选择器和标记选择器冲突了。显然类是更具体的,因为一旦给了标记某个类的属性,就说明我们明确知道这个标记是特别的,需要展示出特殊的形态。

同理,id选择器就要比类选择器更具体,因为id是全页面唯一的,而类可以被赋予多个标记。

同样根据这一原则,组合选择器的优先级要高于单一选择器——显然组合选择器更为具体,也就是说:h1.p1要比.p1h1更优先。

就近原则

随着学习的深入,你会发现就近原则是广泛运用在计算机领域里的一条规则。

调试你的css

还记得怎么调试页面吗?css也是一样的。

css调试器 - 没错,就是当前页面的代码框
css调试器 - 没错,就是当前页面的代码框

选中某个对应的标记,可以在调试窗口里的样式标签里可以看到对应的css规则和css规则是如何推导的。

  1. 筛选器,可以让你快速筛选出你希望看到的规则。
  2. 对应的css规则选择器,从这里可以看出来对于实际部署的项目,css的规则可能是非常复杂的。
  3. 这条css在对应的源文件,点击后可以到达对应的条目
  4. 鼠标移动到每一条css上之后,会出现复选框,通过check/uncheck这个复选框,可以允许或者不允许这条css,有助于你观察和调试规则。
  5. 规则的优先次序是从下往上优先级依次上升,因此下方的规则可能被上方的规则覆盖。你会注意到最下面的color规则有一条横线,表明这条规则被覆盖了(就是被上面的一条覆盖了)。

试试

这个窗口里还有一些其他的用法。例如你可以试试直接修改某个规则的值。看看会有什么变化。

css 变量

大家一定注意到了这里使用了很多var,例如color: var(--text-color);,这里的var括号包裹的--text-color实际上是一个css变量,你可以在下方看到:

:root{
    /* ... */
    --text-color: #2c3e50;
    /* ... */
}

这里就定义了一个--text-color变量。引用时需要通过color:var(变量名)的方式来引用,这样作法的优点也是很明显的,假如要修改对应的颜色,只需要修改一开始定义的位置就行了。

对于工业上的实际项目,var是应用非常广泛编写方式。虽然我们作业里应用不多,但你一定要懂。

伪类选择器

某些标记会因为用户的操作处于不同的状态,例如对于一个超链接a标签,他可能包括2种不同的状态:

  1. 链接未被访问,默认情况下颜色是蓝色,并且有下划线。
  2. 链接已被访问过,默认情况下是紫色,并有下划线。
链接
链接状态链接未被访问过链接已被访问过
伪类选择器a:linka:visited

我们可以通过a:link来选择未访问过的超链接,用a:visited来选择访问过的链接。

除此之外,另一个非常常用的伪类是:hover,这个伪类可以用来所有标记中,当鼠标悬停在该标记上时,会触发该选择器。

:hover伪类
<div>
    <h1>鼠标悬停试试</h1>
</div>
h1:hover{
    background-color: brown;
    color: white;
}

更为全面的伪类可以看这里open in new window这里open in new window