寫作背景
女朋友要我教她CSS,於是我就折騰了一週,終於完成了這篇長文…
然後,然後?然後當我發佈這篇文章的時候,她會感動到哭嗎?
熟悉HTML知識
HTML常見元素
head
部分
body
部分
doctype的意義是什麼
- 讓瀏覽器以標準模式渲染
- 讓瀏覽器知道元素的合法性
HTML、XHTML、HTML5的關係
- HTML屬於SGML(標記語言)
- XHTML屬於XML,是HTML進行XML嚴格化的結果
- HTML5不屬於SGML或XML,比XHTML寬鬆
HTML5有什麼變化
- 新的語義化元素
- 表單增強
- 新的API(離線、音視頻、圖形、實時通信、本地存儲、設備能力)
- 分類和嵌套變更
em和 i 有什麼區別
- em是語義化的標籤,表強調
- i 是純樣式的標籤,表斜體
- HTML5中 i 不推薦使用,一般用作圖標
語義化的意義
- 開發者容易理解
- 機器容易理解(搜索、讀屏、軟件)
- 有利用SEO
- semantic microdata(語義微數據)例電影有評分
哪些元素可以自閉合
- 表單元素 input
- 圖片 img
- br hr
- meta link
HTML和DOM關係
- HTML是“死”的(字符串)
- DOM是由HTML解析而來的,是活的
- JS可以維護DOM
property 和 attritube 區別
- attritube 是“死”的
- property 是活的
- 相互之間不會影響
form的好處
- 直接提交表單
- 使用 submit / reset 按鈕
- 便於瀏覽器保存表單
- 第三方庫可以整體取值
- 第三方庫可以進行表單驗證
CSS精華(Cascading Style Sheet)層疊樣式表
選擇器
- 用於適配HTML元素
- 分類和權重
- 解析方式和性能
- 值得關注的選擇器
選擇器分類
- 元素選擇器
a{}
- 僞元素選擇器
::before{}
- 類元素選擇器
.link{}
- 屬性選擇器
[type=radio]{}
- 僞類選擇器
:hover{}
- ID選擇器
#id{}
- 組合選擇器
[type=checkbox] + label{}
- 否定選擇器
:not(.link){}
- 通用選擇器
*{}
選擇器權重(1)
- ID選擇器 #id{}+100
- 類 屬性 僞類 +10
- 元素 僞元素 +1
- 其它選擇器 +0
例子:計算一個不進位的數字
#id.link a[href]
————————————————
計算過程:
#id +100
.link +10
a +1
[href] +0
結果:111
#id .link.active
————————————————
計算過程:
#id +100
.link +10
.active +10
結果:120
那麼,我們怎麼理解 不進位的數字 這關鍵字眼呢?用一個簡單例子吧:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS選擇器</title>
<style>
#test1{
color: red;
}
#test1.test1{
color: blue;
}
.test2{
color: red;
}
div.test2{
color: blue;
}
#test3{
color: red;
}
.c1.c2.c3.c4.c5.c6.c7.c8.c9.c10.c11{
color: blue;
}
</style>
</head>
<body class="body" id="body">
<div id="test1" class="test1">藍色</div>
<div class="test2">藍色</div>
<div id="test3" class="c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11">紅色</div>
</body>
</html>
結果如下圖所示:
不妨發現,最後一個 div
,儘管我們類選擇器有11個,加起來有110,但是依舊沒有 id 選擇器優先級高,正是因爲這個不進位的數字,簡單說:你大爺還是你大爺!
選擇器權重(2)
- !important 優先級最高
- 元素屬性 優先級高
- 相同權重 後寫的生效
舉個栗子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS選擇器</title>
<style>
.test1{
color: red;
}
.test1{
color: blue;
}
.test2{
color: red!important;
}
.test2{
color: blue;
}
#test3{
color: red;
}
</style>
</head>
<body class="body" id="body">
<div class="test1">藍色</div>
<div class="test2">紅色</div>
<div id="test3" style="color: blue;">藍色</div>
</body>
</html>
運行結果如下圖所示:
非佈局樣式
字體
- 字體族 例如: serif、monospace(不能添加引號)襯線字體
- 多字體fallback 例如: “monaco”、“Microsoft Yahei”、“PingFang SC”
- 網絡字體、自定義字體
- iconfont
行高(經典問題)
- 行高的構成(由line-box組成,line-box由inline-box組成)
- 行高相關的現象和方案(可以通過設置 line-height來實現垂直居中效果)
- 行高的調整
經典問題:圖片下面有空隙,原理是什麼?怎樣去除?
原理是因爲圖片按照 inline 進行排版,排版的時候會涉及到字體對齊,默認按照 baseline
對齊,baseline
和底線之間是有偏差的,偏差大小是根據字體大小而定,如果是12px字體大小,則圖片空隙就是3px左右。這就是經典圖片3px空隙問題。
解決方式:
- 由於默認按照
baseline
對齊,不妨將vertical-align
設爲bottom
,按照底線對齊。 - 設置
display:block
可以解決該問題,但是會獨佔一行,如下圖所示:
背景
- 背景顏色
- 漸變色背景
- 多背景疊加
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>漸變色背景(線性梯度)</title>
<style>
.div1{
height: 90px;
}
.div2{
height: 90px;
/*background: linear-gradient(to right,red,green);*/
/*background: linear-gradient(180deg,red,green);*/
/*background: linear-gradient(135deg,red 0,green 15%,yellow 50%,blue 90%);*/
/*網格線*/
background: linear-gradient(135deg,transparent 0,transparent 49.5%,green 49.5%,green 50.5%,transparent 50.5%,transparent 100%),
linear-gradient(45deg,transparent 0,transparent 49.5%,red 49.5%,red 50.5%,transparent 50.5%,transparent 100%);
background-size: 30px 30px;
}
</style>
</head>
<body>
<div class="div1"></div>
<div class="div2"></div>
</body>
</html>
最後一個例子展示效果:
- 背景圖片和屬性(雪碧圖)
background-repeat: no-repeat;
background-size: 30px 30px; //相對於容器偏移
background-position: 30px 30px;
雪碧圖 就是將很多個圖片進行拼接成一個圖片,然後通過 background-position
等屬性進行偏移,在網頁中得到對應圖片,來達到減少http請求。
-
base64和性能優化
將圖片進行base64編碼後,就是一個字符文本,缺點之一就是圖片的體積會增大
1/3
左右,並且放入css文件中,也會導致css文件變大。另外,雖然能減少http請求,但增大瞭解碼的開銷。適用於小圖標icon
,例如loading
文件等。最後,在開發環境一般不採用直接將圖片進行base64
編碼,因爲對於協同開發來說,無法知曉圖片原樣,只有一個文本。一般情況下,是在生產環境下,通過打包的方式,將小圖片進行
base64
編碼。 -
多分辨率適配
邊框(經典問題)
- 邊框的屬性:線型 大小 顏色
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>邊框</title>
<style>
.c1{
width: 400px;
height: 200px;
border: 1px solid red;
/*border: 5px solid red;*/
/*border: 5px dotted red;*/
/*border: 5px dashed red;*/
}
</style>
</head>
<body>
<div class="c1"></div>
</body>
</html>
- 邊框背景圖
經典問題:九宮格問題,例如下面圖片,我們如果想要實現9個不同形式,然後中間放內容,如果用原本9個div方法,那麼會非常麻煩,而css3提供了 border
方式可以解決上述問題。
在沒有在 border-image
處設置 round
之前,是如上效果,後面 30 是用來切出四個角。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>邊框</title>
<style>
.c1{
width: 400px;
height: 200px;
border: 30px solid transparent;
border-image: url(./xx.png) 30 round; /*round將圖片進行整數個拼接*/
}
</style>
</head>
<body>
<div class="c1"></div>
</body>
</html>
在 border-image
處設置 round
之後,是如下效果,基本達到我們想要的效果。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>邊框</title>
<style>
.c2{
width: 400px;
height: 200px;
border: 30px solid transparent;
border-image: url(./xx.png) 30 round; /*round將圖片進行整數個拼接*/
}
</style>
</head>
<body>
<div class="c2"></div>
</body>
</html>
- 邊框銜接(三角形)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>邊框</title>
<style>
.c3{
width: 0px;
height: 200px;
border-bottom: 30px solid red;
border-left: 30px solid transparent;
border-right: 30px solid transparent;
}
</style>
</head>
<body>
<div class="c3"></div>
</body>
</html>
實現三角形,效果如下:
滾動
產生滾動的原因:當內容比容器多的時候,即容器裝不下內容的時候,就需要滾動。滾動主要包括如下幾個方面:
- 滾動行爲和滾動條
overflow
設置auto
和scroll
區別,auto 是內容多於容器時顯示滾動條,反正,不顯示。而 scroll 是一直顯示滾動條
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>滾動</title>
<style>
.div1{
background: red;
height: 200px;
overflow: scroll; /*可選值: hidden visible auto scroll*/
}
</style>
</head>
<body>
<div class="div1">
<p>test</p>
<p>test</p>
<p>test</p>
<p>test</p>
<p>test</p>
<p>test</p>
<p>test</p>
<p>test</p>
<p>test</p>
<p>test</p>
<p>test</p>
</div>
</body>
</html>
文字折行(經典問題)
- overflow-wrap(word-wrap)通用換行控制(是否保留單詞)
- word-break 針對多字節文字(中文句字也是單詞)
- white-space 空白處是否斷行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文字折行</title>
<style>
.div1{
border: 1px solid;
width: 8em;
overflow-wrap: normal;
word-break: normal;
white-space: normal;
}
</style>
</head>
<body>
<div class="div1">
學如逆水行舟,不進則退!Learning is like sailing against the current, retreating if not advancing
</div>
</body>
</html>
展示效果:
經典問題:怎麼讓一個很長的文本不換行?
將上述屬性設置爲 nowrap
即可
white-space: nowrap;
裝飾性屬性
- 字重(粗體)font-weight
- 斜體 font-style:itatic
- 下劃線 text-decoration
- 指針 cursor
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>font-weight</title>
<style>
.div1{
font-weight: normal; /*400*/
font-weight: bold; /*700*/
font-weight: bolder;
font-weight: lighter;
font-weight: 100;
}
</style>
</head>
<body>
<div class="div1">學如逆水行舟,不進則退!</div>
</body>
</html>
CSS Hack(瞭解)
hack
用來處理瀏覽器兼容性做法,好處就是簡單粗暴。
- Hack即不合法但生效的寫法
- 主要用於區分不同瀏覽器
- 缺點:難理解 難維護 難失效
- 替代方案:特性檢測(檢測瀏覽器是否有相關特性,沒有的話就針對性處理)
- 替代方案:針對性加class(例如檢測到
IE6
,那麼就加IE6
的class)
CSS 面試真題
css樣式(選擇器)的優先級
- 計算權重確定
- !important
- 內聯樣式
- 後寫的優先級高
雪碧圖的作用
- 雪碧圖 就是將很多個圖片進行拼接成一個圖片,然後通過
background-position
等屬性進行偏移,在網頁中得到對應圖片,來達到減少http請求,提高頁面加載性能。 - 有一些情況下可以減少圖片大小(例如png格式圖片,每張圖片顏色基本上一樣的,有可能總的圖片大小是小於每個圖片加起來的大小的)
自定義字體的使用場景
- 宣傳 / 品牌 / banner 等固定文案
- 字體圖標(將文字變爲圖標)
base64的作用
將圖片進行base64編碼後,就是一個字符文本,缺點之一就是圖片的體積會增大 1/3
左右,並且放入css文件中,也會導致css文件變大。另外,雖然能減少http請求,但增大瞭解碼的開銷。適用於小圖標icon
,例如loading
文件等。最後,在開發環境一般不採用直接將圖片進行 base64
編碼,因爲對於協同開發來說,無法知曉圖片原樣,只有一個文本。
- 用於減少http請求
- 適用於小圖片
- base64的體積約爲原圖的 4/3
僞類和僞元素的區別?
- 僞類 表 狀態(某元素是個鏈接 link狀態)
- 僞元素是真的有元素(
::before{}
,在頁面中會顯示內容) - 前者使用單冒號,後者使用雙冒號
如何美化checkbox
- label [for] 和 id
- 隱藏原生 input(所有的樣式由
label
來搞定) - :checked + label
CSS 佈局
CSS體系知識的重中之重
- 早期以 table 爲主(簡單)
- 後來以技巧性佈局爲主(難)
- 現在有 flexbox / grid(偏簡單)
常用佈局方式
- table表格佈局
- float 浮動+ margin
- inline-block 佈局
- flexbox 佈局
佈局方式(表格)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>table佈局</title>
<style>
.table{
margin-top: 20px;
width: 500px;
height: 100px;
display: table;
}
.table-row{
display: table-row;
}
.table-cell{
vertical-align: center;
display: table-cell;
}
.left{
background: red;
vertical-align: middle;
}
.right{
background: blue;
vertical-align: middle;
}
</style>
</head>
<body>
<div class="table">
<div class="table-row">
<div class="left table-cell">left</div>
<div class="right table-cell">right</div>
</div>
</div>
</body>
</html>
展示效果如下圖所示:
display / position(經典問題)
- display 常用屬性值: block(塊級) / inline(內聯) / inline-block(對內表現爲block,可以有寬高,對外表現爲inline,可以與其它元素排在同一行)
- position 常用屬性值:static(靜態) / relative(相對) / absolute(絕對) / fixed(固定)
display
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>display</title>
<style>
.block{
height: 200px;
background: red;
}
.inline{
display: inline;
background: green;
}
.inline-block{
display: inline-block;
width: 200px;
height: 100px;
background: blue;
}
</style>
</head>
<body>
<div class="block">
block
</div>
<div class="inline">inline</div>
<div class="inline-block">inline-block</div>
</body>
</html>
position
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>position</title>
<style>
.p1{
width: 100px;
height: 100px;
background: red;
}
.p2{
position: relative;
width: 100px;
height: 100px;
left: 20px;
top: -10px;
background: blue;
}
.p3{
position: absolute;
width: 100px;
height: 100px;
left: 80px;
top: 30px;
background: yellow;
}
.p4{
position: fixed;
width: 100px;
height: 100px;
left: 0;
bottom: 10px;
background: green;
}
.p5{
width: 100px;
height: 100px;
background: pink;
}
</style>
</head>
<body>
<div class="p1">position:static</div>
<div class="p2">position:relative</div>
<div class="p3">position:absloute</div>
<div class="p4">position:fixed</div>
<div class="p5">no position</div>
</body>
</html>
展示效果如下:
由上圖可知,當設置 position
爲 relative
後,no position(粉色塊) 並沒有在藍色塊下面,也就是說設置 position
爲 relative
後,佔據空間還是按照原來的方式計算的,不會因爲偏移而改變佈局的計算。
經典問題:
-
絕對定位
absolute
,會優先查找父級定位爲absolute
或relative
的進行定位,如果父級沒有,找上級,那麼最終就會根據body
進行定位,它和fixed
一樣,也是脫離了文檔流。 -
fixed
相對於屏幕進行定位
層疊問題 ,因爲默認會根據先後順序顯示,因此會有覆蓋情況,此時,可以通過設計 z-index
解決,權重越大,優先顯示。
flexbox(聖盃佈局)
- 彈性盒子
- 盒子本來就是並列的
- 指定寬度即可
- 移動端常用
(目前用的不是很熱的原因是雖然簡單方便,但是兼容性有點問題)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>flexbox</title>
<style>
.container{
width: 800px;
height: 200px;
display: flex;
border: 1px solid black;
}
.flex{
background: blue;
flex: 1;
margin: 5px;
}
</style>
</head>
<body>
<div class="container">
<div class="flex">flex</div>
<div class="flex">flex</div>
<div class="flex">flex</div>
<div class="flex">flex</div>
<div class="flex">flex</div>
</div>
</body>
</html>
展示效果如下:
由這個很方便的佈局,我們可以寫一個聖盃佈局的例子(即左右固定,中間自適應):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>聖盃佈局-flexbox</title>
<style>
*{
margin: 0;
}
.container{
min-height: 200px;
display: flex;
}
.left{
width: 200px;
display: flex;
background: red;
}
.center{
background: yellow;
flex: 1;
}
.right{
width: 200px;
display: flex;
background: blue;
}
</style>
</head>
<body>
<div class="container">
<div class="left">left</div>
<div class="center">center</div>
<div class="right">right</div>
</div>
</body>
</html>
float
- 元素"浮動"
- 脫離文檔流(不會對其它元素的佈局造成影響)
- 但不脫離文本流
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>float佈局</title>
<style>
.container{
width: 400px;
background: red;
}
.p1{
width: 200px;
height: 80px;
float: left;
background: pink;
}
</style>
</head>
<body>
<div class="container">
<span class="p1">float元素</span>
<div class="p2">很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字</div>
</div>
</body>
</html>
展示效果如下:
float 特性的影響(經典問題)
float 特性對自己的影響:
- 形成塊(BFC,可以使得inline元素能夠設置寬高,例如上文代碼,原本span元素不能設置寬高的,但通過設置float佈局,使得可以設置寬高)
- 位置儘量靠上
- 位置儘量靠左(右)(對於上述解釋,是如果
container
寬度夠的話,就儘量靠上和靠左,如果不行的話,就往下排了)
簡單例子:
float 特性對兄弟的影響:
- 上面貼非 float 元素
- 旁邊貼 float 元素
- 不影響其它塊級元素位置(不脫離文檔流)
- 影響其它塊級元素內部文本(脫離了文本流)
float 特性對父級的影響:
- 從佈局上 “消失”(父級不會管它的寬高)
- 經典問題:高度塌陷 (假設float元素,原本是 100px 高度,這個時候很期望父級能撐開100個像素,但因爲設置了 float,等於消失了,並不會在意這 100個像素,因此,如果沒有其它元素支撐高度的話,父級的高度就會設置爲0,這就是高度塌陷)
清楚浮動的方式
經典問題:
清除浮動的方式
① 當我們設置爲 float 後,會將元素設爲 BFC,接管自己的寬高,因此我們也可以讓父級元素設置爲 BFC,來接管自己的寬高。
初始狀態:
在父級元素設置 overflow: auto/hidden;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>清楚浮動</title>
<style>
.container{
background: red;
width: 400px;
overflow: auto;
margin: 10px;
}
.p1{
background: pink;
float: left;
width: 200px;
height: 50px;
}
</style>
</head>
<body>
<div class="container">
<span>xxxxxx</span>
<span class="p1">float</span>
<span class="p1">float</span>
</div>
<div class="container" style="height: 200px; background: blue;">
<p>第一行</p>
<p>第二行</p>
<p>第三行</p>
</div>
</body>
</html>
最終狀態效果圖如下:
② 由於 float 不脫離文檔流(不會影響其它元素佈局),那麼就可以使得元素剛好到達下面位置。就可以通過其它元素將父級撐起來,當父級剛好撐到下方位置時,就可以將浮動清除掉。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>清楚浮動</title>
<style>
.container{
background: red;
width: 400px;
}
.p1{
background: pink;
float: left;
width: 200px;
height: 50px;
}
.removeFloat::after{
content: 'aaa';
clear: both; /*保證當前元素左右沒有浮動元素*/
display: block;
height: 0;
visibility: hidden;
}
</style>
</head>
<body>
<div class="container removeFloat">
<span>xxxxxx</span>
<span class="p1">float</span>
<span class="p1">float</span>
</div>
<div class="container" style="height: 200px; background: blue;">
<p>第一行</p>
<p>第二行</p>
<p>第三行</p>
</div>
</body>
</html>
經典清除浮動方式,效果圖如下:
float(聖盃佈局)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>聖盃佈局-float</title>
<style>
.container{
min-height: 200px;
}
.left{
float: left;
background: red;
width: 200px;
}
.center{
margin-left: 200px;
margin-right: 200px;
background: yellow;
}
.right{
float: right;
background: blue;
width: 200px;
}
</style>
</head>
<body>
<div class="container">
<div class="left">left</div>
<div class="right">right</div>
<div class="center">center</div>
</div>
</body>
</html>
展示效果如下:
inline-block 佈局
- 像文本一樣排block元素
- 沒有清楚浮動等問題
- 需要處理間隙
例如下圖,紅藍之間有一個間隙,是因爲 inline-block
就像文本一樣,我們沒辦法讓兩個字緊緊地挨着,於是我們就有了下文所述解決方式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>inline-block佈局</title>
<style>
.container{
width: 800px;
height: 200px;
font-size: 0;
}
.left{
font-size: 15px;
background: red;
display: inline-block;
width: 200px;
height: 200px;
}
.right{
font-size: 15px;
background: blue;
display: inline-block;
width: 500px;
height: 200px;
}
</style>
</head>
<body>
<div class="container">
<div class="left">left</div>
<div class="right">right</div>
</div>
</body>
</html>
展示效果如下:
查看上述代碼,將父級元素字體大小設置爲0即可解決間隙問題,但子元素需要設置自己的字體大小,不然就不會顯示。
因此,做自適應方面會有點麻煩,不像上文 float+margin
那樣簡單
響應式設計和佈局
- 在不同的設備上正常使用
- 一般處理屏幕大小問題
- 主要方法:隱藏 + 折行 + 自適應空間(rem:通過html的字體大小(即
font-size
)來確定元素大小,但不太精確 / viewport:通過 js或手工 確定整個界面放到多大 / media query:媒體查詢,根據不同的設備來匹配不同的樣式)
下圖含義就是只有在寬度小於 640px 時纔會生效,即讓移動端進行適配。
CSS 面試真題
實現兩欄(三欄)佈局的方法
- 表格佈局
- float + margin 佈局(兼容性好)
- inline-block 佈局(需要處理間隙問題)
- flexbox佈局(簡單,但兼容性不是很好)
position:absolute / fixed 有什麼區別?
經典問題:
-
絕對定位
absolute
,會優先查找父級定位爲absolute
或relative
的進行定位,如果父級沒有,找上級,那麼最終就會根據body
進行定位,它和fixed
一樣,也是脫離了文檔流。 -
fixed
相對於屏幕(viewport)進行定位
層疊問題 ,因爲默認會根據先後順序顯示,因此會有覆蓋情況,此時,可以通過設計 z-index
解決,權重越大,優先顯示。
display:inline-block 的間隙
- 原因:字符間距
- 解決:消滅字符(把標籤寫在一起或者添加註釋)或者消滅間距(將
font-size
設爲0)
如何清除浮動?爲什麼要清除浮動?
原因:浮動的元素不會佔據父元素的佈局空間,也就是父級元素不會管浮動元素,有可能浮動元素會超出父元素,從而對其它元素產生影響。
經典問題:
清除浮動的方式
① 當我們設置爲 float 後,會將元素設爲 BFC,接管自己的寬高,因此我們也可以讓父級元素設置爲 BFC,來接管自己的寬高。
初始狀態:
在父級元素設置 overflow: auto/hidden;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>清楚浮動</title>
<style>
.container{
background: red;
width: 400px;
overflow: auto;
margin: 10px;
}
.p1{
background: pink;
float: left;
width: 200px;
height: 50px;
}
</style>
</head>
<body>
<div class="container">
<span>xxxxxx</span>
<span class="p1">float</span>
<span class="p1">float</span>
</div>
<div class="container" style="height: 200px; background: blue;">
<p>第一行</p>
<p>第二行</p>
<p>第三行</p>
</div>
</body>
</html>
最終狀態效果圖如下:
② 由於 float 不脫離文檔流(不會影響其它元素佈局),那麼就可以使得元素剛好到達下面位置。就可以通過其它元素將父級撐起來,當父級剛好撐到下方位置時,就可以將浮動清除掉。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>清楚浮動</title>
<style>
.container{
background: red;
width: 400px;
}
.p1{
background: pink;
float: left;
width: 200px;
height: 50px;
}
.removeFloat::after{
content: 'aaa';
clear: both; /*保證當前元素左右沒有浮動元素*/
display: block;
height: 0;
visibility: hidden;
}
</style>
</head>
<body>
<div class="container removeFloat">
<span>xxxxxx</span>
<span class="p1">float</span>
<span class="p1">float</span>
</div>
<div class="container" style="height: 200px; background: blue;">
<p>第一行</p>
<p>第二行</p>
<p>第三行</p>
</div>
</body>
</html>
經典清除浮動方式,效果圖如下:
如何適配移動端頁面?
主要方法:隱藏 + 折行 + 自適應空間(rem:通過html的字體大小(即 font-size
)來確定元素大小,但不太精確 / viewport:通過 js或手工 確定整個界面放到多大 / media query:媒體查詢,根據不同的設備來匹配不同的樣式)
效果屬性(CSS最出彩的一部分)
box-shadow
屬性值介紹:前兩個是偏移量,第三個是模糊區域度,第四個是拓展區域度,第五個是顏色(最後一個是透明度)
box-shadow: 5px 5px 10px 0 rgba(0, 0, 0, .2);
text-shadow
- 立體感
- 印刷品質感
border-radius
- 圓角矩形
- 圓形
- 半圓 / 扇形
- 一些奇怪的角角
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>border-radius</title>
<style>
.container{
width: 100px;
height: 100px;
background: red;
border-radius: 50%;
}
</style>
</head>
<body>
<div class="container"></div>
</body>
</html>
展示效果如下:
background
- 紋理、圖案
- 漸變
- 雪碧圖動畫
- 背景圖尺寸適應
clip-path
- 對容器進行裁剪
- 常見幾何圖形
- 自定義路徑
3D-transform
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D-transform</title>
<style>
.container{
margin: 50px;
padding: 10px;
border: 1px solid red;
width: 200px;
height: 200px;
position: relative;
perspective: 500px;
}
#cube{
width: 200px;
height: 200px;
transform-style: preserve-3d;
transform: translateZ(-100px);
transition: transform 1s;
}
#cube:hover{
transform: translateZ(-100px) rotateX(90deg) rotateY(90deg);
}
#cube div{
width: 200px;
height: 200px;
position: absolute;
line-height: 200px;
font-size: 50px;
text-align: center;
}
.front{
background: rgba(255, 0, 0, .3);
transform: translateZ(100px);
}
.back{
background: rgba(0, 255, 0, .3);
transform: translateZ(-100px) rotateY(180deg);
}
.left{
background: rgba(0, 0, 255, .3);
transform: translateX(-100px) rotateY(-90deg);
}
.right{
background: rgba(255, 255, 0, .3);
transform: translateX(100px) rotateY(90deg);
}
.top{
background: rgba(255, 0, 255, .3);
transform: translateY(-100px) rotateX(-90deg);
}
.bottom{
background: rgba(0, 255, 255, .3);
transform: translateY(100px) rotateX(90deg);
}
</style>
</head>
<body>
<div class="container">
<div id="cube">
<div class="front">1</div>
<div class="back">2</div>
<div class="right">3</div>
<div class="left">4</div>
<div class="top">5</div>
<div class="bottom">6</div>
</div>
</div>
</body>
</html>
展示效果圖如下:
CSS 面試真題
如何用div畫一個 xxx
- box-shadow 無限投影
- ::before
- ::after
如何產生不佔空間的邊框
- box-shadow
- outline
如何實現圓形元素(頭像)
- border-radius:50%
如何實現iOS圖標的圓角
- clip-path:(svg)
如何實現半圓、扇形等圖形
- border-radius 組合:有無邊框、邊框粗細、圓角半徑
如何實現背景圖居中顯示 / 不重複 / 改變大小
- background-position
- background-repeat
- background-size(cover / contain)
如何平移 / 放大一個元素
- transform:translateX(100px)
- transform:scale(2)
- transform本身與動畫沒有關係
如何實現3D效果
- perspective:500px(指定透視角度)
- transform-style:preserve-3d;(3d效果)
- transform:translate rotate …
CSS 動畫
動畫的原理
- 視覺暫留作用:就是說看到的畫面,會在腦海中保留一段片段
- 畫面逐漸變化
動畫的作用
- 愉悅感
- 引起注意
- 反饋(輸入密碼錯誤時,登錄框晃動)
- 掩飾
CSS中動畫的類型
- transition 補間動畫(從一個狀態到另一個狀態,狀態切換之間是有動畫的)
- keyframe 關鍵幀動畫(指定的每一個狀態就是一個關鍵幀)
- 逐幀動畫(跳動)
transition 補間動畫
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>transition補間動畫</title>
<style>
.container{
width: 100px;
height: 100px;
background: red;
transition: width 1s, background 2s;
}
.container:hover{
width: 300px;
background: blue;
}
</style>
</head>
<body>
<div class="container"></div>
</body>
</html>
展示效果如下:
動畫進度與時間的關係
例子:
推薦:動畫進度與時間關係模擬網站
關鍵幀動畫
- 相當於多個補間動畫
- 與元素狀態的變化無關
- 定義更加靈活
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>keyframe關鍵幀動畫</title>
<style>
.container{
width: 100px;
height: 100px;
background: red;
animation: run 1s;
animation-direction: reverse;
animation-iteration-count: infinite;
/*animation-fill-mode: forwards;*/
/*animation-play-state: paused;*/
}
@keyframes run {
0%{
width: 100px;
}
100%{
width: 800px;
}
}
</style>
</head>
<body>
<div class="container"></div>
</body>
</html>
展示效果:
逐幀動畫
- 屬於關鍵幀動畫特殊的一種
- 適用於無法補間計算的動畫
- 資源較大
- 使用 steps() (設置關鍵幀之間有幾個畫面,一般設置爲1,也可以說是將關鍵幀去掉補間)
例如:一個動物跑動的過程,通過將每個動作的圖片逐幀顯示,形成動畫的感覺。
CSS 面試真題
CSS 動畫的實現方式有幾種
- transition
- keyframes(animation)
過渡動畫和關鍵幀動畫的區別
- 過渡動畫需要有狀態變化
- 關鍵幀動畫不需要狀態變化
- 關鍵幀動畫能控制更精細
如何實現逐幀動畫
- 使用關鍵幀動畫
- 去掉補間(steps)
CSS動畫的性能
- 性能不壞
- 部分情況下優於JS
- 但JS可以做的更好
- 部分高危屬性(例如
box-shadow
等)
CSS 預處理器
- 基於CSS的另一種語言
- 通過工具編譯爲CSS
- 添加了很多CSS不具備的特性
- 能提升CSS文件的組織
常見的有 less
(基於node寫的,編譯比較快,入門簡單)和 sass
(基於Ruby
寫的)
- 嵌套 反映層級和約束
- 變量和計算 減少重重複代碼
- Extend 和 Mxxin 代碼片段
- 循環 適用於複雜有規律的樣式
- import CSS 文件模塊化
less嵌套
全局安裝 less
npm install less -g
創建一個 test.less
文件
body{
padding: 0;
margin: 0;
}
.wrapper{
background: white;
.nav{
font-size: 12px;
}
.content{
font-size: 14px;
&:hover{
background: red;
}
}
}
在該文件處調用終端,執行以下命令:
lessc test.less
輸出結果:
執行如下命令,輸出到 test.css
文件中
lessc test.less > test.css
查看 test.css
文件,得到如下結果:
body {
padding: 0;
margin: 0;
}
.wrapper {
background: white;
}
.wrapper .nav {
font-size: 12px;
}
.wrapper .content {
font-size: 14px;
}
.wrapper .content:hover {
background: red;
}
sass嵌套
全局安裝 sass
cnpm install node-sass -g
創建一個 test.scss
文件
body{
padding: 0;
margin: 0;
}
.wrapper{
background: white;
.nav{
font-size: 12px;
}
.content{
font-size: 14px;
&:hover{
background: red;
}
}
}
執行如下命令,查看輸出結果:
node-sass test.scss
執行如下命令,輸出到 test-scss.css
文件中
node-sass test.scss > test-scss.css
查看 test-scss.css
文件,得到如下結果:
body {
padding: 0;
margin: 0; }
.wrapper {
background: white; }
.wrapper .nav {
font-size: 12px; }
.wrapper .content {
font-size: 14px; }
.wrapper .content:hover {
background: red; }
從以上代碼來看,sass嵌套會保留原來嵌套樣式,對於css觀賞性來說,並不是我們特別想要的,於是我們可以執行如下命令,更改輸出樣式:
node-sass --output-style expanded test.scss > test-scss.css
輸出結果就和less嵌套一樣了,讀者可以自己跑一遍!
less變量
創建 variable-less.less
文件
@fontSize: 12px;
@bgColor: red;
body{
padding: 0;
margin: 0;
}
.wrapper{
background: lighten(@bgColor,40%);
.nav{
font-size: @fontSize;
}
.content{
font-size: @fontSize+2px;
&:hover{
background: @bgColor;
}
}
}
創建 variable-less.css
文件,執行如下命令:
lessc variable-less.less > variable-less.css
可以得到如下代碼:
body {
padding: 0;
margin: 0;
}
.wrapper {
background: #ffcccc;
}
.wrapper .nav {
font-size: 12px;
}
.wrapper .content {
font-size: 14px;
}
.wrapper .content:hover {
background: red;
}
sass變量
類似less變量,只需要將 @
改爲 $
即可,因爲 less
變量命名這樣做,是更貼近CSS。而 sass
是爲了區別CSS。
less mixin
創建 mixin.less
文件,複製如下代碼:
@fontSize: 12px;
@bgColor: red;
.block(@fontSize){
font-size: @fontSize;
border: 1px solid #ccc;
border-radius: 4px;
}
body{
padding: 0;
margin: 0;
}
.wrapper{
background: lighten(@bgColor,40%);
.nav{
.block(@fontSize);
}
.content{
.block(@fontSize+2px);
&:hover{
background: @bgColor;
}
}
}
創建 mixin-less.css
文件,執行如下代碼:
lessc mixin.less > mixin-less.css
查看mixin-less.css
文件,發現 .block
沒有了,在CSS內部就完成了樣式複用。
body {
padding: 0;
margin: 0;
}
.wrapper {
background: #ffcccc;
}
.wrapper .nav {
font-size: 12px;
border: 1px solid #ccc;
border-radius: 4px;
}
.wrapper .content {
font-size: 14px;
border: 1px solid #ccc;
border-radius: 4px;
}
.wrapper .content:hover {
background: red;
}
sass mixin
創建 mixin.scss
文件,複製如下代碼:
$fontSize: 12px;
$bgColor: red;
@mixin block($fontSize){
font-size: $fontSize;
border: 1px solid #ccc;
border-radius: 4px;
}
body{
padding: 0;
margin: 0;
}
.wrapper{
background: lighten($bgColor,40%);
.nav{
@include block($fontSize);
}
.content{
@include block($fontSize+2px);
&:hover{
background: $bgColor;
}
}
}
創建 mixin-sass.css
文件,執行如下代碼:
node-sass --output-style expanded mixin.scss > mixin-sass.css
查看mixin-sass.css
文件,發現 .block
沒有了,在CSS內部就完成了樣式複用。
body {
padding: 0;
margin: 0;
}
.wrapper {
background: #ffcccc;
}
.wrapper .nav {
font-size: 12px;
border: 1px solid #ccc;
border-radius: 4px;
}
.wrapper .content {
font-size: 14px;
border: 1px solid #ccc;
border-radius: 4px;
}
.wrapper .content:hover {
background: red;
}
總結:從上文對比來看,sass mixin 除了調用變量符號要換爲 $
外,抽離公共樣式需要使用 @mixin
,此外,調用時還需要使用 @include
。
那麼,mixin還能做什麼呢?
例如,對於佈局方面,我們在上文提到了清楚浮動的方式,那麼,我們就可以將這段樣式進行復用,只需要在需要的元素處引用即可。
less extend
上文提到過的,使用過 less mixin 抽離之後,我們可以得到如下代碼,但是呢,又會有一個小問題,就是我們會有重複樣式代碼。在生產環境下,就會有大量這樣的形式出現,這就會影響到我們的CSS體積了。
一種比較好的方式,如下,我們再講公共樣式代碼進行抽離,這顯然會降低我們的CSS體積。
因此,extend就發揮了它的作用
創建 extend-less.less
文件,複製如下代碼:
@fontSize: 12px;
@bgColor: red;
.block{
font-size: @fontSize;
border: 1px solid #ccc;
border-radius: 4px;
}
body{
padding: 0;
margin: 0;
}
.wrapper{
background: lighten(@bgColor,40%);
.nav{
&:extend(.block);
}
.content:extend(.block){
&:hover{
background: @bgColor;
}
}
}
創建 extend-less.css
文件,執行如下代碼:
lessc extend-less.less > extend-less.css
查看 extend-less.css
文件,發現代碼體積相對減少了。
.block,
.wrapper .nav,
.wrapper .content {
font-size: 12px;
border: 1px solid #ccc;
border-radius: 4px;
}
body {
padding: 0;
margin: 0;
}
.wrapper {
background: #ffcccc;
}
.wrapper .content:hover {
background: red;
}
總結:mixin 和 extend 區別, mixin 能處理一些複雜邏輯,比如添加變量,但會導致體積增大問題。而 extend的話,是將選擇器提取出來,更加簡單,不適合處理複雜邏輯,能將體積進行一定減少。
sass extend
創建 extend-sass.scss
文件,複製如下代碼:
$fontSize: 12px;
$bgColor: red;
.block{
font-size: $fontSize;
border: 1px solid #ccc;
border-radius: 4px;
}
body{
padding: 0;
margin: 0;
}
.wrapper{
background: lighten($bgColor,40%);
.nav{
@extend .block;
}
.content{
@extend .block;
&:hover{
background: $bgColor;
}
}
}
創建 extend-sass.css
文件,執行如下代碼:
node-sass --output-style expanded extend-sass.scss > extend-sass.css
查看 extend-sass.css
文件,發現代碼體積相對減少了。
.block, .wrapper .nav, .wrapper .content {
font-size: 12px;
border: 1px solid #ccc;
border-radius: 4px;
}
body {
padding: 0;
margin: 0;
}
.wrapper {
background: #ffcccc;
}
.wrapper .content:hover {
background: red;
}
less loop
創建 loop-less.less
文件,複製如下代碼
.gen-col(@n) when (@n > 0){
.gen-col(@n - 1);
.col-@{n}{
width: 1000px/12*@n;
}
}
.gen-col(12);
創建 loop-less.css
文件,執行如下代碼:
lessc loop-less.less > loop-less.css
查看 loop-less.css
文件,發現有12個樣式
.col-1 {
width: 83.33333333px;
}
.col-2 {
width: 166.66666667px;
}
.col-3 {
width: 250px;
}
.col-4 {
width: 333.33333333px;
}
.col-5 {
width: 416.66666667px;
}
.col-6 {
width: 500px;
}
.col-7 {
width: 583.33333333px;
}
.col-8 {
width: 666.66666667px;
}
.col-9 {
width: 750px;
}
.col-10 {
width: 833.33333333px;
}
.col-11 {
width: 916.66666667px;
}
.col-12 {
width: 1000px;
}
sass loop
創建 loop-sass.scss
文件,複製如下代碼:
@mixin gen-col($n){
@if $n > 0 {
@include gen-col($n - 1);
.col-#{$n}{
width: 1000px/12*$n;
}
}
}
@include gen-col(12);
創建 loop-sass.css
,執行如下代碼:
node-sass --output-style expanded loop-sass.scss > loop-sass.css
查看 loop-sass.css
文件,發現有12個樣式
.col-1 {
width: 83.33333px;
}
.col-2 {
width: 166.66667px;
}
.col-3 {
width: 250px;
}
.col-4 {
width: 333.33333px;
}
.col-5 {
width: 416.66667px;
}
.col-6 {
width: 500px;
}
.col-7 {
width: 583.33333px;
}
.col-8 {
width: 666.66667px;
}
.col-9 {
width: 750px;
}
.col-10 {
width: 833.33333px;
}
.col-11 {
width: 916.66667px;
}
.col-12 {
width: 1000px;
}
上述版本代碼或許是挺複雜的,好在 sass
提供了for循環,見如下代碼:
@for $i from 1 through 12 {
.col-#{$i} {
width: 1000px/12*$i;
}
}
less import
創建 import-less.less
文件,複製如下代碼:
@import "./mixin";
@import "./variable-less";
創建 import-less.css
文件,執行如下代碼:
lessc import-less.less > import-less.css
查看 import-less.less
文件
body {
padding: 0;
margin: 0;
}
.wrapper {
background: #ffcccc;
}
.wrapper .nav {
font-size: 12px;
border: 1px solid #ccc;
border-radius: 4px;
}
.wrapper .content {
font-size: 14px;
border: 1px solid #ccc;
border-radius: 4px;
}
.wrapper .content:hover {
background: red;
}
body {
padding: 0;
margin: 0;
}
.wrapper {
background: #ffcccc;
}
.wrapper .nav {
font-size: 12px;
}
.wrapper .content {
font-size: 14px;
}
.wrapper .content:hover {
background: red;
}
sass import
語法上沒有什麼變化,注意符號是 $
CSS預處理器框架
- Less - Lesshat / EST(官網)
- SASS - Compass (官網,將有兼容性問題的屬性會進行封裝成mixin,直接調用就好)
- 提供現成的 mixin
- 類似 JS 類庫 封裝常用功能
CSS 面試真題
常見的CSS預處理器
- Less(Node.js)
- Sass(Ruby 有Node版本)
預處理器的作用
- 幫助更好地組織CSS代碼
- 提高代碼複用率
- 提升可維護性
預處理器的能力
- 嵌套 反映層級和約束
- 變量和計算 減少重重複代碼
- Extend 和 Mxxin 代碼片段
- 循環 適用於複雜有規律的樣式(網格系統)
- import CSS 文件模塊化(按需拆解CSS文件)
預處理器的優缺點
- 優點:提高代碼複用率和可維護性
- 缺點:需要引入編譯過程 有學習成本
Bootstrap
- 一個CSS框架
- twitter 出品
- 提供通用基礎樣式
Bootstrap 4
- 兼容IE10+
- 使用flexbox佈局
- 拋棄Nomalize.css
- 提供佈局 和 reboot版本
- (官網,用sass寫)
- 可用於後臺管理系統
Bootstrap JS組件
用於組件交互
- dropdown(下拉)
- modal(彈窗)
- …
基於jquery寫的,同時,依賴第三方庫 Popper.js和 bootstrap.js
如上圖,第二個js文件包含了 Popper.js
使用方式:
- 基於 data-*屬性
- 基於 JS API
Bootstrap 響應式佈局
非常精華的部分
Bootstrap 定製方法
- 使用CSS同名類覆蓋(操作簡單但)
- 修改sass源碼重新構建
- 引用scss源文件 修改變量(推薦使用,乾淨)
CSS 面試真題
Bootstrap的優缺點
- 優點:CSS代碼結構合理,現成的樣式可以直接使用
- 缺點:定製較爲繁瑣 體積大
Bootstrap如何實現響應式佈局
- 原理:通過 media query 設置不同分辨率的class
- 使用:爲不同分辨率選擇不同的網格class
如何基於Bootstrap 定製自己的樣式
- 使用CSS同名類覆蓋(操作簡單但)
- 修改sass源碼重新構建(需要了解Bootstrap 結構)
- 引用scss源文件 修改變量(按需使用,控制體積,推薦使用,乾淨,但需要了解結構)
CSS 工程化
關注幾個事情:組織、優化、構建、維護
PostCSS
- 將 CSS 解析成 CSS,和預處理器沒太多區別。
- 本身只有解析能力
- 各種神奇的特性全靠插件
- 目前至少有200多個插件
常見:
- import 模塊合併
- autoprefixer 自動加前綴
- cssnano 壓縮代碼
- cssnext 使用CSS新特性
- precss 變量、mixin、循環等
PostCSS插件的使用
全局安裝 postcss-cli
npm install postcss-cli -g
在 postcss.config.js
文件進行配置
cssnext
precss
- 變量(使用和 sass 幾乎一樣)
- 條件(if)
- 循環
- Mixin Extend
- import
- 屬性值引用
gulp-postcss
PostCSS 支持的構建工具
- CLI命令行工具
- webpack postcss-loader
- Gulp gulp-postcss
- Grunt grunt-postcss
- Rollup rollup-postcss
- …
webpack
- JS是整個應用的核心入口
- 一切資源均由JS管理依賴
- 一切資源均由webpack打包
webpack 和 CSS
- css-loader 將 CSS變爲 JS
- style-loader 將JS插入到head
- ExtractTextPlugin 將 CSS 從 JS 中 提取出來
- CSS modules 解決 CSS命名衝突的問題
- less-loader sass-loader 各類預處理器
- postcss-loader PostCSS處理
CSS 面試真題
如何解決CSS模塊化問題
- less sass 等CSS預處理器
- PostCSS插件(postcss-import / precss等)
- webpackl處理CSS(css-loader + style-loader)
PostCSS可以做什麼?
- 取決於插件做什麼
- autoprefixer cssnext precss等 兼容性處理
- import 模塊合併
- css語法檢查 兼容性檢查
- cssnano 壓縮文件
CSS modules是做什麼的,如何使用
- 解決類名衝突的問題
- 使用PostCSS或者webpack等構建工具進行編譯
- 在HTML模板中使用編譯過程產生的類名
爲什麼使用JS來引用、加載CSS
- JS作爲入口,管理資源有天然優勢
- 將組件的結構、樣式、行爲封裝到一起,增強內聚
- 可以做更多處理(webpack)
結尾
話說,我有女朋友嗎?我有嗎?原來我沒有…
扯開女朋友話題,終於完成了這篇史詩級大作,時隔幾天時間。更多筆記內容還請關注 小獅子前端筆記倉庫 (不要白嫖,給個 star ✿✿ヽ(°▽°)ノ✿ 就是對我最大的支持啦~)
學如逆水行舟,不進則退