一篇前端討論區抱怨文讓大家 Tailwind 功力更上一層(附上 Bootstrap 比較)

前幾天才看到一篇文章You Don’t Need A UI Framework,一位需要在一個產品一再重複打磨的 in-house 外國工程師,出來講說大家做產品不應該用 Bootstrap, Material UI, Ant Design 之類的 UI Framework,讀了之後有點夏蟲語冰之感,工作型態百百種,就像一個不愁吃穿做興趣的私廚出來分析說早餐店不該用料理包、組合肉、現成化工調味料,不該用水果茶粉/奶茶粉來泡飲料、所有食材要當天採買的,要為客人的健康和餐飲業的未來發展著想 blahblah…

過沒幾天就在FB討論區看到一篇,一位從臉書個人檔案看起來是這個月在某上市櫃公司上班沒幾天的人,發文說改樣式改到火大。

一看 html 的截圖非常精彩,一個看起來像是應該要做水平捲動清單的東西,設了一大堆 Atomic CSS/Functional CSS 邏輯的 css className,還指名 Tailwind 這個現在很熱門的 CSS framework 出來罵。

從截圖可以發現一些值得討論的

但從截圖短短幾層 html makeup 就可以看到一些值得討論的,像是:

  • 有一堆 b1600, b1920, b429, b588, b868, b1366, b2209, b2618….這個我記得 Tailwind 本來是沒有的,應該是原 PO 的前人重新定義了一堆名稱用來當 breakpoint 用的? 而且要定義這東西還不是寫在CSS裡面,而是另外寫在 tailwind.config.js。另外可以外層容器上看到,不同可視區域寬度時上邊距會改變、清單項目的寬度會從一排6個…..一直到變成螢幕 4/5 寬度,除了 breakpoint 不知道裡面還定義了什麼好東西。
    這種命名邏輯的問題,大概就是未來某一天如果有新需求,例如某某寬度的時候標題或文字段落結尾不要落一個字,那是否又要再多一個 b350 之類的去控制文字尺寸或字距,還是讓 b429 對應到的不是 429px? 還是又要動 html,加上其他的 classList 名稱呢?
  • class='border-r-8 border-l-8 border-solid border-b-0 border-transparent' 不知原 PO 的前人為何要用透明的左右框線來當成清單項目的左右間距,而不是用 margin, padding, gap 之類比較普遍的作法,要是遇到那層 div 又要設框線樣式,或是 background, box-shadow 的樣式,豈不是很麻煩嗎?
    而且要用 js 取寬度做一些功能的話,offsetWidth 跟 getComputedStyle 含 border 寬度,clientWidth 不含 border 寬度,網頁寫到一半可能又稍微再卡了一下。
    var item1 = document.getElementById("item1");
    alert(item1.offsetWidth+","+item1.clientWidth+","+getComputedStyle(item1).width);//得到三個不一樣的數值
  • 有些設定似乎是多餘的,外層都已經設 flex 了,whitespace-nowrap 跟內層的 inline-block 應該可以拿掉了。但也有可能是為了不要讓不支援 flexbox 的瀏覽器顯示時爆掉,才加的 fallback?
  • 對完全沒用過的人來說,改網頁時要怎麼知道哪些名稱是 Tailwind 內建的,哪些是前人另外寫的? 例如在深色背景介面時,text-red-600text-red-700 哪個顏色比較亮? border-r-8 的 8 是什麼單位? 8%? 0.8%? 8px? 某種 rem+calc 的算式? 要增加樣式規則時,要怎麼很快知道Index of CSS properties – w3c 上的幾百個 css 屬性,或是一些特殊的 selector,哪些名稱在 Tailwind 有內建,哪些又要自己另外寫?
    還有這種現代 css framework 用了很多 CSS variables var(--xxx) 的寫法,會不會改一下變數,又讓不知道哪邊的東西壞了? 還是為了保險起見,自己再取一個新的 CSS 變數名稱來用? 這樣又回到本段一開始的問題,怎麼知道哪些名稱是 Tailwind 內建的,哪些是另外寫的?
    名稱加得越多,就大大增加了開發與維護的成本,要改一個網頁,不只要看 CSS, html,還要多開一個查 tailwind 文件的視窗。而且搞不好 CSS 裡面還定義了一堆 .page-home .mt-4.page-product .mt-4,不只同一個 mt-4 在不同頁面會有不同數值,還一堆樣式寫在 mt-4 上面,只要想說要改一下上外距,改成 mt-3 然後世界就崩塌了…

