本篇文章围绕了 CSS 的核心知识点和项目中常见的需求来展开。虽然行文偏长,但较基础,适合初级中级前端阅读,阅读的时候请适当跳过已经掌握的部分。
这篇文章断断续续写了比较久,也参考了许多优秀的文章,但或许文章里还是存在不好或不对的地方,请多多指教,可以评论里直接提出来哈。
小tip:后续内容更精彩哦。
核心概念和知识点
语法
CSS 的核心功能是将 CSS 属性设定为特定的值。一个属性与值的键值对被称为声明(declaration)。
color: red;
复制代码
而如果将一个或者多个声明用 {}
包裹起来后,那就组成了一个声明块(declaration block)。
{
color: red;
text-align: center;
}
复制代码
声明块如果需要作用到对应的 HTML 元素,那还需要加上选择器。选择器和声明块组成了CSS 规则集(CSS ruleset),常简称为 CSS 规则。
span {
color: red;
text-align: center;
}
复制代码
规则集中最后一条声明可以省略分号,但是并不建议这么做,因为容易出错。
CSS 中的注释:
/* 单行注释 */
/*
多行
注释
*/
复制代码
在 CSS 文件中,除了注释、CSS 规则集以及 @规则 外,定义的一些别的东西都将被浏览器忽略。
@规则
CSS 规则是样式表的主体,通常样式表会包括大量的规则列表。但有时候也需要在样式表中包括其他的一些信息,比如字符集,导入其它的外部样式表,字体等,这些需要专门的语句表示。
而 @规则 就是这样的语句。CSS 里包含了以下 @规则:
- @namespace 告诉 CSS 引擎必须考虑XML命名空间。
- @media, 如果满足媒体查询的条件则条件规则组里的规则生效。
- @page, 描述打印文档时布局的变化.
- @font-face, 描述将下载的外部的字体。
- @keyframes, 描述 CSS 动画的关键帧。
- @document, 如果文档样式表满足给定条件则条件规则组里的规则生效。 (推延至 CSS Level 4 规范)
除了以上这几个之外,下面还将对几个比较生涩的 @规则 进行介绍。
@charset
@charset 用于定义样式表使用的字符集。它必须是样式表中的第一个元素。如果有多个 @charset
被声明,只有第一个会被使用,而且不能在HTML元素或HTML页面的 <style>
元素内使用。
注意:值必须是双引号包裹,且和
@charset "UTF-8";
复制代码
平时写样式文件都没写 @charset 规则,那这个 CSS 文件到底是用的什么字符编码的呢?
某个样式表文件到底用的是什么字符编码,浏览器有一套识别顺序(优先级由高到低):
-
文件开头的 Byte order mark 字符值,不过一般编辑器并不能看到文件头里的 BOM 值;
-
HTTP 响应头里的
content-type
字段包含的charset
所指定的值,比如:Content-Type: text/css; charset=utf-8 复制代码
-
CSS 文件头里定义的 @charset 规则里指定的字符编码;
-
<link>
标签里的 charset 属性,该条已在 HTML5 中废除; -
默认是
UTF-8
。
@import
@import 用于告诉 CSS 引擎引入一个外部样式表。
link 和 @import 都能导入一个样式文件,它们有什么区别嘛?
- link 是 HTML 标签,除了能导入 CSS 外,还能导入别的资源,比如图片、脚本和字体等;而 @import 是 CSS 的语法,只能用来导入 CSS;
- link 导入的样式会在页面加载时同时加载,@import 导入的样式需等页面加载完成后再加载;
- link 没有兼容性问题,@import 不兼容 ie5 以下;
- link 可以通过 JS 操作 DOM 动态引入样式表改变样式,而@import不可以。
@supports
@supports 用于查询特定的 CSS 是否生效,可以结合 not、and 和 or 操作符进行后续的操作。
/* 如果支持自定义属性,则把 body 颜色设置为变量 varName 指定的颜色 */
@supports (--foo: green) {
body {
color: var(--varName);
}
}
复制代码
层叠性
层叠样式表,这里的层叠怎么理解呢?其实它是 CSS 中的核心特性之一,用于合并来自多个源的属性值的算法。比如说针对某个 HTML 标签,有许多的 CSS 声明都能作用到的时候,那最后谁应该起作用呢?层叠性说的大概就是这个。
针对不同源的样式,将按照如下的顺序进行层叠,越往下优先级越高:
- 用户代理样式表中的声明(例如,浏览器的默认样式,在没有设置其他样式时使用)。
用户样式表中的常规声明(由用户设置的自定义样式。由于 Chrome 在很早的时候就放弃了用户样式表的功能,所以这里将不再考虑它的排序。)。- 作者样式表中的常规声明(这些是我们 Web 开发人员设置的样式)。
- 作者样式表中的 !important 声明。
用户样式表中的 !important 声明S。
理解层叠性的时候需要结合 CSS 选择器的优先级以及继承性来理解。比如针对同一个选择器,定义在后面的声明会覆盖前面的;作者定义的样式会比默认继承的样式优先级更高。
选择器
CSS 选择器无疑是其核心之一,对于基础选择器以及一些常用伪类必须掌握。下面列出了常用的选择器。 想要获取更多选择器的用法可以看 MDN CSS Selectors。
基础选择器
- 标签选择器:
h1
- 类选择器:
.checked
- ID 选择器:
#picker
- 通配选择器:
*
属性选择器
[attr]
:指定属性的元素;[attr=val]
:属性等于指定值的元素;[attr*=val]
:属性包含指定值的元素;[attr^=val]
:属性以指定值开头的元素;[attr$=val]
:属性以指定值结尾的元素;[attr~=val]
:属性包含指定值(完整单词)的元素(不推荐使用);[attr|=val]
:属性以指定值(完整单词)开头的元素(不推荐使用);
组合选择器
- 相邻兄弟选择器:
A + B
- 普通兄弟选择器:
A ~ B
- 子选择器:
A > B
- 后代选择器:
A B
伪类
条件伪类
:lang()
:基于元素语言来匹配页面元素;:dir()
:匹配特定文字书写方向的元素;:has()
:匹配包含指定元素的元素;:is()
:匹配指定选择器列表里的元素;:not()
:用来匹配不符合一组选择器的元素;
行为伪类
:active
:鼠标激活的元素;:hover
: 鼠标悬浮的元素;::selection
:鼠标选中的元素;
状态伪类
:target
:当前锚点的元素;:link
:未访问的链接元素;:visited
:已访问的链接元素;:focus
:输入聚焦的表单元素;:required
:输入必填的表单元素;:valid
:输入合法的表单元素;:invalid
:输入非法的表单元素;:in-range
:输入范围以内的表单元素;:out-of-range
:输入范围以外的表单元素;:checked
:选项选中的表单元素;:optional
:选项可选的表单元素;:enabled
:事件启用的表单元素;:disabled
:事件禁用的表单元素;:read-only
:只读的表单元素;:read-write
:可读可写的表单元素;:blank
:输入为空的表单元素;:current()
:浏览中的元素;:past()
:已浏览的元素;:future()
:未浏览的元素;
结构伪类
:root
:文档的根元素;:empty
:无子元素的元素;:first-letter
:元素的首字母;:first-line
:元素的首行;:nth-child(n)
:元素中指定顺序索引的元素;:nth-last-child(n)
:元素中指定逆序索引的元素;;:first-child
:元素中为首的元素;:last-child
:元素中为尾的元素;:only-child
:父元素仅有该元素的元素;:nth-of-type(n)
:标签中指定顺序索引的标签;:nth-last-of-type(n)
:标签中指定逆序索引的标签;:first-of-type
:标签中为首的标签;:last-of-type
:标签中为尾标签;:only-of-type
:父元素仅有该标签的标签;
伪元素
::before
:在元素前插入内容;::after
:在元素后插入内容;
优先级
优先级就是分配给指定的 CSS 声明的一个权重,它由匹配的选择器中的每一种选择器类型的数值决定。为了记忆,可以把权重分成如下几个等级,数值越大的权重越高:
- 10000:!important;
- 01000:内联样式;
- 00100:ID 选择器;
- 00010:类选择器、伪类选择器、属性选择器;
- 00001:元素选择器、伪元素选择器;
- 00000:通配选择器、后代选择器、兄弟选择器;
可以看到内联样式(通过元素中 style 属性定义的样式)的优先级大于任何选择器;而给属性值加上 !important
又可以把优先级提至最高,就是因为它的优先级最高,所以需要谨慎使用它,以下有些使用注意事项:
- 一定要优先考虑使用样式规则的优先级来解决问题而不是 !important;
- 只有在需要覆盖全站或外部 CSS 的特定页面中使用 !important;
- 永远不要在你的插件中使用 !important;
- 永远不要在全站范围的 CSS 代码中使用 !important;
继承性
在 CSS 中有一个很重要的特性就是子元素会继承父元素对应属性计算后的值。比如页面根元素 html 的文本颜色默认是黑色的,页面中的所有其他元素都将继承这个颜色,当申明了如下样式后,H1 文本将变成橙色。
body {
color: orange;
}
h1 {
color: inherit;
}
复制代码
设想一下,如果 CSS 中不存在继承性,那么我们就需要为不同文本的标签都设置一下 color,这样一来的后果就是 CSS 的文件大小就会无限增大。
CSS 属性很多,但并不是所有的属性默认都是能继承父元素对应属性的,那哪些属性存在默认继承的行为呢&#x