體驗基於 Virtual CSS 的新 CSS 框架--Master Styles 初次使用心得

Eason Lin
10 min readMar 27, 2022

--

Photo by Kalen Emsley on Unsplash

幾天前,我在一個前端社群看見版友(或說作者本人)分享了 Master Styles,一個基於 Virtual CSS 概念的 CSS 框架,由於首次聽到 Virtual CSS 這個新穎的詞彙,加上他是由台灣人撰寫,就懷著好奇的心花了點時間研究及體驗。

Virtual CSS

關於 Vitrual CSS,作者在文件中提及:

『Virtual CSS is the concept of expressing CSS rules through class syntax.』

照翻就是:Virtual CSS 是一種藉由 Class 語法來表達 CSS 規則的概念

其原理就是將一個虛擬的樣式表保存在記憶中,並即時與實際的 CSS 樣式表同步,核心是使用 Mutation Observer,會觀察 DOM 樹並透過一個特殊的規則引擎去遍歷每個 class,將其轉換為 CSS 並注入至 style。

Why

每個框架/函式庫/工具的誕生都是為了解決一個以上痛點,Master Styles也不意外。以下是我參閱了官方文件並加入了一點自己的看法作為超譯。

相較 Master Styles,其他 CSS 開發時可能碰到的痛點:

過早的抽象化

除非有非常充裕的時間,通常在開發時較難找出每個區塊樣式的共同點和重複的部分,如果前期就大量進行了不準確的抽象化,容易降低頁面配合需求變動的靈活性,若樣式大量被使用也可能會有修改不便甚至改A壞B的隱憂。

取名的時間成本

假設我們要為一個樣式命名,通常我們會看:

  • 這個區塊應該被稱為什麼?
  • 先來看看內容有些什麼…
  • 好,看起來像是 xxx
// style.css
.xxx {
font-size: 24px;
/* ... */
}

可能只是幾行 CSS,幾分鐘就過去了。

維護專案 CSS 所在的時間成本

在維護專案時,尋找 CSS 容易耗費額外的時間,通常需要仰賴瀏覽器 devtool 和編輯器的搜尋功能來降低尋找時間。

入門時的學習曲線高

常見的樣式開發技術如 CSS-in-JS、Atomic CSS 本身都有自己的學習曲線,即使是使用傳統的 CSS 建構的專案,首次進入時也得花時間閱讀專案文件或靠自己觀察出 CSS 的檔案架構。

CSS-in-Class

對於這些問題,在使用 CSS in Class 進行開發時,

  • 無須抽象化,直接寫就對了
  • 寫出像是 CSS 的 class 名稱
  • 不必查找大量 CSS 花費額外時間成本
  • 學習曲線低

導入

CDN 範例

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://unpkg.com/@master/normal.css" rel="stylesheet">
<script src="https://unpkg.com/@master/style"></script>
<script src="https://unpkg.com/@master/styles"></script>
</head>
<body>
<h1 class="font:40 font:heavy font:italic m:50 text:center">Hello World</h1>
</body>

不需要 Webpack、不需要任何額外打包工具,就是這麼單純。

亦可藉由 NPM 安裝:

// 安裝指令
npm install @master/styles @master/normal.css
// 引入
import '@master/styles';
@import '@master/normal.css';

以下是截至官方文件的範例:

語法範例1

<p class="text-align:center font-size:1rem background-color:red-50">Lorem ipsum dolor sit amet.</p>

有學習過 CSS 的應該不難猜出,三個 class 分別套上了置中、文字大小及背景色。

覺得寫法太長?試試更簡潔的:

<p class="text:center font:16 background:red-50">Lorem ipsum dolor sit amet.</p>

再來個更簡潔的:

<p class="t:center f:16 bg:red-50">Lorem ipsum dolor sit amet.</p>

三種寫法都能得到相同的結果。

語法範例2 — 可給予多個值的屬性

Master Styles 以分號做為區隔多個值的屬性樣式,例如:

<p class="animation:fade;1s;ease transition:opacity;.3s margin:16;32;16;40">Lorem ipsum dolor sit amet.</p>

animation:fade;1s;ease 代表了 animation: fade 1s easetransition:opacity;.3s 代表了 transition: opacity 0.3s;而 margin:16;32;16;40 則代表了 margin: 16px 32px 16px 40px

