[TOC]
> 部分文章内容来源:《CSS SECRETS》
> 配套 demos:[http://play.csssecrets.io/](http://play.csssecrets.io/)
# Part 1 背景与边框、形状、视觉效果
## 背景与边框
<span style="color: MediumOrchid;font-size: 20px; font-family: 楷体; font-weight: bold;">使用 background-clip 属性控制背景的绘制区域</span>
- border-box:背景被裁剪到边框盒
- padding-box:背景被裁剪到内边距盒(默认)
- content-box:背景被裁减到内容框
这个属性的初始值是 border-box,意味着背景会被元素的 border-box (边框的外沿框)裁切掉。如果不希望背景侵入边框所在的范围,我们要做的就是把它的值设为 padding-box(使用内边距的外沿框来裁切背景)。
你可以通过下面这个半透明边框的例子来理解这个属性的使用:
[http://dabblet.com/gist/012289cc14106a1bd7a5](http://dabblet.com/gist/012289cc14106a1bd7a5)
<span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">多重边框</span>
- box-shadow 方案:利用第四个参数(扩张半径)让投影面积增大或减小,box-shadow 支持逗号分隔语法,我们可以创建任意数量的投影;
有如下一些注意事项:
1.投影不会影响布局,也不受 box-sizing 属性的影响。
2.这种方法创建出的假 “边框” 不会响应鼠标事件,如果这一点非常重要,你可以给 box-shadow 属性加上 inset 关键字,来使投影绘制在元素的内圈。
3.box-shadow 是层层叠加的
```css
background: yellowgreen;
box-shadow: 0 0 0 10px #655, 0 0 0 15px deeppink;
```
![](https://box.kancloud.cn/3b6c2ae70261d9a13b1fec46abe26b49_434x425.png =200x)
- outline 方案:在某些情况下,你可能只需要两层边框,那就可以先设置一层常规边框,再加行 outline(描边)属性来产生外层的边框。这种方式的优点是边框样式十分灵活(不像 box-shadow 只能模拟实线边框);另外,可以通过 outline-offset 属性来控制它跟元素边缘之间的间距。
```css
background: #333;
border-radius: 5px;
outline: 2px dashed white;
outline-offset: -20px;
```
![](https://box.kancloud.cn/75663f9148cd5b325807249b8b6ab3e6_270x146.png =200x)
*****
蚂蚁行军效果:[展示](http://dabblet.com/gist/f26dddc71730c3847153)
分析:[https://www.jianshu.com/p/04b69172ab9e](https://www.jianshu.com/p/04b69172ab9e)
<span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">灵活的背景定位</span>
如果我们想针对容器某个角对背景图片做偏移定位,有如下一些解决方案
- background-position:该属性允许我们指定背景图片距离任意角的偏移量
举例来说,如果我们想让背景图片跟右边缘保持 20px 的偏移量,同时跟底边保持 10px 的偏移量,可以这样做:
```css
background: url(code-private.svg) no-repeat #58a;
background-position: right 20px bottom 10px;
```
demo 地址:[http://dabblet.com/gist/0f226e63595d1bef88cb](http://dabblet.com/gist/0f226e63595d1bef88cb)
- background-origin:有时候我们希望偏移与容器的内边距一致,就可以利用这个属性,其规定了 background-position 的偏移是以什么为基准(边距还是内容)
![](https://img.kancloud.cn/bc/95/bc9544d9ae33674bfbd4200c25ef3f22_498x316.png =300x)
我们也许写过这样的代码:`background-position: top left;`,那么这个 top、left 到底是哪个左上角?每个元素都存在如上图的三个矩形框:content box(内容区的外沿框)、padding box(内边距的外沿框)、border box(边框的外沿框),默认情况下,background-position 是以 padding-box 为准的,这样边框才不会遮住背景图片。因此,top left 默认指的是 padding box 的左上角。
现在,你可以用 background-origin 属性来改变这个默认行为,它的默认值是 padding-box,如果修改为 content-box,那么 background-position 属性中使用的边角关键字将会以内容区的边缘作为基准。
<span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">渐变</span>
渐变就是一种代码生成的图像,先设置一个最基础的:
```css
background: linear-gradient(#fb3, #58a);
```
![](https://box.kancloud.cn/32fbc61f791d8c3c2cf9c79a9037504c_271x263.png =150x)
然后我们试着把这两个色标拉近一点:
```css
background: linear-gradient(#fb3 20%, #58a 80%);
```
![](https://box.kancloud.cn/d81e8dadfec5f29c7dbf49ca6db2c5c6_275x267.png =150x)
现在容器顶部的 20% 区域被填充为 #fb3 实色,而底部 20% 区域被填充为 #58a 实色,真正的渐变只出现在容器 60% 的高度区域。
>[success] 是否可以这么理解?把色标位置值想成在距离顶部多少位置画一条线,只有这两条线之间的部分才有渐变。且最后一个色标位置之后都是该色标颜色。
如果我们把两个色标重合在一起会发生什么?
```css
background: linear-gradient(#fb3 50%, #58a 0);
/* 第二个色标的位置值设置为 0,那么它的位置就和前一个色标的位置值相同 */
```
![](https://box.kancloud.cn/586b891ec428a0595de73d6162fa7772_271x268.png =150x)
可以看到:已经没有任何渐变效果了,只有两块实色,各占据 background-image 一半的面积。
<span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">水平条纹</span>
因为渐变是一种由代码生成的图像,所以我们能像对待其他任何背景图像那样对待它,而且还可以通过 background-size 来调整其尺寸:
```css
/* 左图-没有平铺的情况 */
background: linear-gradient(#fb3 50%, #58a 0) no-repeat;
background-size: 100% 30px;
/* 右图 */
background: linear-gradient(#fb3 50%, #58a 0);
background-size: 100% 30px;
```
![](https://box.kancloud.cn/3cdb8b445d99bf2b876f05f6a4041c2c_651x274.png)
我们还可以创建多种颜色、不等宽的条纹:
```css
background: linear-gradient(#fb3 33.3%, #58a 0, #58a 66.6%, yellowgreen 0);
background-size: 100% 45px;
```
![](https://box.kancloud.cn/91e973e149da1b10e4a5319cf2812892_266x263.png =200x)
<span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">垂直条纹</span>
对于垂直条纹,我们需要在开头加上一个额外的参数来指定渐变的方向(默认 to bottom),然后,还需要把 background-size 的值颠倒一下:
```css
background: linear-gradient(to right, /* 或 90deg*/
#fb3 50%, #58a 0);
background-size: 30px 100%;
```
![](https://box.kancloud.cn/e0d7d4e6e92cdd7347e055c985d79843_267x270.png =150x)
<span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">斜向条纹</span>
对于斜向条纹,我们可以利用 repeating-linear-gradient() 和 repeating-radial-gradient() 这两个 linear-gradient() 和 radial-gradient() 的循环式加强版,它们的工作方式与之前的类似,只有一点不同:**色标是无限循环重复的,直到填满整个背景**。(这里我就不记为啥只用 linear-gradient() 不好实现斜向渐变了,感兴趣的自己尝试)
```css
background: repeating-linear-gradient(45deg, #fb3, #58a 30px);
```
它相当于下面这样:
```css
background: linear-gradient(45deg, #fb3, #58a 30px,
#fb3 30px, #58a 60px,
#fb3 60px, #58a 90px,
#fb3 90px, #58a 120px,...)
```
![](https://box.kancloud.cn/ceaac8b4a251711a61563a1e8d13809c_267x267.png =150x)
<span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">灵活的同色系条纹</span>
大多数情况下,我们想要的条纹图案并不是由差异极大的几种颜色组成的,这些颜色往往属于同一色系。我们可以把最深的颜色指定为背景色,同时把半透明白色的条纹叠加在背景色之上来得到浅色条纹:
```css
background: #58a;
background-image: repeating-linear-gradient(30deg,
hsla(0, 0%, 100%, .1),
hsla(0, 0%, 100%, .1) 15px,
transparent 0, transparent 30px);
```
![](https://box.kancloud.cn/799f7d94ed255c6f5ee8736ccdfa2f84_266x147.png =150x)
### 实现常用的图案
只使用一个渐变时,我们能创建的图案并不多,当我们把多个渐变图案组合起来,让它们透过彼此的透明区域显现时,神奇的事情就发生了。
<span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">网格</span>
我们让水平和垂直的条纹叠加起来,就能得到各式各样的网格:
```css
background: white;
background-image: linear-gradient(90deg,
rgba(200, 0, 0, .5) 50%, transparent 0),
linear-gradient(
rgba(200, 0, 0, .5) 50%, transparent 0);
background-size: 30px 30px;
```
![](https://box.kancloud.cn/20c743ba0e0a17879b329d1d69f2d5a1_200x208.png =150x)
<span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">图纸效果</span>
```css
background: #58a;
background-image:
linear-gradient(white 1px, transparent 0),
linear-gradient(90deg, white 1px, transparent 0);
background-size: 30px 30px;
```
![](https://box.kancloud.cn/9091269c185dd1e58012a6e6996328c0_201x207.png =150x)
<span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">波点</span>
径向渐变允许我们创建圆形、椭圆,或是它们的一部分。
```css
background: #655;
background-image: radial-gradient(tan 30%, transparent 0),
radial-gradient(tan 30%, transparent 0);
background-size: 30px 30px;
background-position: 0 0, 15px 15px; /* 让背景定位错开 */
```
![](https://box.kancloud.cn/69b7f027a109f76fa89d1ff7ec434276_205x205.png =150x)
为了达到效果,第二层背景的偏移定位值必须是贴片宽高的一半,这意味着如果要改动贴片的尺寸,需要修改四处。这样代码就很难维护,我们可以写一个 mixin:
```css
@mixin polka($size, $dot, $base, $accent) {
background: $base;
background-image:
radial-gradient($accent $dot, transparent 0),
radial-gradient($accent $dot, transparent 0);
background-size: $size $size;
background-position: 0 0, $size / 2 $size / 2;
}
// 在创建波点图案时,我们就可以这么调用它
@include polka(30px, 30%, #655, tan);
```
## 形状
### border-radius
四个属性值:border-radius:10px 20px 30px 40px;
表示左上角、右上角、右下角、左下角的圆角大小(**顺时针方向**)
![](https://img.kancloud.cn/9b/ca/9bca20db5976ea3581b7ac6bb74d7700_350x269.png =200x)
<br/>
三个属性值:border-radius:10px 30px 60px;
第一个值表示左上角,第二个值表示右上角和左下角(对角),第三个值表示右下角。
![](https://img.kancloud.cn/37/20/37208f9a1f09121523dc9a759be36739_369x278.png =200x)
<br />
两个属性值:border-radius:20px 40px;
第一个值表示左上角和右下角,第二个值表示右上角和左下角。
![](https://img.kancloud.cn/f2/44/f244e06cd8d4297ce8e6a0b6f33dba1f_332x273.png =200x)
斜杠二组值:第一组值表示水平半径,第二组值表示垂直半径,每组值也可以同时设置1到4个值,规则与上面相同。
```css
border-radius: 2em 1em 4em / 0.5em 3em;
```
等价于:
```css
border-top-left-radius: 2em 0.5em;
border-top-right-radius: 1em 3em;
border-bottom-right-radius: 4em 0.5em;
border-bottom-left-radius: 1em 3em;
```
一个沿纵轴劈开的椭圆:
```css
border-radius: 100% 0 0 100% / 50%;
```
四分之一椭圆:
```css
border-radius: 100% 0 0 0;
```
鸡蛋:
```css
.egg {
width: 120px;
height: 160px;
background: #EC0465;
border-radius: 60px 60px 60px 60px/100px 100px 60px 60px;
}
```
花瓣:
```css
.flower {
width: 120px;
height: 120px;
background: #EC0465;
border-radius: 60px 60px 0 60px;
}
```
![](https://box.kancloud.cn/f81ca538670b4cdf6e59b524ae0f66e1_1131x209.png)
### 平行四边形
我们可以通过 skew() 的变形属性来对元素进行斜向拉伸,但是这会导致该元素的内容也斜向变形,有没有办法只让容器的形状倾斜,而保持其内容不变呢?
1.嵌套元素方案
我们可以对内容再应用一次反向的 skew() 变形,从而抵消容器的变形效果,不过这意味着我们需要添加额外的 HTML 元素。
```html
<a href="#" class="button">
<div>Click me</div>
</a>
.button { transform: skewX(-45deg); }
.button > div { transform: skewX(45deg); }
```
2.伪元素方案
我们把所有的样式(背景、边框等)应用到伪元素上,然后再对伪元素进行变形。
我们希望伪元素保持良好的灵活性,可以自动继承其宿主元素的尺寸,甚至当宿主元素的尺寸是由其内容来决定时仍然如此。一个简单的办法就是给宿主元素应用 position:relative 样式,并为伪元素设置 position:absolute,然后把所有偏移量设置为零,以便让它在水平和垂直方向上都被拉伸至宿主元素的尺寸。
```css
.button {
position: relative;
/* 其他的文字颜色、内边距等样式 */
}
.button::before {
content: '';
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
z-index: -1; /* 防止遮住内容 */
background: #58a;
transform: skew(45deg);
}
```
![](https://box.kancloud.cn/4d171bda2788ee8804d2d472a39ec0a2_216x88.png =150x)
### 菱形图片
裁切路径方案:使用 clip-path 属性,它允许我们使用一系列以逗号分隔的坐标点来指定任意的多边形,百分比值会被解析为元素自身的尺寸。
```css
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
```
我们甚至可以利用这个属性来实现动画效果:
```css
img {
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
transition: 1s clip-path;
}
img:hover {
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}
```
![](https://box.kancloud.cn/33c52fb43812bbd3a2429904ea766788_320x236.gif)
相关属性值介绍:[https://www.jb51.net/css/601746.html](https://www.jb51.net/css/601746.html)
## 视觉效果
### 投影
```css
{
box-shadow: none| [inset? && [ <offset-x> <offset-y> <blur-radius>? <spread-radius>? <color>? ] ]
}
```
以 `box-shadow: 1px 2px 3px 4px #333` 为例,4 个数值的含义分别是,x 方向偏移值、y 方向偏移值 、模糊半径、扩张半径。
>扩张半径是以阴影的外边界向外扩展(为正数)或者向内抵消原来的阴影(为负数),当负数绝对值大于等于某方向的阴影偏移量时,该方向的阴影消失。
<iframe height="300" style="width: 100%;" scrolling="no" title="阴影属性" src="//codepen.io/chenmingk/embed/Bgazpw/?height=265&theme-id=0&default-tab=css,result" frameborder="no" allowtransparency="true" allowfullscreen="true">
See the Pen <a href='https://codepen.io/chenmingk/pen/Bgazpw/'>阴影属性</a> by 陈明康
(<a href='https://codepen.io/chenmingk'>@chenmingk</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>
如果我们想实现双侧投影呢?(比如左侧和右侧),可以把 “单侧投影” 运用两次:
```css
box-shadow: 5px 0 5px -5px black,
-5px 0 5px -5px black;
```
<span style="font-family: 楷体; font-size: 20px; color: #007fff; font-weight: bold;">不规则投影</span>
难题:当我们想给一个矩形或其他能用 border-radius 生成的形状加投影时,box-shadow 的表现都堪称完美。但是,当元素添加了一些伪元素或半透明的装饰之后,它就有些力不从心了,因为 border-radius 会忽视透明部分。这类情况包括:
- 半透明图像、背景图像、或者 border-image
- 元素设置了点状、虚线或半透明的边框,但没有背景(或者当 background-clip 不是 border-box 时)
- 对话气泡,它的小尾巴通常是用伪元素生成的
- 几乎所有的折角效果
- 通过 clip-path 生成的形状
解决方案:(不完全支持所有浏览器)
[滤镜效果规范](http://w3.org/TR/filter-effects) 为这个问题提供了一个解决方案。它引入了一个叫作 filter 的新属性,这个属性也是从 SVG 那里借鉴过来的。尽管 CSS 滤镜基本上就是 SVG 滤镜,但我们并不需要掌握任何 SVG 知识,只需要一些函数就可以很方便地指定滤镜效果了,比如 blur()、grayscale()、以及我们需要的 drop-shadow()。我们甚至可以把多个滤镜串连续起来,如下:
```css
filter: blur() grayscale() drop-shadow();
```
drop-shadow() 滤镜可接受的参数基本上跟 box-shadow 属性是一样的,但不包括扩展半径,不包括 inset 关键字,也不支持逗号分隔的多层投影语法。
![](https://img.kancloud.cn/11/3e/113ec62b8c1ebe246403842c930c8614_844x235.png)
demo 地址:[http://dabblet.com/gist/d8a2376c79906d68f3d1](http://dabblet.com/gist/d8a2376c79906d68f3d1)
<br/>
CSS 滤镜最大的好处在于,它们可以平稳退化:当浏览器不支持时,不会出现问题,只不过没有任何效果而已。
# Part2 字体排印、用户体验、结构与布局、过渡与动画
- 序言 & 更新日志
- H5
- Canvas
- 序言
- Part1-直线、矩形、多边形
- Part2-曲线图形
- Part3-线条操作
- Part4-文本操作
- Part5-图像操作
- Part6-变形操作
- Part7-像素操作
- Part8-渐变与阴影
- Part9-路径与状态
- Part10-物理动画
- Part11-边界检测
- Part12-碰撞检测
- Part13-用户交互
- Part14-高级动画
- CSS
- SCSS
- codePen
- 速查表
- 面试题
- 《CSS Secrets》
- SVG
- 移动端适配
- 滤镜(filter)的使用
- JS
- 基础概念
- 作用域、作用域链、闭包
- this
- 原型与继承
- 数组、字符串、Map、Set方法整理
- 垃圾回收机制
- DOM
- BOM
- 事件循环
- 严格模式
- 正则表达式
- ES6部分
- 设计模式
- AJAX
- 模块化
- 读冴羽博客笔记
- 第一部分总结-深入JS系列
- 第二部分总结-专题系列
- 第三部分总结-ES6系列
- 网络请求中的数据类型
- 事件
- 表单
- 函数式编程
- Tips
- JS-Coding
- Framework
- Vue
- 书写规范
- 基础
- vue-router & vuex
- 深入浅出 Vue
- 响应式原理及其他
- new Vue 发生了什么
- 组件化
- 编译流程
- Vue Router
- Vuex
- 前端路由的简单实现
- React
- 基础
- 书写规范
- Redux & react-router
- immutable.js
- CSS 管理
- React 16新特性-Fiber 与 Hook
- 《深入浅出React和Redux》笔记
- 前半部分
- 后半部分
- react-transition-group
- Vue 与 React 的对比
- 工程化与架构
- Hybird
- React Native
- 新手上路
- 内置组件
- 常用插件
- 问题记录
- Echarts
- 基础
- Electron
- 序言
- 配置 Electron 开发环境 & 基础概念
- React + TypeScript 仿 Antd
- TypeScript 基础
- 样式设计
- 组件测试
- 图标解决方案
- Algorithm
- 排序算法及常见问题
- 剑指 offer
- 动态规划
- DataStruct
- 概述
- 树
- 链表
- Network
- Performance
- Webpack
- PWA
- Browser
- Safety
- 微信小程序
- mpvue 课程实战记录
- 服务器
- 操作系统基础知识
- Linux
- Nginx
- redis
- node.js
- 基础及原生模块
- express框架
- node.js操作数据库
- 《深入浅出 node.js》笔记
- 前半部分
- 后半部分
- 数据库
- SQL
- 面试题收集
- 智力题
- 面试题精选1
- 面试题精选2
- 问答篇
- Other
- markdown 书写
- Git
- LaTex 常用命令