CSS 揭秘(CSS Secrets)

2017.11.19 日 22:44


[希]Lea Verou 著
CSS魔法 译
人民邮电出版社出版发行
2016年 4 月北京第 1 次印刷
8章266页 47 篇攻略,并根据主题的不同收入 7 章之中

## 本书是怎样炼成的
通俗地说,这本书在技术上是自产自销的。它完全用 HTML5 写成,并 用 到 了 一 些 由 O’Reilly 的 HTMLBook 标 准http://oreillymedia.github.io/HTMLBook)定义的 data- 属性。这意味着你在这本书里看到的每样东西(包括布局、图片、颜色等)都是由 CSS 渲染出的 HTML。大量图片是由SVG 生成的,或者是由 SCSS 函数生成的 SVG data URI。书中为数不多的数学公式是在LaTeX 中写成的,然后转换成 MathML。有一点可能会让你意想不到,书中的所有页码、章节号、攻略编号都是由纯粹的 CSS 计数器生成的。

目前 O’Reilly 出版的绝大多数图书都是以这种方式制作出来的。O’Reilly 专门为这件事搭建了一个叫作 Atlas(http://atlas.oreilly.com)的系统。Atlas 最美好的地方在于,它并不只是供 O’Reilly 官方专用的,对公众
也开放。
## 这本书适合谁
正在由中级向高级进阶的 CSS 开发者
## 本书的格式和约定
有很多优秀的网站提供了及时有效的浏览器兼容性信息。推荐如下:
1. Can I Use…?(http://caniuse.com)
1. WebPlatform.org(http://webplatform.org)
1. Mozilla Developer Network(http://developer.mozilla.org)
1. 维基百科上的“浏览器排版引擎对比(CSS 兼容性) ”词条(http://en.wikipedia.org/wiki/Comparison_of_layout_engines_(Cascading_Style_Sheets))

举例来说,当我们像上面那样指定一个渐变色作为背景的时候,应该在前面添加一行实色背景的声明。添加实色的一个好方法是取渐变色的平均色值

不过,有些时候不太可能只通过样式的层叠就提供完善的回退样式。这时别忘了你还有一招,可以使用 Modernizr(http://modernizr.com/)这样的工具来给根元素()添加一些辅助类,比如 textshadow 或 no-textshadow 等。这样你就可以针对支持或不支持某些特性的浏览器来分别编写样式了,就像这样:

h1 { color: gray; }

.textshadow h1 {
color: transparent;
text-shadow: 0 0 .3em gray;
}

如果你想尝试使用的某个 CSS 特性非常新,还可以试试用 @supports规则来实现回退,可以将其视作浏览器“原生”的 Modernizr。比如说,上面的代码还可以这样写:
h1 { color: gray; }

@supports (text-shadow: 0 0 .3em gray) {
h1 {
color: transparent;
text-shadow: 0 0 .3em gray;
}
}
但在眼下,还必须慎用 @supports。在上面的例子中,我们想要的文本投影效果只会在那些支持 text-shadow 且同时支持 @supports 规则的浏览器中生效。这个范围明显比我们所期望的要窄。

最后,同样值得一提的是,即使你不打算使用 Modernizr,也可以自己写一小段 JavaScript 代码来实现相同的功能——做一些特性检测然后给根元素加一些辅助类。如果要检测某个样式属性是否被支持,核心思路就是在任一元素的 element.style 对象上检查该属性是否存在:

function testProperty(property) {
var root = document.documentElement;
if (property in root.style) {
root.classList.add(property.toLowerCase());
return true;
}
root.classList.add(‘no-‘ + property.toLowerCase());
return false;
}

如果我们想要检测某个具体的属性值是否支持,那就需要把它赋给对应的属性,然后再检查浏览器是不是还保存着这个值。很显然,这个过程会改变元素的样式,因此我们需要一个隐藏元素:

function testValue(id, value, property) {
var dummy = document.createElement(‘p’);
dummy.style[property] = value;

if (dummy.style[property]) {
root.classList.add(id);
return true;
}

root.classList.add(‘no-‘ + id);
return false;
}

如果要检测选择符和 @ 规则的支持情况,则会稍稍复杂一些。不过原理也很简单,在解析 CSS 代码时,浏览器总会丢弃它自己无法识别的部分,因此我们可以动态地应用样式并检查它是否生效,以此来判断浏览器是否可以识别某个特性。当然,我们也要清楚地认识到,浏览器可以解析某个 CSS特性并不代表它已经实现(或正确实现)了这个特性

## 第1 章 引言
### 1.1 Web 标准:是敌还是友
#### 1 标准的制定过程
#### 2 CSS3、CSS4 以及其他传说
因此,我们决定跨出一步,将 CSS 打散到多个不同的规范(模块)中,每个模块都可以独立更新版本。这其中,那些延续 CSS 2.1 已有特性的模块会升级到 3 这个版本号。比如以下模块:
1. CSS 语法(http://w3.org/TR/css-syntax-3)
1. CSS 层叠与继承(http://w3.org/TR/css-cascade-3)
1. CSS 颜色(http://w3.org/TR/css3-color)
1. 选择符(http://w3.org/TR/selectors)
1. CSS 背景与边框(http://w3.org/TR/css3-background)
1. CSS 值与单位(http://w3.org/TR/css-values-3)
1. CSS 文本排版(http://w3.org/TR/css-text-3)
1. CSS 文本装饰效果(http://w3.org/TR/css-text-decor-3)
1. CSS 字体(http://w3.org/TR/css3-fonts)
1. CSS 基本 UI 特性(http://w3.org/TR/css3-ui)

此外,如果某个模块是前所未有的新概念,那它的版本号将从 1 开始。比如下面这些:
1. CSS 变形(http://w3.org/TR/css-transforms-1)
1. 图像混合效果(http://w3.org/TR/compositing-1)
1. 滤镜效果(http://w3.org/TR/filter-effects-1)
1. CSS 遮罩(http://w3.org/TR/css-masking-1)
1. CSS 伸缩盒布局(http://w3.org/TR/css-flexbox-1)
1. CSS 网格布局(http://w3.org/TR/css-grid-1)

尽管“CSS3”这个名词非常流行,但它实际上并没有在任何规范中定义过。这一点跟 CSS 2.1 或更早的 CSS 1 不一样。真正的情况是,绝大多数编辑在提到这个词时,指的是一个非正式的集合,它包括 CSS 规范第三版(Level 3)再加上一些版本号还是 1 的新规范。
#### 3 冰与火之歌:浏览器前缀
显然,把每个声明都重复五遍是相当枯燥的,而且很难维护。因此出现
某个工具来把这项工作自动化只是个时间问题。

1. 像 CSS3, Please!(http://css3please.com)和 pleeease(http://pleee-ase.io/playground.html)这样的网站允许你把无前缀的 CSS 代码粘贴进去,它们会自动帮你把必要的前缀都加好。这类网站是“前缀危
机”所催生出的第一批工具,很快就过气了,因为跟其他方案相比,它们的使用成本太高了。
1. Autoprefixer(https://github.com/ai/autoprefixer)采用 Can I Use… (http://caniuse.com)的数据库来判断哪些前缀是需要添加的;此外,它是在本地完成编译的,类似预处理器。
1. 我自己开发的 -prefix-free(http://leaverou.github.io/prefixfree)会在浏览器中进行特性检测,来决定哪些前缀是需要的。它的好处在于几乎不需要更新,因为其所有信息都是用一份属性清单在真实的浏览器环境中跑出来的结果。
1. 类 似 Stylus(http://stylus-lang.com/) 、LESS(http://lesscss.org) 或Sass(http://sass-lang.com)的预处理器并不自带任何加前缀的方法,但很多人开发过一些能为常用属性加前缀的 mixin;社区中也有一些库提供了这类 mixin。

最近,浏览器厂商已经很少以前缀的方式来实验性地实现新特性了。取而代之的是,这些实验性特性需要通过配置开关来启用
### 1.2 CSS 编码技巧
#### 1 尽量减少代码重复
在实践中,代码可维护性的最大要素是尽量减少改动时要编辑的地方
当某些值相互依赖时,应该把它们的相互关系用代码表达出来font-size: 20px; line-height: 1.5;
1. 代码易维护 vs. 代码量少 不可兼得
2. currentColor CSS 中有史以来的第一个变量
> 可能有人会争论说 em 单位才是 CSS 中的第一个变量,因为它引用了font-size 的值。其实大多数百分比数值也扮演了类似的角色,只不过它们的工作方式不是很起眼。
3. 继承

#### 2 相信你的眼睛,而不是数字
#### 3 关于响应式网页设计
然而对于今后的 CSS 改动来说,每个媒体查询都会增加成本,而这种成本是不应轻易上升的。

这并不是说媒体查询是一种不良实践。只要用对了,它就是利器。但是,你只应该把它作为最后的手段。

下面还有一些建议,可能会帮你避免不必要的媒体查询。
1. 使用百分比长度来取代固定长度。如果实在做不到这一点,也应该尝试使用与视口相关的单位(vw、vh、vmin 和 vmax) ,它们的值解析为视口宽度或高度的百分比。
1. 当你需要在较大分辨率下得到固定宽度时,使用 max-width 而不是width,因为它可以适应较小的分辨率,而无需使用媒体查询。
1. 不要忘记为替换元素(比如 img、object、video、iframe 等)设置一个 max-width,值为 100%。
1. 假如背景图片需要完整地铺满一个容器,不管容器的尺寸如何变化,background-size: cover 这个属性都可以做到。但是,我们也要时刻牢记——带宽并不是无限的,因此在移动网页中通过 CSS 把一张大图缩小显示往往是不太明智的。
1. 当图片(或其他元素)以行列式进行布局时,让视口的宽度来决定列的数量。弹性盒布局(即 Flexbox)或者 display: inline-block加上常规的文本折行行为,都可以实现这一点。
1. 在使用多列文本时,指定 column-width(列宽)而不是指定column-count(列数) ,这样它就可以在较小的屏幕上自动显示为单列布局。
#### 4 合理使用简写
合理使用简写是一种良好的防卫性编码方式,可以抵御未来的风险。当然,如果我们要明确地去覆盖某个具体的展开式属性并保留其他相关样式,那就需要用展开式
属性,就像我们在“尽量减少代码重复”一节中为了得到按钮的其他颜色版本所做的那样。

其实我们可以从 CSS 的“列表扩散规则”那里得到好处。它的意思是说,如果只为某个属性提供一个值,那它就会扩散并应用到列表中的每一项。因此,我们可以把这些重复的值从简写属性中抽出来写成一个展开式属性:

background: url(tr.png) top right,
url(br.png) bottom right,
url(bl.png) bottom left;
background-size: 2em 2em;
background-repeat: no-repeat;
#### 5 我应该使用预处理器吗
不过,预处理器也不是完美无缺的。

> 怪异的简写语法
在 background 简写属性中指定 background-size时,需要同时提供一个 background-position 值(哪怕它的值就是其初始值也需要写出来) ,而且还要使用一个斜杠(/)作为分隔。为什么有些简写的语法如此怪异?
这通常都是为了消除歧义。在这个例子中,top right 显然是background-position,而 2em 2em 是background-size,不管它们的顺序如何。但是,请设想一下 50% 50% 这样的值,它到底是 background-size 还是 background-position 呢?
对绝大多数的简写属性来说,并没有这样的歧义问题,因而简写属性的多个值往往可以随意排列。不过,我还是建议你养成随手查阅语法的好习惯,

或者在未来,说不定预处理器最受欢迎的那些特性都被加入了原生 CSS 中。很惊讶吗?没错,很多受预处理器启发的特性都已经以各种方式融入到原生 CSS 中了。

请注意,这些原生特性通常比预处理器提供的版本要强大得多,因为它们是动态的
1(①不要忘了这样的原生 CSS 特性也可以通过脚本来操纵。比如说,你可以用 JS 来改变一个变量的值)。举个例子,预处理器完全不知道如何完成 100% - 50px 这样的计算,因为在页面真正被渲染之前,百分比值是无法解析的。但是,原生CSS 的 calc() 在计算这样的表达式时没有任何压力。与此类似,下面这样的变量玩法在预处理器中是不可能做到的:

ul { –accent-color: purple; }
ol { –accent-color: rebeccapurple; }
li { background: var(–accent-color); }

11.19 23:34

第2 章 背景与边框

1 半透明边框

2 多重边框

3 灵活的背景定位

4 边框内圆角

5 条纹背景

6 复杂的背景图案

7 伪随机背景

8 连续的图像边框

第3 章 形状

9 自适应的椭圆

10 平行四边形

11 菱形图片

12 切角效果

13 梯形标签页

14 简单的饼图

第4 章 视觉效果

15 单侧投影

16 不规则投影

17 染色效果

18 毛玻璃效果

19 折角效果

第5 章 字体排印

20 连字符断行 113

21 插入换行 115

22 文本行的斑马条纹 119

23 调整 tab 的宽度 121

24 连字 123

25 华丽的 & 符号 125

26 自定义下划线 129

27 现实中的文字效果 132

28 环形文字 138

第6 章 用户体验

29 选用合适的鼠标光标 144

30 扩大可点击区域 147

31 自定义复选框 149

32 通过阴影来弱化背景 153

33 通过模糊来弱化背景 157

34 滚动提示 159

35 交互式的图片对比控件 164

第7 章 结构与布局

36 自适应内部元素 173

37 精确控制表格列宽 175

38 根据兄弟元素的数量来设置样式 178

39 满幅的背景,定宽的内容 182

40 垂直居中 185

41 紧贴底部的页脚 191

第8 章 过渡与动画

42 缓动效果 196

43 逐帧动画 205

44 闪烁效果 209

45 打字动画 212

46 状态平滑的动画 217

47 沿环形路径平移的动画 221

按规范分类 230

knowledge is no pay,reward is kindness
0%