為什么使用Tailwind Css框架
簡短的概括:
發(fā)現(xiàn)問題:項目中css代碼痛點
.mock {
margin: auto;
font-size: 16px;
// ...
}
<div class='mock'>mock</div>
以上代碼就是舉個例子,大部分情況應(yīng)該都是寫一個類,然后整一堆樣式進去。這種方式寫多了以后,會感受到一些痛點,比如說:
1) 取名困難,節(jié)點結(jié)構(gòu)一多,取名真的是個難事。當(dāng)然了,我們可以用一些規(guī)范或者選擇器的方式去規(guī)避一些取名問題。
2) 需要用 JS 控制樣式的時候又得多寫一個類,尤其交互多的場景。
3) 組件復(fù)用大家都懂,但是樣式復(fù)用少之又少,這樣就造成了冗余代碼變多。
4) 全局污染,這個其實現(xiàn)在挺多工具都能幫我們自動解決了。
5) 死代碼問題。JS 我們通過 tree shaking 的方式去除用不到的代碼減少文件體積,但是 CSS 該怎么去除?尤其當(dāng)項目變大以后,無用 CSS 代碼總會出現(xiàn)。
6) 樣式表的插入順序影響了 CSS 到底是如何生效的。
一、Tailwind CSS 介紹
Tailwind 能夠快速將樣式添加到 HTML 元素中,并提供了大量的開箱即用的設(shè)計樣式。
tailwindcss 基于比組件更小、更靈活的工具類思想的 CSS 框架。這個思想簡單來說就是用 class 保證靈活、便于自定義組件,而不是在組件基礎(chǔ)上實現(xiàn)個性化。
官網(wǎng):https://www.tailwindcss.cn/
如果你從來沒見過 Tailwind 的實際應(yīng)用,可以看這個:
<div class="bg-gray-100 rounded-xl p-8">Hello World</div>
這里的類名就反映了 Tailwind 的定義:一個包含多個預(yù)定義類(所謂的工具類)的集合。你并不需要編寫基礎(chǔ)的 CSS 樣式規(guī)則,只需要直接在 HTML 中應(yīng)用已經(jīng)事先定義好的類名。
這樣的類名還有很多。下面這個列表展示了部分類別和對應(yīng)的例子:
1)背景 (bg-gray-200, bg-gradient-to-bl)
2)彈性布局 (flex-1, flex-row)
3)網(wǎng)格布局 (grid-cols-1, col-span-4)
4)內(nèi)邊距 (p-0, p-1)
5)尺寸 (w-1, h-1)
開發(fā)大型應(yīng)用的時候,每一個 HTML 元素都充斥著一大堆 Tailwind 的工具類名。
<div class="sm:w-4 md:w-6 lg:w-10 xl:w-full sm:text-sm md:text-base lg:text-base xl:text-2xl flex-1 sm:flex-none bg-black sm:bg-white rounded-md sm:rounded-none">
hello world
</div>
問題:
要怎么組織這些類名呢?也許我們要創(chuàng)建并遵循某個排序規(guī)則。
解決方案:
部分 HTML 元素會使用非常多的樣式,這種情況下應(yīng)該考慮將樣式與 HTML 標(biāo)簽進行分離,單獨放到某個文件里。這樣,我們就可以組織樣式并增強其可讀性。你不能把 CSS 的所有功能”塞到“ class 這一個 HTML 標(biāo)簽屬性里,Tailwind 也不能。這樣做只會讓 HTML 結(jié)構(gòu)越發(fā)臃腫。
@apply
針對上面提到的問題,Tailwind 允許我們在單個 CSS 文件中使用它們的類名:
.header {
@apply bg-red-200 w-4 text-gray-400 rounded-sm border-2;
}
比如說項目中的按鈕都是存在通用的圓角、內(nèi)邊距、字體等,這樣我們就可以封裝出這樣一個類:
.btn {
@apply p-8 rounded-xl font-semibold;
}
二、使用 Tailwind CSS 的理由
1、超小的文件尺寸 = 令人難以置信的性能
在開發(fā)模式下,Tailwind的輸出尺寸非常大。這是設(shè)計使然:在此階段生成每個可能的類,因此當(dāng)你想要使用某些東西時,無需等待完成構(gòu)建的過程。
但是,一旦Tailwind CSS進入生產(chǎn)模式,就會清除所有未與PurgeCSS工具一起使用的類。這是通過在項目文件中搜索類的名稱來實現(xiàn)的,只保留那些使用過的。你可以在purge數(shù)組中的tailwind.config.js中配置將搜索哪些文件路徑。
// tailwind.config.js
module.exports = {
purge: [
"./src/**/*.html",
"./src/**/*.vue",
'./src/**/*.js'
],
theme: {},
variants: {},
plugins: [],
}
2、原型和快速構(gòu)建
使用常規(guī)SCSS,需要為頁面上的每個元素編寫自定義類。這樣雖然可以提供更好的控制,但編寫自定義類需要花費大量時間:你必須在HTML中添加類,然后在CSS中創(chuàng)建,再以長格式寫出每個屬性。你必須等待CSS構(gòu)建后才能看到結(jié)果——并且,如果你需要進行更多更改,則每次都需要重新構(gòu)建,這可能會花費幾秒鐘時間并中斷你的流程。
Tailwind CSS取消了這些額外的步驟,并在為元素設(shè)置樣式時提供了簡單、爽快的開發(fā)體驗??梢钥吹较胍O(shè)置樣式的元素,使用簡寫方式添加需要的屬性,不需要等待CSS文件束就能很快出現(xiàn)改變。因此只要專注于一個地方即可,不用頻繁切換到不同的文件,整個過程感覺很流暢。
<div class="bg-white rounded p-4">
<h1 class="text-24 font-heading underline">
Foobar
</h1>
<p class="text-16 font-body>
Hello world!
</p>
</div>
3、消除范圍泄漏
人們喜歡BEM以及它能在今天如此流行的原因是,命名系統(tǒng)類的構(gòu)建是為了表示組件的結(jié)構(gòu)。在使其易于閱讀和理解的同時,開發(fā)人員還受益于這種結(jié)構(gòu):由于布局易于理解,因而可以在不使用CSS選擇器的情況下編寫類。如下:
// this
.block {
&__element { ... }
&__element--modifier { ... }
}
// not this
.block {
& > .element {
&.modifier { ... }
}
}
CSS選擇器的問題在于它們給CSS帶來了復(fù)雜性:組件變得非常依賴于特定的HTML結(jié)構(gòu)。由于通用CSS類,例如.container,可以重復(fù)多次,所以使用這些名稱可能會導(dǎo)致重疊,因此更改一個類將影響許多其他的類。這是我們使用BEM的主要原因之一,因為它使得結(jié)構(gòu)清晰,并將每個類扁平化到頂級范圍,這樣就不會互相依賴。如果沒有像這樣的CSS方法,那么開發(fā)工作可能會讓人頭疼,并且其簡單性意味著其他人可以更容易地理解它。
三、Tailwindcss 為何大受歡迎
NPM.DEVTOOL 中 tailwind 標(biāo)簽大全
地址:https://npm.devtool.tech/tailwindcss
現(xiàn)在項目開發(fā)用的 TailwindCSS,在這里談一點感受,TailwindCSS 因為一個 class 代表一個 CSS 屬性這種原子化 CSS (Atomic CSS),這種細粒度的 CSS 方案備受爭議。
1、四種粒度
<div style="{ borderRadius: '0.5rem', padding: '1rem' }"> Click </div>
<div class="rounded-lg p-4"> Click </div>
<div class="button"> Click </div>
<Button> Click </Button>
越往下封裝的粒度就越大,越抽象,靈活性就越低,但是靈活性往往是和開發(fā)工作量成反比的,靈活性越高也就意味著更多的工作需要開發(fā)者自己去處理,如何平衡開發(fā)工作量與靈活度之間的關(guān)系就顯得尤為重要。
因為這涉及到css庫的選擇,其中BootStrap庫更多的是提供顆粒度3的形式,給定一個固定的樣式,開發(fā)者需要自定義樣式的話必須去重寫樣式,而tailwind則是提供顆粒度2形式的原子樣式,更多的是提供一種規(guī)范,然后將更大的自由度交由開發(fā)者,由開發(fā)者來進行樣式的組裝。
2、一些問題的解答
Tailwindcss 為啥受歡迎,無非是更好用的原子化的 CSS。在國外如火如荼,但是在國內(nèi)論壇上爭議很大,前幾天看的前端大佬博客上寫了一篇關(guān)于 Tailwindcss 的文章,但是底下評論很多了各種問題,總結(jié)一下
Q1: tailwind的寫法和行內(nèi) CSS 有何區(qū)別,不就少寫幾個字嗎?
大部分人的想法應(yīng)該是這樣的: 僅僅對于 text-center 而言,雖然提供了些許方便,但是不足以拉開差距。
如果說它僅僅是簡單的原子化 CSS,好用卻不亮眼。但是它卻不僅僅止于此。
1. 方便性: text-center、grid-cols-3
或許一個 text-center 不足以使你覺得提供了多大的方便性,但對于一個三等分的 Grid 屬性來說,一個 grid-cols-3 和 shadow 絕對方便。
.grid-cols-3 {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
2. 語義化: text-lg、text-white、ring、animate-spin`
text-lg,一個較大字體,如果設(shè)置行內(nèi)樣式,肯定有諸多麻煩的事: 我想設(shè)計一個較大的字體,那我應(yīng)該設(shè)計多大尺寸、使用什么單位。
同樣還有:
text-white: 白色的色值是哪個來著?
ring: 我想給這個按鈕加一個圈圈?
animate-spin: 怎么做一個動畫?
3. 響應(yīng)式:
先來看一個在工作中會遇到的響應(yīng)式布局問題,這也是我上一次在頭條面試時的一道題目
響應(yīng)式布局,一大堆子元素,在大屏幕三等分,中等屏幕二等分,小屏幕一等分?
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
通過 grid 布局很容易實現(xiàn),但未免繁瑣
@media (min-width: 1024px) {
.container {
grid-template-columns: repeat(3,minmax(0,1fr));
}
}
@media (min-width: 768px) {
.container {
grid-template-columns: repeat(2,minmax(0,1fr));
}
}
.conainer {
display: grid;
gap: 1rem;
}
那使用 tailwind 呢? 只要一行,就問你高效不高效。
4. 修飾符
把修飾符,如各種偽類、暗黑模式、響應(yīng)式設(shè)計至于前綴的設(shè)計簡直深得我心。
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"></div>
Q2: 既然 TailwindCSS 這么好用,那豈不是可以擺脫手寫 CSS 了
很遺憾,不能。不過雖然你無法擺脫手寫 CSS,但是你基本上也寫不了幾行,說以下幾種很常用的情況。
1. 復(fù)雜選擇器
當(dāng)父級元素鼠標(biāo)懸浮時的,子級元素的樣式控制
.container:hover .item {
}
2. CSS function
.body {
height: calc(100vh - 6rem)
}
3. 多種屬性復(fù)用
.item {
@apply p-2 border-b flex justify-between font-mono;
}
Q3: 造成新的記憶負擔(dān)
這個問題就仁者見仁智者見智了,在 Vue 的 template 語法中也經(jīng)常出現(xiàn)此類問題,很多人會對一些命名上的約定,特別是自己不太喜歡的約定天然排斥,這也無可厚非。
在初期確實會一邊開發(fā)網(wǎng)頁,一邊瞅著文檔全局搜索: TailwindCSS 屬性查找,現(xiàn)在借助瀏覽器插件及熟能生巧的經(jīng)驗已經(jīng)不太需要翻文檔了。
1. Tailwind CSS IntelliSense (vscode)
智能補全
代碼提示
初期經(jīng)?;〞r間翻文檔而不手寫 CSS,而其中的原因不外乎兩個:
1、多寫幾個字母,確實有點嫌麻煩,有這時間還不如看看文檔,全局搜索下也不費事;
2、自己設(shè)置一個 fontSize,padding、margin 實在不知道設(shè)置多少尺寸,tailwindcss 有較大的約束;
過了多久就會覺得: 嗯,真香。
四、Tailwindcss 項目實踐
原本傳統(tǒng)的寫法是定義一個類,然后寫上需要的樣式:
.class1 {
font-size: 18px;
margin: 10px;
}
.class2 {
font-size: 16px;
color: red;
margin: 10px;
}
這種寫法是存在一部分樣式重復(fù)的,換成 Atom CSS 就能減少一部分代碼的冗余。
把 CSS 當(dāng)成組件來寫。大家乍一看 tailwindcss 官網(wǎng)肯定會覺得我在 HTML 里寫個樣式要敲那么多類不好吧。
<figure class="md:flex bg-gray-100 rounded-xl p-8 md:p-0">
<img class="w-32 h-32 md:w-48 md:h-auto md:rounded-none rounded-full mx-auto" src="/sarah-dayan.jpg" alt="" width="384" height="512">
<div class="pt-6 md:p-8 text-center md:text-left space-y-4">
<blockquote>
<p class="text-lg font-semibold">
“Tailwind CSS is the only framework that I've seen scale
on large teams. It’s easy to customize, adapts to any design,
and the build size is tiny.”
</p>
</blockquote>
<figcaption class="font-medium">
<div class="text-cyan-600">
Sarah Dayan
</div>
<div class="text-gray-500">
Staff Engineer, Algolia
</div>
</figcaption>
</div>
</figure>
其實我們是可以利用 Atom CSS 一次只干一件事的特性,將這些類隨意組裝成我們想要的類,這樣就可以提供出來一個更上層的通用樣式來復(fù)用。
tailwind.confing.js 配置文件
/**
* 定制配置
* 默認配置請參考 https://unpkg.com/browse/tailwindcss@2.2.6/stubs/defaultConfig.stub.js
*/
module.exports = {
purge: [
"./src/**/*.html",
"./src/**/*.vue",
'./src/**/*.jsx'
],
theme: {
extend: {
fontFamily: {
sans: ["Inter", "Roboto", '"Segoe UI"'],
dincond: ["DINCond-Black"]
},
fontSize: {
'2.5': '0.625rem', // 10px
'3': '0.375rem', // 12px
'5.5xl': '3.25rem', // 52px
'4.5xl': '2.5rem', //40px
},
width: {
'4.5': '1.125rem', //18px
'10.5': '2.65rem', //42px
'15': '3.75rem', // 60px
'18': '4.5rem', // 74px
'18.5': '4.625rem', // 74px
'23': '5.75rem' // 92px
},
lineHeight: {
'12': '3rem', // 48px
'15': '3.875rem', // 62px
'16': '4rem', //64px
'14': '3.5rem', //56px
"18" : "4.625rem" //74px
},
padding: {
'0.5': '0.125rem', // 2px
'5.5': '1.375rem', // 22px
'4.5': '1.125rem', //18px
'0.75': '0.1875rem', //3px
'7.5': '1.875rem' //30px
},
paddingBottom:{
'4.5': '1.375rem' //22px
},
margin: {
'4.5': '1.125rem', //18px
'15': '3.75rem', // 60px
'21.25': '5.3125rem', // 85px
'11.5': '2.875rem', // 46px
'19': '4.75rem', //76px
},
marginTop: {
'6.5': '1.625rem', // 26px
},
spacing: {
'3.5': '0.875rem', // 14px
'7.5': '1.875rem', //30px
'9.5': '2.375rem', // 38px
// '15': '3.375rem', // 54px
'11.5': '2.875rem', // 46px
'23': '5.75rem', // 92px
'28': '7rem', // 112px
'98': '39rem', // 624px
},
height: {
'0.25': '0.0625rem', //1px
'0.75': '0.1875rem', // 3px
'14': '3.5rem', // 56px
'10.5': '2.65rem' //42px
},
backgroundColor: {
'primary-a100': 'rgba(43, 121, 255, 0.1)',
},
borderRadius: {
'5.5': '1.375rem'
}, //22px
zIndex: {
'6': 6 // z-index: 6
},
screens:{
'3xl': '1664px',
'4xl': '1792px'
},
scale: {
'85': '.85', // 0.85rem
}
}
},
plugins: [
require("tailwindcss-theming")({
variants: {
light: true
}
})
]
};
至此,我們已經(jīng)了解了什么是 Tailwind CSS?如何使用 Tailwind CSS?Tailwind CSS 定制以及插件的使用,相信大家對Tailwind CSS已經(jīng)有一個全面的認識。