當然有些是預想以後可能會發生的問題,但有些需求可能一輩子都不會產生。原 PO 壓根兒沒有具體列出他目前碰到那組 code,有遇到什麼想做但是做不出來的,想改但是改不動的?
只記得從一個留言回覆看到他說對於 div 上要要用偽元素設定一些樣式的時候,豈不是又要再取名字? …之類的,這點其實說得滿有道理,用這種 framework 看似可以稍微縮短盤古開天初期的混沌,多人協作時至少有個基本的準則,但為了需求或使用者體驗,最後還是免不了要自己寫樣式,然後後續走上又要整天想著要取什麼名稱、用 devtool inspect style 的老路。

TailwindCSS 官網文件搜尋有夠難用

對於像我手刻派,之前也碰過 Bootstrap 跟 Tailwind 的人來說,有些名稱其實滿直覺的。
但對於沒用過的人來說,或是之前在研究時,發現 Tailwind 官網文件有個問題,就是不少東西無法直接很快搜尋到?

以截圖中的 -mx-2 為例,Tailwind 的文件搜尋出來前幾筆,完全是不相干的東西,但稍微用過的就知道 mx 應該是 margin 相關的東西(Bootstrap 4,5也有一模一樣的),開頭加 dash 表示負數,而不是什麼 css variables 或特殊的 options。而 spacing>margin 這個應該要出現在最上面的搜尋結果,卻顯示在整個搜尋結果的最後一筆。

Bootstrap 也有一樣的 mt-2, mx-2 之類的名稱,但官網的文件搜尋功能,搜尋出來也是一些亂七八糟不相干的東西,應該要出現 margin & padding 的章節,但完全沒出現。

難用的文件+處處充滿眉角的系統,可能讓世界上產生很多 Joker 呢!


(這個只是網路上看到的梗圖,演員應該沒有真的裝過K8S)

工具本身沒有錯,存在即合理

技術百百種,每個使用的人或團隊各有各的選型理由,但各行各業卻常常碰到,由不是使用者、操作者的人來決定什麼情境該用什麼工具,而決策原因也跟技術毫無關係,通常是什麼大公司也在用、聽起來很新潮、被一些業務或掮客開發到、預算不足、預算不足但是人力很便宜可以盡量浪費…之類的,軟工自然也不例外,不過網頁前端似乎常常不被當軟工看。

原 PO 在公司接手別人的 code,應該也無法決策技術選型,他其實也沒說他的角色是什麼,他們的工作流程是如何,我們無從得知他覺得不好的原因。
搞不好他要接手別人已經切好版的 html,需求是整個 li 的東西都要做成可以從後台編輯,要用 for loop 把 li tag 和那一大坨 classList 寫在後端程式那邊,或是要用 for loop 把 li tag 用某種前端元件的方式寫出來,而且第一個 li tag 的視覺樣式要顯示得特別大,所以第一個 li 跟後面其他的 li tag 的樣式類別名稱都要長不一樣?
或是有人想要調個樣式邊距,因為 li tag 寫在後端程式裡面,可能調樣式就變成後端工程師的工作,甚至變成以下情況:

「ml-1.5 太多了,ml-1 好了」
「ml-1 又太少了,可以 ml-1.2嗎?」
「Tailwind 沒有 ml-1.2 喔?反正就是要跟那個圖案對齊,大約距離 17px 嗎?」

2022/6/22 更新:該文原 PO 後來又跑去社團發徵才文,要找會用 Vue 跟 Ant Design of Vue 的前端工程師,不過似乎沒人敢再提之前 Tailwind 的事。

原 PO 所講的 CSS 應有的架構是什麼? 我也不知道

