Tailwind CSS (可能)是名過其實的

Tailwind CSS 是一個工具集 CSS 框架,網上不少文章已對其有詳盡的介紹。本文不是官方文檔的複述,也不是系列優勢的羅列,做者 Gerard 會從另外一個角度出發,在盡力保持客觀的前提下,立足於實際開發的場景,指出 Tailwind CSS 存在的一些問題。事實上,除了文中說起的,Tailwind CSS 還存在着很多缺點,好比對高度定製化的支持程度不足、記憶大量預約義類名帶來的心智負擔等。css

友情提醒,你不必定會贊同這篇文章的見解,畢竟咱們的見解總會受到自身認知和使用體驗的影響,但更重要的是多是做者對新興技術的態度,用他的原話說,就是:「When everyone is shouting that it’s awesome, it’s usually a good moment to sit down and have a good look at it」html

下面正文開始。正則表達式

引言

在過去的兩年間,Tailwind CSS 廣受青睞(從每週 30K 的下載量到現在的 600K)。毫無疑問,這個流行的實用優先 CSS 框架具有諸多優勢。極可能你對它的驚豔和強大早有耳聞,由於不少開發者正是這麼想的。npm

但關於這個框架,咱們還有不少要說的。sass

什麼是 Tailwind CSS?

若是你歷來沒見過 Tailwind 的實際應用,能夠看這個:併發

<div class="bg-gray-100 rounded-xl p-8">Hello World</div>

這裏的類名就反映了 Tailwind 的定義:一個包含多個預約義類(所謂的工具類)的集合。你並不須要編寫基礎的 CSS 樣式規則,只須要直接在 HTML 中應用已經事先定義好的類名。app

這樣的類名還有不少。下面這個列表展現了部分類別和對應的例子:框架

  • 背景 (bg-gray-200, bg-gradient-to-bl)
  • 彈性佈局 (flex-1, flex-row)
  • 網格佈局 (grid-cols-1, col-span-4)
  • 內邊距 (p-0, p-1)
  • 尺寸 (w-1, h-1)

以前有人將這個預約義類的集合比做能夠在代碼中使用的「樂高積木」。固然,它與傳統的 CSS 有不少重複之處,但卻不止於此:好比它還包括了預約義的範圍(bg-red-100, bg-red-200 等)。Tailwind 旨在讓咱們的開發事半功倍,從某個角度來講,它也確實作到了。工具

同時,我很喜歡這個名字:Tailwind(順風)。我閒下來的時候會駕船出海,順風但是個不錯的東西。佈局

語法

正如上面所展現的,咱們直接在 HTML 中書寫工具類名。咱們會很快想到這和內聯 CSS 是很是類似的,這或許也能解釋爲何 Tailwind 的開發者會在文檔的開頭部分就說起這個問題。

雖然他們極力解釋,稱 Tailwind 瑕不掩瑜(我不否定它確實有諸多優勢),但我仍是不太承認它的語法。我不想用一大堆類名污染 HTML 結構中的每個元素,也不想天天都面對這樣的代碼:

Image for post

注意:上面這段代碼來自 Tailwind 的文檔,所作的事情是渲染一個簡單的卡片。事實上,它最後呈現的效果很是漂亮,甚至仍是響應式的。但若是放眼於咱們的平常開發,這種狀況就會急速惡化:若是我正在開發一個比卡片複雜更多的組件呢?若是我必須遵循設計師提出的某種設計風格,以及忍受他的一些「小怪癖」呢?

我嘗試去應付這種狀況,結果也在乎料之中 —— 每個 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>

這也是實際開發中不可避免的。

上面這個例子可不誇張,我甚至能夠說它是一個最簡化的例子了 —— 至少對於那些有明確要求、明確設計風格(基於不一樣屏幕尺寸做出的響應式變化和樣式調整)的應用來講,是這樣的。

那麼要怎麼組織這些類名呢?也許咱們要建立並遵循某個排序規則,但這樣實在太複雜了。另外一種作法是容許模板設計者和開發者使用任意一種具體的排序,但這樣一來,爲了找到要修改的目標類名。咱們就不得不水平掃視甚至是滾動查看代碼。

我可不想像找威利同樣去找元素的字號(譯者注:威利是兒童書籍《威利在哪裏》中的人物,讀者須要在一張人山人海的圖片中找到威利)

個人觀點是,部分 HTML 元素會使用很是多的樣式,這種狀況下應該考慮將樣式與 HTML 標籤進行分離,單獨放到某個文件裏。這樣,咱們就能夠組織樣式並加強其可讀性。你不能把 CSS 的全部功能」塞到「 class 這一個 HTML 標籤屬性裏,Tailwind 也不能。這樣作只會讓 HTML 結構愈加臃腫。

@apply

