本文为winter发布在极客时间的《重学前端》的学习笔记。
大家支持正版喔:time.geekbang.org/column/arti…
导语
我们到W3C上搜索css相关可以得到98份CSS相关的标准,去掉Working Draft状态的标准,可以得到22份候选标准和6份推荐标准。
将这些规则整合之后,可以进行抽象,CSS的顶层样式表有两种规则:
- at-rule,也就是at 规则
- qualified rule,也就是普通规则
at 规则
at-rule由一个 @ 关键字和后续的一个区块组成,如果没有区块,则以分号结束。
@charset
@charset用于提示CSS文件使用的字符编码方式,它如果被使用,必须出现在最前面。这个规则只在给出语法解析阶段前使用,并不影响页面上的展示效果。
@charset "utf-8";
@charset "iso-8859-15";
在样式表中有多种方法去声明字符编码,浏览器会按照以下顺序尝试下边的方法(一旦找到就停止并得出结果):
- 文件的开头的Unicode byte-order字符值。
- 由Content-Type:HTTP header 中的 charset 属性给出的值或用于提供样式表的协议中的等效值。
- CSS @规则@charset。使用参考文档定义的字符编码:元素的 charset 属性。该方法在 HTML5 标准中已废除,无法使用。
- 假设文档是 UTF-8。
@import
@import用于引入一个CSS文件,在样式表中的所有其他有效规则和样式规则之前(忽略@charset)。除了该文件的@charset信息,其他内容全部引入。
// 格式
@import [ <url> | <string> ]
[ supports( [ <supports-condition> | <declaration> ] ) ]?
<media-query-list>? ;
// 示例
@import "mystyle.css";
@import url("mystyle.css");
@import url("fallback-layout.css") supports(not (display: flex));
@import url("narrow.css") handheld and (max-width: 400px);
思考:link 与 @import 的区别?
- link是html标签,能被dom控制;@import是css方法,不能被dom控制
- link能通过设置
rel来引入其他资源,@import仅能引入css - 浏览器对link支持早于@import,@import可能会有兼容性问题
注:在chrome-86版本使用link和@import加载文件,没有出现@import阻塞css现象,两者效果相同,没出现FOUC(即Flash of Unstyled Content,亦浏览器样式闪烁,为css阻塞浏览器渲染导致)。IE中可能会不一样,但是现在没有IE,权做个记录。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title></title>
<style>
@import url(./test.css);
@import url(./test-a.css);
@import url(./test-b.css);
</style>
</head>
@media
@media就是大名鼎鼎的media query使用的规则了,它能够对设备的类型进行一些判断(具体规则可以参考这里)。在media的区块内,是普通规则列表。
@media screen and (min-width: 35em),
print and (min-width: 40em) {
#section_navigation { float: left; width: 10em; }
}
@page
@page用于分页媒体访问页面时(打印文档)的表现设置,页面是一种特殊的盒模型结构,除了页面本身,还可以设置它周围的盒。
你不能用@page规则来修改所有的CSS属性,而是只能修改margin,orphans,widow 和 page breaks of the document。对其他属性的修改是无效的。 --MDN,@page
@page {
size: 8.5in 11in;
margin: 10%;
@top-left {
content: "Hamlet";
}
@top-right {
content: "Page " counter(page);
}
}
@counter-style
@counter-style产生一种数据,用于定义列表项的表现。也可以参考MDN。
@counter-style triangle {
system: cyclic;
symbols: ‣;
suffix: " ";
}
.items {
list-style: triangle;
}
items类的列表效果如下:
‣ One
‣ Two
‣ Three
@key-frames
@key-frames产生一种数据,用于定义动画关键帧。配合animation-name使用,定义一个物体从开始到结束(0%/from 和100%/to)的动画。 也可以参考MDN。
@keyframes diagonal-slide {
from {
left: 0;
top: 0;
}
to {
left: 100px;
top: 100px;
}
}
@font-face
@font-face用于定义一种字体,icon font技术就是利用这个特性来实现的。
@font-face {
font-family: Gentium;
src: url(http://example.com/fonts/Gentium.woff);
}
p { font-family: Gentium, serif; }
@support
@support可以指定依赖于浏览器中的一个或多个特定的CSS功能的支持声明。这叫特性查询。
@supports at-rule 由一组样式声明和一条支持条件构成。支持条件由一条或多条使用 逻辑与(and)、逻辑或(or)、逻辑非(not)结合的名称-值对(name-value pair)组成。可以使用圆括号调整操作符的优先级。 -- MDN,@support
@supports (transform-origin: 5% 5%) {
...
}
如果transform-origin: 5% 5%是有效的值,则块内的样式则生效。
@namespace
@namespace用于跟XML命名空间配合的一个规则,表示内部的CSS选择器全都带上特定命名空间。
任何 @namespace 规则都必须在所有的 @charset 和 @import 规则之后, 并且在样式表中,位于其他任何 style declarations 之前。--MDN,@namespace
@namespace 可以用来定义默认命名空间。当定义过默认命名空间后, 所有的通配选择器和类型选择器(但不包括属性选择器,详情看下面的note)都只应用在这个命名空间的元素中。
@namespace 规则也可以用于定义命名空间前缀。当一个通配、类型、属性选择器前面有命名空间前缀修饰时,这个选择器将只匹配那些命名空间与 元素名或属性匹配 的元素。
@namespace url(http://www.w3.org/1999/xhtml);
@namespace svg url(http://www.w3.org/2000/svg);
/* 匹配所有的XHTML <a> 元素, 因为 XHTML 是默认无前缀命名空间 */
a {}
/* 匹配所有的 SVG <a> 元素 */
svg|a {}
/* 匹配 XHTML 和 SVG <a> 元素 */
*|a {}
@viewport
@viewport用于设置视口的一些特性.
该特性已经从 Web 标准中删除,虽然一些浏览器目前仍然支持它,但也许会在未来的某个时间停止支持,请尽量不要使用该特性。
目前多数时候被HTML的meta代替,可以参考之前的文章。
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
其它
这里还有一些不太推荐的at规则:
- @color-profile 是 SVG1.0 引入的CSS特性,但是实现状况不怎么好。
- @document 还没讨论清楚,被推迟到了CSS4中。
- @font-feature-values 。
普通规则
普通规则主要是由选择器和声明区块构成。声明区块又由属性和值构成。
选择器
声明:属性和值
值可以分为函数和CSS属性值两种,这里重点介绍一些函数。
CSS支持一批特定的计算型函数:
- calc() 基本的表达式计算,它支持加减乘除四则运算
- max() 表示取两数中较大的一个
- min() 表示取两数之中较小的一个
- clamp() 是给一个值限定一个范围,超出范围外则使用范围的最大或者最小值
- toggle() 在规则选中多于一个元素时生效,它会在几个值之间来回切换
- attr() 返回选择元素的属性值
- var() 通过
--xx的格式来设置一个自定义属性,在值中通过var()来使用该自定义属性 - rgb() 使用红(R)、绿(G)、蓝(B)三个颜色的叠加来生成各式各样的颜色
- rgba() 使用红(R)、绿(G)、蓝(B)、透明度(A)的叠加来生成各式各样的颜色
- linear-gradient() 创建一个线性渐变的图像
- radial-gradient() 用径向渐变创建图像
- repeating-linear-gradient() 用重复的线性渐变创建图像
- repeating-radial-gradient() 用重复的径向渐变创建图像
- ...
当然,上面的函数是一些常用的,更多的函数可以在这里查询。