覺得太長嗎?試試這個:

<p class="@fade;1s;ease ~opacity;.3s m:16;32;16;40">Lorem ipsum dolor sit amet.</p>

作者對於 animation 以 @ 作為簡寫,~ 作為 transition 簡寫也寫出自己如此設計的原因,有興趣可參考官方文件

其他寫法如 !important、偽元素、偽類別、calc、var、斷點等等的寫法,在官方文件中都有詳細敘述及範例,我這邊就不再贅述。

樣式複用

當專案慢慢變大,需要對樣式進行複用時,就必須仰賴打包工具進行輔助,以 Vue Cli 和 create-react-app 為例:

// 兩個架構都使用同路徑及內容
// src\classes\outline-button.js
export const OUTLINE_BUTTON_CLASS = `
b:1px;solid;#000 p:12 r:4 bg:aqua bg:navy:hover color:#fff:hover ~all;300ms;ease
`;

// -----------------------------------------------------------
// Vue (以Vue Cli為例)
// some-random-component.vue
<template>
<div>
<button :class="OUTLINE_BUTTON_CLASS">Hover me!</button>
</div>
</template>
<script>
import { OUTLINE_BUTTON_CLASS } from "../classes/outline-button";
export default {
name: "HelloWorld",
data() {
return {
OUTLINE_BUTTON_CLASS: OUTLINE_BUTTON_CLASS,
};
},
};
</script>
// main.js
import "@master/normal.css";
import "@master/styles";
// -----------------------------------------------------------
// React (以create-react-app為例)
// src/App.js
import { OUTLINE_BUTTON_CLASS } from "./classes/outline-button";
import "./App.css";
function App() {
return (
<div className="App">
<button className={OUTLINE_BUTTON_CLASS}>Imma leave my door open</button>
</div>
);
}
export default App;// index.js
import "@master/normal.css";
import "@master/styles";

(關於樣式複用,官方文件目前看起來還沒有很清楚的說明,如果未來有補充了還煩請打臉我的寫法,感謝!)

個人心得

在大致閱讀了官方文件並到 Frontend Mentor 找了一個小專案來切版後,專案的原始碼我會放在最下方。大致分享一些心得。

優缺點及適合場景

優點

  • 非常輕量,CDN所需的資源總容量不超過13KB
  • 極低的導入成本,可不依賴打包工具
  • 可與其他 CSS 框架並行(須注意原本專案是不是就有 reset.css 或 normalize.css)

缺點

  • 核心需仰賴 JavaScript 驅動,在不允許 JS 的瀏覽器會完全失效
  • 複用樣式需要仰賴打包工具,部分架構如 Laravel 目前尚不知複用架構的做法,且若複用樣式相較傳統 CSS 寫法我覺得沒那麼好
  • 尚無法完全捨棄 <style> 或 .css,如若需要自定義 keyframes 或 CSS 變數依然需要用原生的寫法寫
  • 若標籤的樣式過多,可能造成可讀性差的問題

適合

  • 走快速開發且注重載入效能的頁面
  • 沒有 Webpack 或其他打包工具的專案

不適合

  • 需支援舊瀏覽器的頁面
  • 已有高度模組化 CSS 的專案

可嘗試的情境

  • 一次性的活動頁
  • 小型專案

使用體驗

使用上提供的小專案切版作為體驗,在沒有任何 CSS 包袱情況下,我個人覺得寫起來蠻爽的,尤其是簡寫部分,以往要移動滑鼠去開啟 style.css 的時間就已經寫好一個 HTML 元素所需的樣式,我個人也非常喜歡 var 的簡寫:

<div class="h:$(size)">Guess my height!</div>

看著就覺得滿優雅的。

但就如同上面所述,我覺得最適合它的場景沒有很多,但框架、技術、工具都是很主觀的,實際體驗才會知道適不適合,且這個專案是去年年底才釋出 Alpha 版,實際年齡可能連一歲都不到,官方文件也有很多還在撰寫的地方,我個人是很看好它的未來的。

關於 Master Styles 的體驗心得就記錄到這,希望能幫助到正在觀望的人,與其觀望,不如找個版型切切看吧!

實際切版頁面

及原始碼:

References:

--

--