使用全新的 CSS 語言建構你的設計而非實用程序/程式庫。
該篇藉由論述傳統 CSS 的開發詬病來介紹 Master CSS 對其提出的解決方案以及運作原理。
虛擬 CSS 引擎
Master CSS 的虛擬規則引擎使你省去編寫、排序及命名 CSS 等大部分實作,再白話一點 —— 你完全不需撰寫 CSS,只需在 HTML 中增添類名。
虛擬 CSS 是一個藉由增強語法表達真實 CSS 規則的概念。 ——Master
上圖為 Master CSS 在瀏覽器實時運行的概念圖,讓我們概覽幾個處理過程以利後續閱讀:
- 觀測 DOM tree 上的所有類名
- 透過差異演算法偵測類名的變更
- 匹配類名後創建其對應的樣式實例
- 解析類名,將語法分割為多個核心標記
- 生成 CSS 規則
- 根據斷點大小及選取器特性等進行智慧地排序
- 插入 CSS 規則到你的 HTML 中
- 若有類名被徹底移除,對應的 CSS 規則也將被刪除
自動地生成規則
不需撰寫 CSS?那我要怎麼新增樣式?在這之前,讓我們從你最熟悉的寫法開始。
你:「設置 section
背景、互動及內距,並且在 >=1024
的時候內距大一點,我先想想該叫什麼...」
<section>...</section>
時光匆匆,一分鐘過去了... 「好,就叫 home-section
了。」
<section class="home-section">...</section>
打開/建立其對應的 home.css
檔或 style tag 又花了幾十秒... 終於,可以開始寫 CSS 了。
.home-section { background-color: blue; padding: 2rem; text-align: center;}.home-section:hover { background-color: red;}@media (min-width: 1024px) { .home-section { padding: 3rem; }}
你:「這樣寫有什麼問題嗎?非常標準啊!」對的,以結果來說沒有問題,但編碼的過程與生產力是 Master 旨要優化的環節。上述過程換作是你將花多久的時間來構思並實作呢?
讓我們用 Master CSS 改寫,只要一行,並且沒有 CSS 檔。↓ 86% 程式碼
<section class="bg:blue bg:red:hover p:32 p:48@md text:center">...</section>
用更少的程式碼( 近乎 90% 的減少 )來完成相同的效果且省去命名的時間,以最快的方式實踐。
那真正的 CSS 規則跑哪去了?在你新增完類名的同時 Master 已將其注入當前的頁面,讓我們看一下自動生成的 CSS 規則:
/* 核心代碼已將其壓縮,此為格式化結果 */
.p\:32 {
padding: 2rem
}
.text\:center {
text-align: center
}
.bg\:blue {
background-color: #175fe9
}
.bg\:red\:hover:hover {
background-color: #d11a1e
}
@media (min-width:1024px) {
.p\:48\@md {
padding: 3rem
}
}
以上面的例子來看最終生成的 CSS 似乎比 home.css
多一點?沒錯,但是總體來說它將更小,後面我們會談到。
在 Master,非必要時撰寫 CSS 只是“純開銷的生產行為”,因為我們會自動幫你生成。 ——Master
智慧地排序規則
那 CSS 規則的優先級排序怎麼決定?讓我們看一個常見的響應式範例。
你:「首頁的標題在視口寬度 >=1280px
時置中;>=1024px
時置右」
@media (min-width:1280px) {
h1 {
text-align: center;
}
}
@media (min-width:1024px) {
h1 {
text-align: right;
}
}
上面的 CSS 是錯的,因為不管視口寬度 >=1024px
或 >=1280px
都將優先套用 @media (min-width:1024px)
。「@media (min-width:1280px)
至始至終都未被套用。
你本來就知道其原理?還是碰巧放對?即便你知道,但這只是一個極其單純的 CSS 規則,當規則變得更多且更複雜呢?
現在,讓引擎自動幫你排序,再也不用思考優先級的問題了!
<h1 class="text:right@md text:center@lg">...</h1>
<!-- or -->
<h1 class="text:center@lg text:right@md">...</h1>
不管類名怎麼排列 Master 都將自動為你生成正確順序的 CSS 規則:
@media (min-width:1024px) {
.text\:right\@md {
text-align: right
}
}
@media (min-width:1280px) {
.text\:center\@lg {
text-align: center
}
}
就只有這樣?只要你應用了選取器 :disabled
, :active
, :focus
, :hover
, :where()
甚至響應式斷點 @lg
, @sm&<lg
,Master 都能以你預期的行為排序,幾乎用不到 !important
。
如果你還沒看過我們首頁的動畫,點此查看。
常用單位轉換
在進行 UI 工程或設計時,像素 (pixel) 是大部分開發者/設計師的共通語言,但是對 CSS 及瀏覽器來說就不是這麼單純。
回顧厭世的你:「以最佳化 rem
設置 24px
的文字大小,打開轉換器、查表或自己算... 24/16=1.5rem
」
<h1 class="font:1.5rem">...</h1>
你:「還好啊!查一下表沒這麼困難。」但同樣的動作你可能要重複數十次甚至數百次。
現在,依賴內建的轉換行為直接寫上你預期的 24
(px)。
<h1 class="font:24">...</h1>
讓 Master 自動幫你轉換成 rem
並生成 CSS:
.font:24 {
font-size: 1.5rem
}
Master 依樣式/屬性不同的特徵及實用性預設了最佳的單位或轉換,這不只提升了生產力還消弭了單位在 class=""
出現的頻率及觀感。
體驗導向的原創設計
你:「使用 Master CSS 不就得學習新的語言及用法?
Master 的語法是建立在原生 CSS 之上,你可以把它想成是 SASS 語言,讓你先用最熟悉的 CSS 語言/介面起手,並提供額外的語法糖與簡化的結構。
具結構性的語法
我們本意不是要讓你直接在 class=""
中撰寫原生的 CSS,而是將其做合理的簡化及精煉,並使其更優雅地呈現在元素的類屬性。
所有的樣式都依循著相同的語法,幾乎不用查表,以設置 1rem
的文字大小為例:
<div class="font-size:1rem">與原生相同的寫法</div>
<div class="font:1rem">原來可以簡化</div>
<div class="font:16">不給單位就是 16px to 1rem</div>
<div class="f:16">極致短</div>
讓我們再看一些樣式:
<div class="bg:blue-60/.5">設置透明度 .5 的藍色 60 背景</div>
<div class="scale(1.5)">變形放大 1.5 倍</div>
<div class="~transform|.3s|ease">設置持續 0.3 秒且加減速 ease 的變形過渡</div>
<div class="block">以語意化方式設置 display: block</div>
...
開箱即用選取器,以設置背景為例:
<div class="bg:pink:hover">懸停的時候設置粉紅背景</div>
<div class="bg:pink~*">後面的元素通通設置粉紅背景</div>
<div class="bg:pink+div">後面的 div 元素設置粉紅背景</div>
<div class="bg:pink_:where(p)">後代所有的 p 元素皆弱設置粉紅背景</div>
<div class="bg:pink:first">用簡化的 :first 代替 :nth-child 設置粉紅背景</div>
...
開箱即用媒體查詢,並提供更簡練的標記:
<div class="width:800@>=1024">視口寬度 >=1024px 才設置寬度 50rem,支援任意值</div>
<div class="width:800@sm">使用內建的標記,效果同上</div>
<div class="top:1@xs&<lg">視口寬度 >=600px 且 < 1279.98px 時距離上緣 0.0625rem</div>
<div class="bg:gray-20@dark">背景於暗色模式時為灰色 20</div>
<div class="hide@print">列印時隱藏該元素</div>
<div class="@fade|.2s@motion">用戶不減少動畫偏好時才套用持續 0.2 秒的淡入動畫</div>
...
這只是冰山一角,查閱官方的語法教學了解更多。
引領尖端的科技
你覺得上面的語法夠方便了?我們還設計了一些神奇的用法來優化你的程式碼。
群組功能 ✨
你:「一直重複寫相同的選取器/媒體查詢,變好長喔。」
<ul class="block>li:hover@md p:16>li:hover@md w:full>li:hover@md text:center>li:hover@md font:blue/.5>li:hover@md"></ul>
使用 Master 的群組功能將其縮短。↓ 45% 程式碼
<ul class="{block;p:16;w:full;text:center;font:blue/.5}>li:hover@md"></ul>
反應式樣式 ✨
你:「目標元素的樣式寫在其它元素上有點怪。而且不會隨著元素被清除。」
<label class="inline-flex center-content">
<input class="text:line-through:checked+span cursor:pointer h:16 mr:8 w:16" type="checkbox" checked />
<span>½ teaspoon red chili powder (adjust to taste)</span>
</label>
使用 Master 的反應式樣式使其更方便存取/管理狀態。
<label class="inline-flex center-content">
<input class="cursor:pointer h:16 mr:8 w:16" type="checkbox" checked />
<span class=":checked+{text:line-through}">½ teaspoon red chili powder (adjust to taste)</span>
</label>
欲了解更多請查閱官方的語法教學。
語法突出的先行者
細心的你可能已經觀察到官方文件中的 class="..."
類名具有語法突出,這歸功於 Master 本身結構性的語法及其語言的定位。
語法突出全面提升你的開發體驗:
- 改善普遍開發者對於類名過長的觀感。
閱讀程式碼和識別其結構變得更快速。
- 程式碼的實現更容易,因為語法突出是即時完成的,可以更快地檢測到輸入錯誤。
PPIG 會議上發表的一項研究評估了語法突出對短程序理解的影響,發現語法突出顯著減少了開發者內化程序語義所需的時間。
爲什麼其它 CSS 框架/庫沒有這個功能?因爲其類名不具有統一性的結構,並且它們只是一個實用程序/組件庫。
我們還提供了程式碼自動完成、CSS 渲染預覽等輔助功能,詳細請查閱官方的開發者工具。
與框架無關,開箱即用
我們依賴你最熟悉的 class=""
介面,故無需與框架整合,並且所有的樣式、屬性、選取器、函式、斷點、媒體查詢、配色方案及支援依賴都是零配置開箱即用。
現在,以一行引入 JIT 模式並零配置開箱所有功能,不受框架/平台所限。
<script src="https://cdn.master.co/css"></script>
官方首推 JIT 模式是因其便攜/友善且適用於大部分專案,我們還提供伺服器端與瀏覽器端的混合渲染,它類似水合作用 (Hydration),日後我們也將推出與建置工具整合的 AOT 模式使其更完善。
雖然我們與框架無關,但我們仍提供框架或建置工具的安裝指南,讓你更快上手!
如果你還未學過 CSS,就以更簡練的語法作為開端。
避免過早抽象化
CSS 的本質就如你在使用繪圖軟體,當你為目標填色、調整大小時需先為其命名才得以編輯嗎?
傳統上,習慣設置元素樣式時先為其命名,或因需套用選取器/斷點而不得不這麼做,這都是導致過早抽象化的主因。我們先來複習一下傳統的習慣及過程。
<div class="card">
<img class="card-image" src="/images/mountain.jpg" />
<div class="card-body">
<div class="card-title">Mountain</div>
<div class="card-text">A mountain is an elevated portion of the Earth's crust, generally with steep sides that show significant exposed bedrock.</div>
</div>
</div>
結果看起來依舊沒什麼問題對吧?對,但你在這之前你不只撰寫了大量的 card.css
還有一段痛苦的經歷...
- 這個卡片要叫什麼?
.card
命名有被佔用了嗎?- 命名成
.card-text
是依據什麼規範?其他人能接受嗎? - 其它地方的卡片風格一樣嗎?
.card
真的有共用到嗎? - 這個卡片要微調間距怎辦?不會要再取一個名字吧?
- 這個卡片風格似乎有落差無法重用?
- 首頁的這個區塊的卡片要叫什麼?另一個區塊的又要叫什麼?
- 這個地方是不是要直接拿
.card
來改?有點像。 - 這個地方的風格跟卡片一樣,但它不是卡片... 叫卡片好奇怪喔!
.card
似乎要再擴充一點樣式?好多地方一樣呢?- 在 HTML 和 CSS 檔之間來回編輯/確認...
- 這樣真的是最佳實踐?
等等,寫完就想拍拍屁股走人?後續維護跟開發造成什麼問題?
- 這個卡片的 CSS 檔在哪?
- 有沒有其它檔案對卡片增添了額外的 CSS 規則?
- 這個卡片添加了什麼屬性、選取器或媒體查詢?我會不會重複實作了?
- 這個卡片最終合併計算出來的外觀如何?我有沒有需要加
!important
? - 我要直接修改這個
.card
嗎?會不會改爆其它地方? - 這個卡片需要增加其它 CSS 規則,好像要再命名一個類名來修改。
- 這個卡片不需要了,相關 CSS 規則要刪除。怎麼還有殘留?
- 這個人的命名怎麼這麼噁心...
你的腦中還有更多聲音?請告訴我們
什麼!上面這一堆過程只是一個卡片而已?十個組件我不就要...
傳統主要以語意的方法實踐樣式,導致你大多在“不確定的狀況”設置了“不精準的樣式”,你必須遍歷元素類名所在的檔案並透過交叉比對揣測元素最終的外觀與行為,過程可能歷經 CSS 優先級比較、排序及覆蓋等複雜運算及行為合併,隨著專案規模增長樣式變得極為複雜且不可預測,專案也越來越不可控,這不但降低了可維護性及延展性更直接摧毀生產力。
現在,用具有結構化的語言扁平地表達元素的樣式,不再盲目地將其分散,讓協作人員更快上手專案。
<div class="flex@xs translateY(-5):hover ~transform|.2s overflow:hidden bg:white bg:gray-22@dark r:10 shadow:demo">
<img class="object:cover w:144@xs" src="/images/mountain.jpg" />
<div class="p:25">
<div class="font:bold font:fade-30@light text:20">Mountain</div>
<div class="font:fade font:gray-60@dark text:14 lines:3 mt:8">A mountain is an elevated portion of the Earth's crust, generally with steep sides that show significant exposed bedrock.</div>
</div>
</div>
卡片的結構 (HTML) 與風格 (CSS) 緊湊並集中,按需求新增/刪除目標元素的樣式,越是複雜的樣式使用 Master CSS 語法就越簡單。
綜合上述來看,我們不就反對 .card
這種抽象化寫法?不,請不要誤會,我們探討的議題如標題所示《 避免過早抽象化 》,我們仍建議你於將具有重用潛力的樣式抽象化來簡化你的代碼,只是大部分的開發者包含作者本身都不敢保證自己抽象化的樣式是精準的,所以我們倡導 —— 語法為主,語意為輔。
欲了解更多抽象化概念,請參閱官方指南 —— 重用設計。
可擴展性減少 CSS
More to come... 🚧
程式碼的可移植性
傳統樣式集成者/設計師需要學習像是 React、Vue 及 Angular 等前端框架甚至建立複雜的開發環境來實踐專案的設計。只是想把設計圖代碼化,為何門檻這麼高?
現在,將所有的設計整合在 HTML 中,只要具備基本 HTML/CSS 的初學者都能上手,甚至複製&貼上就能擁有完整的介面。
一個具結構性/增強的 CSS 語言穿梭在 HTML 及 JS 中,任何平台/框架都適用。 ——Master
打開我們的 Sandbox 立即試玩。
癡迷於關注點分離
許多人認為 HTML 和 CSS 應遵循關注點分離 (SoC),但我相信你把 HTML 與 CSS 分開來撰寫更多是因為慣性和傳統的做法,關注點分離 (SoC) 一直都不是你所在意的,只是人們探討這類議題時會試圖放大該原則。
先撇除 JS,一個用戶介面的組成由 HTML 組織其構造並透過 CSS 將其風格化,接觸 HTML 大半的時間都在建置其風格或進行一些互動的編程,甚至商業邏輯也與介面息息相關,這表明了結構 (HTML) 與風格 (CSS) 具有高度耦合,且其搭配使用的頻率極高。將其分離除了造成編程上的不便,還會影響功能的研發,間接引發我們前面提到的《過早抽象化的通病》並讓元素的樣式難以預測。
借鑑當今最多用戶的前端框架 React,當時 JSX 推出時引發了一波評論,指 JSX 混合 HTML、CSS 及 JS 違背了關注點分離 (SoC),詳細可以參閱該篇 《 React and separation of concerns 》了解 React 是如何在這種混合結構下依循該原則並更加靈活。
綜觀來說,這一切與你的設計和構圖有關,JSX 也能輔助你編寫架構良好、職責明確的程式,而受惠於混合的架構,你的應用程式將更加靈活且易於維護。
進行前端工程時,關注點分離 (SoC) 應聚焦在組件化的過程而非語言的分離。 ——Master
使用語言而非實用程序框架
每個庫/框架都有著自我風格的命名規則和約束的實用程序。不同專案都遵循著不同的設計系統,利用帶有約束的工具建置自己的設計系統只會阻礙實踐的進行。
More to come... 🚧
主流框架比較
Master CSS | Tailwind CSS | Bootstrap | |
---|---|---|---|
Type | CSS Language | CSS Utility | CSS Library/Utility |
Setup | 🟢 Zero-configuration | 🔴 PostCSS, Autoprefixer, Build Tools | 🟢 Zero-configuration |
Compile Mode | |||
Ahead of time | 🚧 | 🟢 | 🟢 |
Production at runtime | 🟢 | 🔴 | 🔴 |
Server-side rendering | 🟢 | 🔴 | 🔴 |
Hybrid rendering | 🟢 | 🔴 | 🔴 |
Output Size | |||
Fixed cost of runtime | ~14KB | - | - |
Fixed cost of static output | 🟢 0KB | 🟢 0KB | 🔴 ~24KB |
Source | 🟢 Current page | 🟠 All files | 🔴 Whole lib |
Rendering | |||
Render-blocking resources | 🟢 Internal CSS | 🔴 External CSS | 🔴 External CSS |
First contentful paint | 🟢 Fastest | Fast | 🟠 Normal |
Loading | |||
Page-loaded CSS size | 🟢 Smallest | 🟠 Large | 🔴 Largest |
Cache target | HTML file | CSS file | CSS file |
Developer Tools | |||
Code-completion | 🟢 | 🟢 | 🔴 |
Syntax highlighting for class names | 🟢 | 🔴 | 🔴 |
CSS generate preview | 🟢 | 🟢 | 🔴 |
Linting | 🚧 | 🟢 | 🔴 |
More to come... 🚧
常見問答
我們蒐羅了大眾對於樂高式 CSS 常見的疑問和擔憂。若您有其它議題或建議可以直接到我們 Discord 頻道 或 Discussions。
為何不寫行內樣式就好了?
我想在視口寬度 >=1024px
的時候按鈕大些,然後禁用的時候變淡。
<button style="font-size: .875rem; text-align: center; height: 2.5rem;" disabled>Oops...</button>
行內樣式不能應用選擇器、媒體查詢和諸多 CSS 功能。現在,以最簡潔的語法實踐它們。
<button class="font:14 text:center height:40 height:56@md opacity:.5[disabled]" disabled>Yeah!</button>