做這行應該都有聽過「不就幾行字跟一些按鈕,怎麼做這麼久」「程式不就寫好就好了嗎? 幹嘛還要這麼多人在維護?」做網頁這麼多年碰過非常多前端問題,現在也一直在尋找解答…

  1. 瀏覽器相容性問題
    瀏覽器更新會讓網頁跑版,瀏覽器不更新也讓網頁跑版,要怎樣的 CSS 架構才能避免這種瀏覽器相容性問題?
  2. HTML 的變動帶來頻繁的樣式修改或重寫
    像我有在幫人改部落格的、商城魔改的,人家的 html 長怎樣當然不是我決定的,要幫一些現成的 CMS 或 EC 平台調整樣式,因為範本寫法改變,或是平台政策變更,每隔一陣子就要跟著修改 CSS 樣式。要怎樣的 CSS 架構,才能避免這種 HTML 重構連帶樣式要重寫的問題?
  3. framework 版本升級,就要重背樣式類別名稱
    從 Bootstrap 2, 3, 4, 5 都有用過,都是引用 CSS 跟 JS 而已,結果每升一版就有一堆東西要調整修改、重新背 html 裡的各種樣式名稱跟 html markup,要怎樣的 CSS 架構才能避免這種明明視覺上看起來差不多,但每隔一兩年就要把背後的網頁程式碼大改的問題?
  4. 跟風新東西,結果變孤兒
    有時候跟風用一些看似很潮、有點討論度的 framework,像是 Foundation,還有各種模仿 Material Design 風格的,過幾年要維護修改或是擴充功能時,發現上錯車了,套件根本就不更新,後續也根本很少人用,生態系都沒建立起來,於是又要重寫一堆東西,看是回歸手刻派,或是再用上當時最熱門的 framework,那要怎樣的 CSS 架構才能避免這種變成套件孤兒的問題?
  5. 假RWD
    有人不想因為 RWD 多花錢花時間,但是網頁用電腦看要漂亮滿版,用手機看要能正常顯示,不要有東西被切到或是點不到,或是手機上的畫面要跟電腦上一樣,選單、側欄之類的不要收合起來,於是用 JS 判斷行動裝置時,硬改出一個畫面跟按鈕都很小,不是 RWD 也不是 mobile 的版本,這種情況是要用怎樣的 CSS 架構能解決的問題嗎?
  6. 錢沒有變多但事情變多
    維護一些超久的老網頁,常常發現裡面都是一堆跨欄跨列很複雜,人腦難以構築的 table,一點也不 a11y 的 map 元素,還有一堆看了就高血壓的流水號命名樣式名稱,才知道原來以前只要在 Photoshop 裡面拿切片工具畫一畫就會自動產生 html,即使網頁資訊都在圖片裡,在標題跟 meta 堆砌關鍵字就能讓SEO名列前茅,在 Dreamweaver 用滑鼠點一點就可以設一堆流水號命名風格的樣式名稱。
    而現在寫網頁,編輯器的 HTML/SCSS/JS 檔案各一個視窗,開一個 CMD 視窗用來跑 npm 指令,網頁瀏覽器的網頁畫面和 devtool 各開一個視窗,再開個小算盤或 excel 隨時把 px 換成 em, rem 或 % 單位,還有另幾個視窗看文件/設計稿/backlog/sns 訊息,那要用怎樣的 CSS 架構能讓網頁開發者少開一些視窗?
  7. 把專案管理問題變成前端工程問題
    要先知道所有的視覺畫面會長怎樣,然後再來寫 CSS code,還是什麼食材都不用準備,直接叫廚師先去煮飯煮湯,煮出來才開始想說要吃牛肉麵還是義大利麵,然後開始責怪廚師不會通靈,做一餐要很久。這似乎是專案管理問題,完全不是 CSS 架構問題啊?

有什麼完美的 CSS 架構能一次解決所有問題嗎? 應該是沒有,基本上就是新的架構可能解決舊問題,也同時帶來新問題,新問題可能帶來新商機,這整個過程一直持續在發生而已。