針對上面提到的問題,Tailwind 容許咱們在單個 CSS 文件中使用它們的類名:

.header {
  @apply bg-red-200 w-4 text-gray-400 rounded-sm border-red-400 border-2;
}

但比起傳統編寫 CSS(或者 SASS 等其它預處理器)的方式,我看不出這樣作有什麼優勢。你能夠說我是「老古董」,但我確實更喜歡下面這種編寫方式:

.header {
  background-color: #FECACA;
  width: 200px;
  color: #444;
  border-radius: 5px;
  border: 2px solid #F87171;
}

再次強調,在真實開發中,元素可能會應用很是多的樣式。

我並無對 Tailwind 的優勢避而不談,其提供的部分工具類必定有更多用處亟待探索。但談及語法的時候,我仍是但願標記語言(HTML) 和樣式規則能夠進行明確的分離。我想,這是一個主觀的見解。

清除無用代碼

在項目中引入 Tailwind 以後,全部的類名都是可用的。但在構建和打包項目的時候,咱們顯然並不須要用上全部類名。所以,Tailwind 使用了 PurgeCSS 這個工具:

這就是 PurgeCSS 發揮做用的地方。PurgeCSS 會分析你的內容和 css 文件,首先它將 css 文件中使用的選擇器與內容文件中的選擇器進行匹配,而後它會從 css 中刪除未使用的選擇器,從而生成更小的 css 文件。

簡單總結一下:首先,咱們爲項目引入大量的工具類名,接着,在準備構建併發布項目的時候,使用一個工具掃描代碼並找出全部未使用的類名,以確保它們不會隨其它代碼一塊兒打包。其實現依賴於下面這個正則表達式:

Image for post

引入並使用 Tailwind 會給咱們的項目平添一層複雜性,複雜性帶來的是必定的風險,會給咱們的開發形成麻煩。好比說:

render(
  myItems.map(item => (
    <div className={`item level-${item.level}`}>
      {item.text}
    </div>
  ));
);

像這樣動態生成類名的操做是作不到的。這意味着 Tailwind 對咱們的開發形成了限制。關於這一點,文檔也有提到,但很容易被開發者忽略:

Image for post

字符串拼接的操做是不容許的。

開發上的限制是一方面,還有一個問題是:給項目增長一層複雜性,一般會給項目帶來風險。

這最終變成了一個關乎判斷的問題,即 Tailwind 是否利大於弊?項目不一樣,對這個問題的回答也不一樣,但咱們至少得留意到它存在的問題。關於 Tailwind 帶來的限制性,上面提到的問題只是冰山一角。能夠再舉一個例子,那就是給 Tailwind 項目添加額外的(自定義的)CSS 並不那麼簡單直接

替代品

在閱讀了 Tailwind 的文檔並上手開發了幾天以後,我忍不住在想:做者並無意識到咱們中的大多數人已經在平常開發中使用其它工具來簡化樣式編寫了。

文檔說過,使用 Tailwind 的一個好處在於能夠避免魔數(譯者注:魔數指的是缺少解釋或命名的獨特數值,出現屢次,且能夠被有名字的常量取代)。確實如此,這是它的一個優勢:咱們定義一個諸如 bg-red-200 的顏色工具類,以後能夠在代碼各處使用,並在一個地方(Tailwind 的配置文件)集中修改它的實際值。這仍是挺香的,我相信你也贊成這種作法。

但今天的工具,好比說 SASS (周下載量超過五百萬),早就能夠輕鬆建立工具類和變量並在代碼中重用了。甚至原生的 CSS 也已經支持使用變量。

當咱們使用 SASS 或者原生 CSS 的時候,咱們不須要面對額外的一層複雜性,在編寫 CSS 樣式規則的時候,也不須要改變既已造成的習慣和語法。

使用 Tailwind 是有成本的。花費時間和精力學習 Tailwind 的語法和類名,你會逐漸忘記其背後的語法:也即原生 CSS 的語法。若是個人開發者在一個更大的項目中使用 Tailwind 長達一年,他們將會逐漸忘記原生 CSS。這種事態真的樂觀嗎?我不太肯定。

後序

Tailwind 很流行,它的吸引力和追捧者與日俱增。我能理解這其中的緣由,畢竟使用它真的可讓咱們受益不淺。對其優勢我也表示承認,它的一些工具類能夠發揮很大的做用。

我撰寫本文的目的,在於向各位展現一個事實:故事老是有兩面性的。

一些人會從這個框架中受益,但還有一些人則會受限,他們會在開發的過程當中不斷髮現這些限制 —— 或者更糟,在開發後才發現。

在適應新框架的時候,請保持你的批判性。當「每一個人」都高聲驚呼其驚豔的時候,也許正是冷靜坐下、仔細端詳的最佳時機。

感謝你花費時間閱讀本文!

相關文章
相關標籤/搜索