快速掌握 Tailwind:最流行的原子化 CSS 框架
Tailwind 是流行的原子化 css 框架。
大廠技術(shù) 高級(jí)前端 精選文章
點(diǎn)擊上方 全站前端精選,關(guān)注公眾號(hào)
回復(fù)1,加入高級(jí)前段交流
有多流行呢?
它現(xiàn)在有 68k star 了,要知道 express 才 60k:
那什么是原子化 css?
我們平時(shí)寫(xiě) css 是這樣的:
<div class="aaa"></div>
.aaa {
font-size: 16px;
border: 1px solid #000;
padding: 4px;
}
在 html 里指定 class,然后在 css 里定義這個(gè) class 的樣式。
也就是 class 里包含多個(gè)樣式:
而原子化 css 是這樣的寫(xiě)法:
<div class="text-base p-1 border border-black border-solid"></div>
.text-base {
font-size: 16px;
}
.p-1 {
padding: 4px;
}
.border {
border-width: 1px;
}
.border-black {
border-color: black;
}
.border-solid {
border-style: solid;
}
定義一些細(xì)粒度的 class,叫做原子 class,然后在 html 里直接引入這些原子化的 class。
這個(gè)原子化 css 的概念還是很好理解的,但它到底有啥好處呢? 它解決了什么問(wèn)題?
口說(shuō)無(wú)憑,我們?cè)囅?tailwind 就知道了,它就是一個(gè)提供了很多原子 class 的 css 框架。
我們通過(guò) crerate-react-app 創(chuàng)建一個(gè) react 項(xiàng)目:
npx create-react-app tailwind-test
然后進(jìn)入 tailwind-test 目錄,執(zhí)行
npm install -D tailwindcss
npx tailwindcss init
安裝 tailwindcss 依賴(lài),創(chuàng)建 tailwindcss 配置文件。
tailwind 實(shí)際上是一個(gè) postcss 插件,因?yàn)?cra 內(nèi)部已經(jīng)做了 postcss 集成 tailwind 插件的配置,這一步就不用做了:
然后在入口 css 里加上這三行代碼:
這三行分別是引入 tailwind 的基礎(chǔ)樣式、組件樣式、工具樣式的。
之后就可以在組件里用 tailwind 提供的 class 了:
import './App.css';
function App() {
return (
<div className='text-base p-1 border border-black border-solid'>guang</div>
);
}
export default App;
我們執(zhí)行 npm run start 把開(kāi)發(fā)服務(wù)跑起來(lái)。
可以看到,它正確的加上了樣式:
用到的這些原子 class 就是 tailwind 提供的:
這里的 p-1 是 padding:0.25rem,你也可以在配置文件里修改它的值:
在 tailwind.config.js 的 theme.extend 修改 p-1 的值,設(shè)置為 30px。
刷新頁(yè)面,就可以看到 p-1 的樣式變了:
.text-base 是 font-size、line-height 兩個(gè)樣式,這種通過(guò)數(shù)組配置:
也就是說(shuō)所有 tailwind 提供的所有內(nèi)置原子 class 都可以配置。
但這些都是全局的更改,有的時(shí)候你想臨時(shí)設(shè)置一些值,可以用 [] 語(yǔ)法。
比如 text-[14px],它就會(huì)生成 font-size:14px 的樣式:
比如 aspect-[4/3],就是這樣的樣式:
我們平時(shí)經(jīng)常指定 hover 時(shí)的樣式,在 tailwind 里怎么指定呢?
很簡(jiǎn)單,這樣寫(xiě):
生成的就是帶狀態(tài)的 class:
此外,寫(xiě)響應(yīng)式的頁(yè)面的時(shí)候,我們要指定什么寬度的時(shí)候用什么樣式,這個(gè)用 tailwind 怎么寫(xiě)呢?
也是一樣的寫(xiě)法:
生成的是這樣的代碼:
這個(gè)斷點(diǎn)位置自然也是可以配置的:
可以看到 md 斷點(diǎn)對(duì)應(yīng)的寬度變了:
光這些就很方便了。
之前要這么寫(xiě):
<div class="aaa"></div>
.aaa {
background: red;
font-size: 16px;
}
.aaa:hover {
font-size: 30px;
}
@media(min-width:768px) {
.aaa {
background: blue;
}
}
現(xiàn)在只需要這樣:
<div class="text-[14px] bg-red-500 hover:text-[30px] md:bg-blue-500"></div>
省去了很多樣板代碼,還省掉了 class 的命名。
并且這些 class 都可以通過(guò)配置來(lái)統(tǒng)一修改。
感受到原子化 css 的好處了么?
tailwind 文檔提到了 3 個(gè)好處:
不用起 class 名字,這點(diǎn)簡(jiǎn)直太爽了,我就經(jīng)常被起 class 名字折磨。
css 不會(huì)一直增長(zhǎng),因?yàn)槿绻阌弥暗膶?xiě)法可能是這樣的:
多個(gè) class 里都包含了類(lèi)似的樣式,但你需要寫(xiě)多次,而如果用了原子 class,就只需要定義一次就好了。
css 沒(méi)有模塊作用域,所以可能你在這里加了一個(gè)樣式,結(jié)果別的地方樣式錯(cuò)亂了。
而用原子 class 就沒(méi)這種問(wèn)題,因?yàn)闃邮绞侵皇亲饔迷谀硞€(gè) html 標(biāo)簽的。
我覺(jué)得光這三點(diǎn)好處就能夠說(shuō)服我用它了,特別是不用起 class 名字這點(diǎn)。
當(dāng)然,社區(qū)也有一些反對(duì)的聲音,我們來(lái)看看他們是怎么說(shuō)的:
一堆 class,可讀性、可維護(hù)性太差了
真的么?
這種把 css 寫(xiě)在 html 里的方式應(yīng)該是更高效才對(duì)。
想想為啥 vue 要?jiǎng)?chuàng)造個(gè)單文件組件的語(yǔ)法,把 js、css、template 放在一個(gè)文件里寫(xiě),不就是為了緊湊么?
之前你要在 css、js 文件里反復(fù)跳來(lái)跳去的,查找某個(gè) class 的樣式是啥,現(xiàn)在不用這么跳了,直接在 html 里寫(xiě)原子樣式,它不香么?
而且 tailwindcss 就前面提到的那么幾個(gè)語(yǔ)法,沒(méi)啥學(xué)習(xí)成本,很容易看懂才對(duì)。
但是還要每次去查文檔哪些 class 對(duì)應(yīng)什么樣式呀
這個(gè)可以用 tailwind css 提供的 vscode 插件來(lái)解決:
安裝這個(gè) Tailwind CSS IntelliSense 之后的體驗(yàn)是這樣的:
有智能提示,可以查看它對(duì)應(yīng)的樣式。
不需要記。
難以調(diào)試
在 chrome devtools 里可以直接看到有啥樣式,而且樣式之間基本沒(méi)有交叉,很容易調(diào)試:
相反,我倒是覺(jué)得之前那種寫(xiě)法容易多個(gè) class 的樣式相互覆蓋,還要確定優(yōu)先級(jí)和順序,那個(gè)更難調(diào)試才對(duì):
類(lèi)型太長(zhǎng)了而且重復(fù)多次
這種問(wèn)題可以用 @layer @apply 指令來(lái)擴(kuò)展:
前面講過(guò) @tailwind 是引入不同的樣式的,而 @layer 就是在某一層樣式做修改和擴(kuò)充,里面可以用 @apply 應(yīng)用其他樣式。
效果是這樣的:
內(nèi)置 class 不能滿(mǎn)足我的需求
其實(shí)上面那個(gè) @layer 和 @apply 就能擴(kuò)展內(nèi)置原子 class。
但如果你想跨項(xiàng)目復(fù)用,那可以開(kāi)發(fā)個(gè) tailwind 插件
const plugin = require('tailwindcss/plugin');
module.exports = plugin(function({ addUtilities }) {
addUtilities({
'.guang': {
background: 'blue',
color: 'yellow'
},
'.guangguang': {
'font-size': '70px'
}
})
})
在 tailwind.config.js 里引入:
這樣就可以用這個(gè)新加的原子 class 了:
插件的方式或者 @layer 的方式都可以擴(kuò)展。
tailwind 的 class 名和我已有的 class 沖突了咋辦?
比如我本來(lái)有個(gè) border 的 class:
而 tailwind 也有,不就沖突了么?
這個(gè)可以通過(guò)加 prefix 解決:
不過(guò)這樣所有的原子 class 都得加 prefix 了:
知道了什么是原子 css 以及 tailwind 的用法之后,我們?cè)賮?lái)看看它的實(shí)現(xiàn)原理。
tailwind 可以單獨(dú)跑,也可以作為 postcss 插件來(lái)跑。這是因?yàn)槿绻麊为?dú)跑的話,它也會(huì)跑起 postcss,然后應(yīng)用 tailwind 的插件:
所以說(shuō),tailwind 本質(zhì)上就是個(gè) postcss 插件。
postcss 是一個(gè) css 編譯器,它是 parse、transform、generate 的流程。
在 astexplorer.net 可以看到 postcss 的 AST:
而 postcss 就是通過(guò) AST 來(lái)拿到 @tailwind、@layer、@apply 這些它擴(kuò)展的指令,分別作相應(yīng)的處理,也就是對(duì) AST 的增刪改查。
那它是怎么掃描到 js、html 中的 className 的呢?
這是因?yàn)樗袀€(gè) extractor 的東西,用來(lái)通過(guò)正則匹配文本中的 class,之后添加到 AST 中,最終生成代碼。
extractor 的功能看下測(cè)試用例就明白了:
所以說(shuō),tailwind 就是基于 postcss 的 AST 實(shí)現(xiàn)的 css 代碼生成工具,并且做了通過(guò) extractor 提取 js、html 中 class 的功能。
tailwind 還有種叫 JIT 的編譯方式,這個(gè)原理也容易理解,本來(lái)是全部引入原子 css 然后過(guò)濾掉沒(méi)有用到的,而 JIT 的話就是根據(jù)提取到的 class 來(lái)動(dòng)態(tài)引入原子 css,更高效一點(diǎn)。
最后,為啥這個(gè) css 框架叫 tailwind 呢?
因?yàn)樽髡呦矚g叫做 kiteboarding 風(fēng)箏沖浪的運(yùn)動(dòng)。
就是這樣的,一個(gè)風(fēng)箏,一個(gè)沖浪板:
這種運(yùn)動(dòng)在順風(fēng) tailwind 和逆風(fēng) headwind 下有不同的技巧。而 tailwind 的時(shí)候明顯更加省力。
所以就給這個(gè) css 框架起名叫 tailwind 了。
確實(shí),我也覺(jué)得用這種方式來(lái)寫(xiě) css 更加省力、高效,不用寫(xiě) class 名字了,代碼更簡(jiǎn)潔了,還不容易樣式?jīng)_突了。
總結(jié)
tailwind 是一個(gè)流行的原子化 css 框架。
傳統(tǒng) css 寫(xiě)法是定義 class,然后在 class 內(nèi)部寫(xiě)樣式,而原子化 css 是預(yù)定義一些細(xì)粒度 class,通過(guò)組合 class 的方式完成樣式編寫(xiě)。
tailwind 用起來(lái)很簡(jiǎn)單:
所有預(yù)定義的 class 都可以通過(guò)配置文件修改值,也可以通過(guò) aaa-[14px] 的方式定義任意值的 class。
所有 class 都可以通過(guò) hover:xxx、md:xxx 的方式來(lái)添加某個(gè)狀態(tài)下的樣式,響應(yīng)式的樣式,相比傳統(tǒng)的寫(xiě)法簡(jiǎn)潔太多了。
它的優(yōu)點(diǎn)有很多,我個(gè)人最喜歡的就是不用起 class 的名字了,而且避免了同樣的樣式在多個(gè) class 里定義多次導(dǎo)致代碼重復(fù),并且局部作用于某個(gè)標(biāo)簽,避免了全局污染。
它可以通過(guò) @layer、@apply 或者插件的方式擴(kuò)展原子 class,支持 prefix 來(lái)避免 class 名字沖突。
tailwind 本質(zhì)上就是一個(gè) postcss 插件,通過(guò) AST 來(lái)分析 css 代碼,對(duì) css 做增刪改,并且可以通過(guò) extractor 提取 js、html 中的 class,之后基于這些來(lái)生成最終的 css 代碼。
是否感受到了 tailwind 的簡(jiǎn)潔高效,易于擴(kuò)展?就是這些原因讓它成為了最流行的原子化 css 框架。
前端 社群
下方加 Nealyang 好友回復(fù)「 加群」即可。
如果你覺(jué)得這篇內(nèi)容對(duì)你有幫助,我想請(qǐng)你幫我2個(gè)小忙:
1. 點(diǎn)個(gè)「在看」,讓更多人也能看到這篇文章