在還沒有原子式CSS或 TailwindCSS 的時代,也曾接手過用 HEX 色碼命名邏輯的網站,例如長得像 class='title-42B8dd' 這種,
碰到網站整個視覺要改版,色碼當然也不一樣了,處理時又發生各種恐怖故事:

  • 要翻遍整個專案程式中有 title-42B8dd 此類命名的地方,有些可能寫在後端程式產生迴圈的地方,有的可能在跨頁面共用的元件裡,也有可能好幾支不同程式的 view 檔案都有,或是在各種 if-else 片段中,萬一沒改到那段情況就糟了,或是 AJAX 呼叫後返回的整包 html 裡面,或是根據 AJAX 返回的 JSON 再組合 UI 的 JS 程式裡面,不少部分要請後端部分的工程師改,要重新編譯的就重新編譯。搞不好還沒辦法全部用取代的,因為有些地方還是要繼續用 title-42B8dd,沒有要換顏色 …
  • 放在後台編輯區內讓使用者自行修改的內容,也有用到 title-42B8dd,要嘛人工一一檢查,要嘛直接撈資料庫比對資料表的所有欄位,看哪個欄位有存到 title-42B8dd,再逐一做調整。
  • 換成新的色碼,例如把前二步驟中所有 title-42B8dd 換成 title-0066cc,然後校對期間客人每提一次「想改顏色」,上面的步驟就要重做一次,全部工作人員就要重忙一遍。什麼? 叫客人確認好再來? 童話故事的內容嗎?
  • 上面的通通不管,直接在 CSS 檔案改寫成 .title-42B8dd{background:#0066cc}日後碰到哪個衰鬼再維護這網站,可能會連聲驚呼 WTF。

一個小小的樣式命名問題,在網站改版時可能牽涉不同程度的人員工作量,大家平常都沒有別的事要做嗎?
但客人或是不用寫程式的管理人員,認知可能就停在「阿這就美工改一改 CSS 就好,滑鼠選一下調色盤而已」,時間跟預算壓得很緊,也難怪第一線人員的怨氣永遠這麼重。

想不到那篇文章釣出不少高手回應

我在晚上睡覺前剛好看到那篇,底下留言也沒有看到什麼有意義的回覆,頂多只有「如果這是你寫的,那還是不要用 Tailwind」(原PO回覆說是要接手別人的code),或是「某某功能 (例如 Tailwind @apply) 先了解一下」之類的,隔天早上起來想再看看有什麼好的回覆,文章已經消失了。

看起來好像這樣就結束了? 在網路上發問的風險就是這樣,有時候大家集思廣益得到好內容,隔天想再去找卻不見了,有時候什麼問題都沒解決,只是戰成一團。

想不到議題後來持續發酵,不少高手又專門出來寫文章:

上述文章,雖然有些看到最後會發現,每篇的目的各有不同,
有的可能是真的想解決工作中痛苦的根源,提升工作效率
有些是來賣課程、來推銷服務或產品的,
有些是工程師想要自己做個簡單介面,或是做 Saas 服務偏 UI 類的用法,而不是思考「實現視覺設計稿」(可以去玩一下Can’t Unsee)。

會覺得常常有些套件或工具只用少少的一些規範,就妄想解決所有網頁實作問題,
更可惡的是一些推銷文可以拐騙一些完全不負責實作的人,讓他們覺得喔~這工具或套件好棒棒,導入就可以完美解決所有問題,趕快叫團隊成員更換,真是叫實作人員翻白眼翻到外太空。

每個人的用法跟觀點都不同,但就看有沒有範例用法值得學習的囉。

現代問題要用現代解法

網頁前端也是隨著瀏覽器的 CSS 支援性、使用者裝置和軟體更新,寫法不斷在改變,
隨便舉一個簡單的例子,要做一個一排X個的清單,從以前的 table,持續發展到後來的 float, inline-block, flexbox, grid,現在用 table 寫會死嗎? 也不會啊,只是要做成大螢幕時一排4個,螢幕很小的時候一排2個,會很麻煩就是了。

我用 Tailwind 反而用得比較少,不只是 Tailwind 官方的 Tailwind UI 是要錢的,而且 tailwindcss 套件沒辦法直接 build SCSS/SASS 檔案,如果覺得 tailwind 的 Functional CSS 功能更多、@apply 跟 purge 功能也不錯,但又習慣 SCSS 的 nesting 跟一些 for loop 寫法?
如果真的要用,SCSS 和 tailwind 還是可以混用,但是要先把 SCSS 編譯出來,再用 tailwindcss build 把上一步驟的 css 檔案 build 一次,在 package.json 先配好指令,雙重套娃才行。

以下稍微分享一下幾個使用經驗,Tailwind 跟 Bootstrap 要排出一樣的東西的話,寫法有什麼差異

Tailwind 跟 Bootstrap 的用法差異1 – 以一橫排 5 個均分寬度的清單為例

想到以前用 Bootstrap 要做一個東西,一個 row 清單 有幾十個項目,要做出一橫排 5 個均分寬度,超過5個要換到下一行,這個看似常見的需求,在 Bootstrap 早期版本的文件內是沒有內建的。(超過5個要換到下一行,跟N個東西要在一行內顯示,是兩個完全不同的需求)

Bootstrap

曾試過用 3.x 版本的 Customize 功能,把 12 grid-columns (2, 3, 4 的最小公倍數) 改成 30 (2, 3, 5的最小公倍數),需求是達成了,但常常用起來覺得懷疑人生:
– 為什麼 .col-sm-4 顯示出來卻這麼小? 因為改了基準值,要用 .col-sm-10 才是本來的 col-sm-4,要用 col-sm-15 才是本來的 col-sm-6 。
– 一排4個均分的怎麼用不出來? 30 沒辦法被 4 整除,還要兼顧一排4個均分可能得分到 60 cols (2, 3, 4, 5的最小公倍數)才行。
– 而且這樣硬改,要3均分、左小右大,整個欄寬數值跟 offset 都要自己腦中重算
– 連自己也忘記哪些網站有這樣改,改網頁前還要先看一下這網站是用 12 的還是 30 的,其他地方寫過的東西也無法很快直接 copy 過來用。
結果最後還是在 row 或 col 上面加個另外的自己取的名稱和樣式。

結果這問題在 Bootstrap 4 (改用 flexbox) 跟 Bootstrap 5 (有 flexbox 跟 grid) 壓根就不是問題:
– 可以直接用 .row.row-cols-5>.col*10grid-column 寫法(使用 flexbox),
– 用 SCSS 寫的話,還可以 @import grid 的相關檔案,然後在清單上面下 .test-list{@include row-cols(5);} 之類的樣式,再編譯出瀏覽器可解讀的 CSS。

Tailwind

Tailwind 對於這個需求也不在話下,
– 可以用幾個 css 樣式類別名稱 .grid-cols-5.gap-4>div*11 基本湊出一排5個和加上間距的清單(這個寫法背後是用 css grid,IE11 不支援)。
– 可以用幾個 css 樣式類別名稱 .flex.flex-wrap>(div.w-full sm:w-1/2 md:w-1/3 lg:w-1/5) * 11 基本湊出一排5個的清單(使用 flexbox)。
– 把剛剛用到的名稱配上 apply 寫在 CSS 檔案裡面 .test-list{@apply grid-cols-5 gap-4;},再編譯出瀏覽器可解讀的 CSS。

但是如果需求改一下,要做 7 個均分、9 個均分、11 均分,17均分,超過的要自動換到下一行? Tailwind 的 grid-cols 可以分到 12 個,Bootstrap 的話…還是自己手寫吧。

Tailwind 跟 Bootstrap 的用法差異2 – 以原始範例的人型蜈蚣 classList 為例

Atomic CSS/Functional CSS 的寫法,減少一些常見的問題,例如
– 有時候只是要設幾個小小的CSS屬性,要兼顧語意,還要避免撞名,要幫元件取一堆什麼 feature-block-deco-1, feature-block-deco-2, feature-block-deco-3, feature-block-deco-blue …之類的,現在可以先不用取名,簡單的東西直接用 Atomic CSS/Functional CSS 來做。
– 讓一些樣式規則用途至少有個基本規範,減緩明明一樣的用途,卻取了一堆不一樣的名字四處分散在各支 CSS 檔案內,或是撞名導致一些靈異事件之類的情況。

那假如今天情況比較極端,頁面上有 100 個一模一樣的 li tag,每個 li 上面都有一堆樣式名稱,有什麼更好的做法?

Bootstrap

到 Bootstrap 5.2 為止,好像沒看到可以特別縮短一狗票 Atomic CSS 名稱的做法,頂多就是:
– 像上一段提的,看要設定的樣式,查文件裡有什麼類似 @include row-cols() 的 mixin 名稱可以用 (天呀,又要再記一套名稱?)
– 像 客觀評價 TailwindCSS 裡面提到的,改用一些 JS framework,把那一大串名字放到 JSX 裡面,眼不見為淨?
– 把名字拿掉,另外取名字,開 CSS 檔案用手刻。

Tailwind

原範例的 li 如果有 100 個,每個 li 上面的這個東西就至少占了 18KB 的文件大小。 class='w-4/5 b429:w-2/3 b588:w-1/2 b868:w1/3 b1366:w-1/4 b2209:w-1/5 b2618:w-1/6 flex-shrink-0 inline-block transition-opacity border-r-8 border-l-8 border-solid border-b-0 border-transparent'

如果把那一大串改成用 @apply 寫在 CSS 檔案裡面,例如 .test-item{
@apply w-4/5 b429:w-2/3 b588:w-1/2 b868:w1/3 b1366:w-1/4 b2209:w-1/5 b2618:w-1/6 flex-shrink-0 inline-block transition-opacity border-r-8 border-l-8 border-solid border-b-0 border-transparent
}

再用 tailwindcss 去 build css,然後 li 改成 li class=’test-item’,這樣有 100 個 li tag 的情況下,CSS+HTML 所佔的肯定會比 18KB 少。

名字太長,就用套件內獨有的功能多包一層,讓檔案小一點,PageSpeed Insight 跑分可以少扣一點分。那這樣在閱讀性和維護性有比較好嗎? 感覺就是頭痛醫頭、腳痛醫腳而已。

我也不曉得是真的有解決寫樣式時要頻繁切換檔案、開 devtool inspect css、設個 css 屬性還要去查文件,換算數值,文件沒有的又要再自己定義…之類的問題,還是讓人覺得自己背了好多 Tailwind 的 CSS 名稱,炫技成分比較大?

Tailwind 跟 Bootstrap 的用法差異3 – 以製作日期輸入框為例

在網頁上放一個 HTML5 的 input type='date' 的日期輸入框,就可以用瀏覽器內建的日曆元件選擇日期,不用再掛一堆有的沒的日期時間選擇器 UI 套件,input type='date' 這玩意在視覺跟程式上地雷都不少,以後有機會再寫一篇。
然後深色系佈景主題,右方的日曆 icon 整個看不見了,在 Microsoft Edge 上面不知為啥會中英混雜,如下圖

所以規格有5項
– 把瀏覽器本來的 icon 弄掉
– 另外放一顆 icon 上去,要另外改顏色
– 視覺上盡量跟之前的差不多(圖示位置要在輸入框內)
– 先不討論 IE11 根本不支援 input type=date,Microsoft Edge 的預設文字跟別人不一樣的問題,本例先以 Google Chrome 為主
– 農民曆說今日不宜寫 CSS,最好不要有新的 CSS 檔產生

Tailwind

  • 有個 appearance-none 的名稱可以用,但加了之後毫無變化,因為那個日曆 icon 是用 ::-webkit-calendar-picker-indicator 去控制,所以還是要另外開一支 CSS 檔自己寫,第一個需求開始就破功。
  • 在文件的 Handling Hover, Focus, and Other States 章節有個比較接近的範例,調整 html 可以得到這樣子的東西

  • 接下來要找個日曆圖示把 icon 換掉,Tailwind 沒有提供圖示集,所以去 google 找了個 heroicons by the makers of Tailwind CSS.,用 MIT 授權,找了一個日曆的 inline svg 把本來的換掉,再手動加上 fill='#fff'

接下來要增加 JS 偵聽事件,點擊日曆圖示時,彈出瀏覽器內建的 Date picker 小視窗,嗯,查了一下發現好像有點麻煩…先看有沒有別的方法?

原來有其他方法可以直接改變一開始瀏覽器在 tyoe=date 自動跑出來的的日曆圖示顏色,就是用 input{color-scheme:dark} ,這樣不用再自己把圖示隱藏、另外設新圖示、把新圖示移到定位。
但是 Tailwind 雖然有 dark: 讓深色模式下改用其他屬性,但沒有針對這個 color-scheme 設專門的名稱,所以要另外開一支 CSS 檔自己寫。
可以用 input[type="date"]::-webkit-calendar-picker-indicator {filter: invert(1);} ,filter: invert 剛好 tailwindcss 有內建,但是這選擇器沒辦法直接寫在 input 的 class 上,所以還是得要另外開一支 CSS 檔,用 @apply invert-0 之類的,然後再用 tailwindcss build 出 css 檔案。

Bootstrap

  • appearance:none 的屬性跟 ::webkit-calendar-picker-indicator 沒有相關直接寫好的樣式類別名稱,所以還是要開一支 CSS 檔自己寫。
  • input group,但要做出視覺上盡量跟之前的差不多(圖示要在輸入框內),還是要再自己手寫不少 CSS。
  • BS5 一樣沒有內建圖示集,但一樣有外部的 Bootstrap Icons 可以用,有 inline svg 或 iconfont。
  • BS5 的元件沒有日曆(date-picker)的,所以幫 input 或圖示增加 JS 偵聽事件的需求一樣要自己處理。
  • input{color-scheme:dark}filter: invert(1),沒有相關直接寫好的樣式類別名稱,所以一樣要自己寫。

所以 Bootstrap 5.2.0 跟 Tailwind 3.0.24 在這需求上,有增加便利性或減少開發時間嗎? 也許只有心靈加成吧。
不但不少需求還是要自己手寫,還浪費時間查這個 selecter, pseudo, CSS屬性在文件上有沒有現成的定義,查老半天,結果文件上幾乎沒定義,自己寫應該早就寫完了。

Tailwind 跟 Bootstrap 的用法差異4 – 以製作中文國字的編號巢狀項目清單為例

刊物數位化已經行之有年,但是手機閱讀浪潮又讓這件事繼續進化,以往的什麼 flash 酷炫翻頁效果電子書、平面設計排版精美的A4/B5/8開 size 的 pdf 整份放上去…之類的作法,在手機平板上的體驗真的很差,專業一點的是做成 RWD 網頁,在平板、電腦、手機各種不同尺寸的螢幕上設計能最舒服瀏覽的排版方式。

例如今天碰到一個網頁,內文有巢狀項目清單,需求大概如下:
– 巢狀項目清單的編號是中文國字,為了瀏覽器相容性暫時不考慮 list-style-type: cjk 那些鬼東西。
– 內容是專業前端網頁人員寫 code 來排,不是用一些 WYSIWYG 的傻瓜編輯器來排,所以要怎麼寫就怎麼寫。
– 先不討論一般論文正規的 一、(一)、1.、(1) 階層,先單純的 (一)、1. 就好。

Tailwind

大致排一下,大概可以排出長這樣的東西

首先因為 Tailwind 預設會把 ul 和 ol 的樣式通通清光光,所以不用加一堆 padding 或 margin 之類的調整每個瀏覽器都長不一樣的預設距離,也不用設 list-style 把 ul 的點點拿掉,反而還要加 list-decimal 把數字清單的數字弄回來。
但是一看就知道,國字的清單換行之後對齊不太美觀(覺跟不沒對齊),數字有序清單已經達到2位數了,與(二)那邊的對齊也不是很滿意,但是用 -indent-10-indent-9 都沒辦法讓他排整齊。

或是可以用 -indent-[10px]-indent-[2em] 這種寫法,會動態生成一個樣式規則,達到更精準地像素級控制。
但這樣是不是跟寫 inline style 有 87% 像? 而且這些規則都可能在 Tailwind 改版之後又要大改一番,一覺醒來又風雲變色。

當然以元件概念來說,這種國字編號清單的樣式應該是統一的,又可以用上述的方法,自己開一支 CSS 檔案,取一個新的名稱,然後把規則 @apply 上去再編譯 CSS 檔案。這樣一波操作搞下來。遲早還是要手刻 CSS 的,為什麼不直接手刻呢?

Bootstrap

Bootstrap 比較接近 normalize.css 的概念,數字還會保留,ul 的點點也會保留,所以要在 ul 加 list-unstyled 把點點消掉。
控制左邊外距的 ml-* 跟左邊內距的 pl-* 在 Bootstrap 5.2 又換名字了,從 2014~2022 年間從 4 beta 開始用到 5.1.3 的,又要捨棄肌肉記憶,背新的名字了!
然後因為 BS 沒有 text-indent 的 Utilities 可以用,所以想調到滿意,可以直接開 CSS 檔開始手刻了。

所以 Bootstrap 5.2.0 跟 Tailwind 在這需求上,有增加便利性或減少開發時間嗎? 也許有信仰加成吧! 用 Tailwind 寫網頁、包一堆只用一次的元件又帥又潮,用 SCSS、關注點分離好 old school?
祝各位網頁開發者武運昌隆,能幫工具找到適合的場景。(怎麼不是人找到好用的工具,而是人要幫工具想使用場景呢?)

Tailwind 跟 Bootstrap 的用法差異5 – 把一塊舊網頁的內容搬到新網頁

隨著服務或產品的更新,一個網站的內容、架構跟版面不斷更新也是正常的,一直疊疊樂疊不上去了,可能就會直接重新做一個新的。
這段要來檢視實務上遇到的問題,當新網站的前端用 Bootstrap 或 Tailwind 來排,但是客人說舊網站本來有一些內容,新網站也要放。
聽到這種需求,感覺應該很簡單,既然已經有現成的網頁可以參考了,複製貼上應該幾分鐘就好了? 大錯特錯。

案例是一個 modal 視窗,但樣式跟 JS 完全是前人自己弄的,視覺樣式跟內容有點豐富,不是 Bootstrap 或 Tailwind 或哪家的 UI 元件庫,之前做的人不知道哪去了,幸好也不是 jQuery UI,不然臉都綠了。
仔細一看發現是有一段時間流行的檔案架構方式,就是 IE 市佔率開始變小,使用者都用並行下載數變多的現代瀏覽器,伺服器有支援 http/2,一個網站專案裡面會有超級多支 CSS。例如:
– 一支 reset.css 或 normailize.css
– 接著另一支 css 控制基本的 heading tag, p, table, img, button, select…的全局 element 樣式
– 還有一支 theme 或 style 之類的,把配色和背景之類的和其他東西分開
– 再有幾支各元件專屬的 css 檔案
– 還有獨立專屬那頁的 css 檔案
– 最後 html tag 上還有行內樣式

也就是說這一塊舊網頁的 modal,隨便選取一個元素,背後都至少牽涉 N 支 CSS 檔案,要在新網站跟 html 復刻出肉眼看起來要一模一樣的東西。
直接把幾十支檔案包成一支直接 link css 引用進來肯定是不可行的,這樣檔案會很大,還會影響網頁裡其他元素的樣式。

Tailwind

先嘗試用 DevTools 觀察每一層的元素最終吃到哪些樣式,調整原來的 html,把本來那些看起來好像有意義的名字,一堆什麼 title 什麼 box 什麼 bg 什麼 outer, inner, wrapper,通通替換成 tailwind 的那些 CSS className?
但是 modal 從外到內有好幾層,光是把每一層的樣式轉換成 tailwind 對應的 CSS className 就已經非常曠日廢時,
還有 RWD 的情況,視窗縮放還有各 breakpoint 的要控制,很明顯跟 tailwind 預設的不同,可能要參考 tailwindcss – Using custom screen names 另外新增幾組,縮放視窗觀察元素也非常花時間。
而且很多地方都有背景圖片,少不了要自己寫 css,處理 modal 隱藏或顯示的 JavaScript 還沒寫呢?

那我不要變動 html 的包法和名稱,直接沿用所有的原有 html,然後用 tailwind 的 @apply 來重寫樣式呢?
這樣首先得檢查有沒有名稱用到跟新網站重複的,再觀察每一個 element 的樣式,再換算回去 tailwind 的名稱,這動作非常花時間,而且本來用的單位也不是靠 mb-5, text-sm 之類就能解決的,肯定會有很多 text-[15px] 之類的東西,簡直跟直接自己手刻沒什麼差異。

Bootstrap

直接有一個 modal 元件,然後再自己寫 CSS,把 Bootrstrap modal 改成跟原來的樣式一樣,應該是最快的。

在此例 Tailwind 派不上什麼用場,Bootrstrap 內建的 modal 少費一點工,最終還是要靠自己在幾十支檔案裡面尋找並整理 css 片段,或是直接寫出一個視覺上看起來長得一樣的。

另外舊網站在某些情況顯示有些 bug,現在當然繼承到做新網站的人頭上,要一併再另外調整,不能直接照搬原來的 code。

其他這種作新網站,但是舊網站部分內容要移植過來的,還有非常多實作地雷,例如移植內容是一些特殊編排或 UI 操作元件,但舊網站的文字樣式、margin, padding, 寬高通通是用 rem 單位,而新舊網站的 rem base font size 不一樣大,會嚴重跑版;或是舊網站內容是用某些套件或模板工具產生的,移植這種東西容易讓樣式變得很髒很難維護,或是搬過來之後還要花不少時間重構和修正,工時從分鐘升級到小時或日。

分類: 網頁設計
留言:

近期熱門 Hot Posts

    Contact Me

    E-Mail

    Open Email Client

    LINE 私訊
    此為 LINE 官方帳號,僅用於連絡,不會群發訊息

    加 LINE 好友

    FB Messenger/Instagram 私訊

    FB Messenger IG 小盒子

    Telegram 私訊

    傳訊息到 Telegram