[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;
```

- outline 方案:在某些情況下,你可能只需要兩層邊框,那就可以先設置一層常規邊框,再加行 outline(描邊)屬性來產生外層的邊框。這種方式的優點是邊框樣式十分靈活(不像 box-shadow 只能模擬實線邊框);另外,可以通過 outline-offset 屬性來控制它跟元素邊緣之間的間距。
```css
background: #333;
border-radius: 5px;
outline: 2px dashed white;
outline-offset: -20px;
```

*****
螞蟻行軍效果:[展示](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 的偏移是以什么為基準(邊距還是內容)

我們也許寫過這樣的代碼:`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);
```

然后我們試著把這兩個色標拉近一點:
```css
background: linear-gradient(#fb3 20%, #58a 80%);
```

現在容器頂部的 20% 區域被填充為 #fb3 實色,而底部 20% 區域被填充為 #58a 實色,真正的漸變只出現在容器 60% 的高度區域。
>[success] 是否可以這么理解?把色標位置值想成在距離頂部多少位置畫一條線,只有這兩條線之間的部分才有漸變。且最后一個色標位置之后都是該色標顏色。
如果我們把兩個色標重合在一起會發生什么?
```css
background: linear-gradient(#fb3 50%, #58a 0);
/* 第二個色標的位置值設置為 0,那么它的位置就和前一個色標的位置值相同 */
```

可以看到:已經沒有任何漸變效果了,只有兩塊實色,各占據 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;
```

我們還可以創建多種顏色、不等寬的條紋:
```css
background: linear-gradient(#fb3 33.3%, #58a 0, #58a 66.6%, yellowgreen 0);
background-size: 100% 45px;
```

<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%;
```

<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,...)
```

<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);
```

### 實現常用的圖案
只使用一個漸變時,我們能創建的圖案并不多,當我們把多個漸變圖案組合起來,讓它們透過彼此的透明區域顯現時,神奇的事情就發生了。
<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;
```

<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;
```

<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; /* 讓背景定位錯開 */
```

為了達到效果,第二層背景的偏移定位值必須是貼片寬高的一半,這意味著如果要改動貼片的尺寸,需要修改四處。這樣代碼就很難維護,我們可以寫一個 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;
表示左上角、右上角、右下角、左下角的圓角大小(**順時針方向**)

<br/>
三個屬性值:border-radius:10px? ?30px? 60px;
第一個值表示左上角,第二個值表示右上角和左下角(對角),第三個值表示右下角。

<br />
兩個屬性值:border-radius:20px? 40px;
第一個值表示左上角和右下角,第二個值表示右上角和左下角。

斜杠二組值:第一組值表示水平半徑,第二組值表示垂直半徑,每組值也可以同時設置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;
}
```

### 平行四邊形
我們可以通過 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);
}
```

### 菱形圖片
裁切路徑方案:使用 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://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 關鍵字,也不支持逗號分隔的多層投影語法。

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 基礎
- React + ts
- 樣式設計
- 組件測試
- 圖標解決方案
- Storybook 的使用
- Input 組件
- 在線 mock server
- 打包與發布
- Algorithm
- 排序算法及常見問題
- 劍指 offer
- 動態規劃
- DataStruct
- 概述
- 樹
- 鏈表
- Network
- Performance
- Webpack
- PWA
- Browser
- Safety
- 微信小程序
- mpvue 課程實戰記錄
- 服務器
- 操作系統基礎知識
- Linux
- Nginx
- redis
- node.js
- 基礎及原生模塊
- express框架
- node.js操作數據庫
- 《深入淺出 node.js》筆記
- 前半部分
- 后半部分
- 數據庫
- SQL
- 面試題收集
- 智力題
- 面試題精選1
- 面試題精選2
- 問答篇
- 2025面試題收集
- Other
- markdown 書寫
- Git
- LaTex 常用命令
- Bugs