小而美的 css 的原子化

小而美的 css 的原子化

http://zoo.zhengcaiyun.cn/blog/article/css

什麼是 CSS 原子化

引用 文章 Let’s Define Exactly What Atomic CSS is 中定義:

Atomic CSS is the approach to CSS architecture that favors small, single-purpose classes with names based on visual function.

譯文:

原子化 CSS 是一種 CSS 的架構方式,它傾向於小巧且用途單一的 class,並且會以視覺效果進行命名。

.bg-blue { background-color: #357edd; } 
.f1 { font-size: 3rem; }
.m0 { margin: 0; }

通常情況下我們是怎麼寫 CSS 的

原子化 CSS 是一個 CSS 框架, 在沒有對應的 CSS 框架的項目中,是如何寫 CSS 的。我們引用  Challenging CSS Best Practices 文中例子來看看。

如圖所示:我們要實現一個類似訪問記錄組件,右邊是訪問人的頭像,左側是訪問的描述。

對應代碼.

<div class="media">
  <a href="https://www.zcygov.cn/" class="img">
    <img width="40" src="logo.png" alt="zcy" />
  </a>
  <div class="bd">@小明 14 分鐘之前</div>
</div>
<style>
.media {
  margin: 10px;
}
.media,
.bd {
  overflow: hidden;
  _overflow: visible;
  zoom: 1;
}
.media .img {
  float: left;
  margin-right: 10px;
}
.media .img img {
  display: block;
}
</style>

新增一個設計,需要把頭像放在右側,描述在左側,如圖所示

我們通過新增一個類名 imgExt,右浮動

代碼:

<div class="media">
  <a href="https://www.zcygov.cn/" class="imgExt">
    <img width="40" src="https://sitecdn.zcycdn.com/f2e-assets/b37c37db-ce59-4bfe-a889-5c8615d008c8.png" alt="zcy" />
  </a>
  <div class="bd">@小明 14 分鐘之前</div>
</div>
<style>
  ...
/* 圖片在右側 */
.media .imgExt {
  float: right;
  margin-left: 10px;
}
</style>

這時候有來一個新設計,要求組件在頁面右側欄中時候,字體變小

代碼:

<div id="rightRail">
<div class="media">
  <a href="https://www.zcygov.cn/" class="imgExt">
    <img width="40" src="https://sitecdn.zcycdn.com/f2e-assets/b37c37db-ce59-4bfe-a889-5c8615d008c8.png" alt="zcy" />
  </a>
  <div class="bd">@小明 14 分鐘之前</div>
</div>
<style>
</div>
<style>
  ...
/* 頁面右側容器中時,字體變小 */
#rightRail .bd {
    font-size: smaller;
}
</style>

用這種方式寫 CSS 存在存在以下的問題

雖然文中的代碼樣例是 2013 年的,9 年過去了,發現自身的老項目中還是存在着類似問題。

.text-overflow-dot {
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
}
...
  .title-number {
    width: 55%;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
  }
...  
.invoice-content {
    div {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
 }
.time-tip {
  i {
    margin-left: 10px;
    cursor: pointer;
  }
}

#service-charge-Bill {
  .zcy-search-panel .ant-form-item-label {
    min-width: 80px;
  }
}

.invoice-tpl-container {
  max-height: 360px;
  overflow-y: scroll;
}

.add-invoice-tpl-item {
  border: 1px dashed rgb(209, 215, 232);
  text-align: center;
  height: 160px;
  line-height: 160px;
  margin: 10px;
}

.invoice-tpl-item {
  border: 1px solid rgb(209, 215, 232);
  margin: 10px;
  height: 160px;
  position: relative;

  .invoice-content {
    overflow: hidden;
    padding: 20px;
    height: 119px;

    div {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .invoice-type-mark {
      display: inline-block;
      width: 20px;
      height: 20px;
      line-height: 20px;
      text-align: center;
      color: white;
      background-color: #3177fd;
    }
  }

  .operate {
    position: absolute;
    bottom: 0;
    width: 100%;
    border-top: 1px solid rgb(209, 215, 232);
    height: 40px;
    line-height: 40px;
    text-align: center;
  }
}

.invoice-tpl-item.active {
  border-color: #3177fd;
}

.default-mark {
  position: absolute;
  right: 0;
  top: 0;
  background-color: #bbb;
  color: white;
  padding: 0 5px;
}
.catalogue {
 &-title {
   display: flex;
   &-btns {
     flex-grow: 1;
     align-items: center;
     text-align: right;
     .ant-btn {
       margin: 0 5px;
     }
   }
 }
 &-content {
   height: calc(100% - 60px);
   overflow: auto;
   padding: 18px;
   .cy-tree {
     width: 80%;
   }
   .ant-tree {
     overflow: auto;
   }
 }
 &-tree {
   height: calc(100% - 22px);
   .ant-input {
     width: 100%;
     &-search {
       width: 80%;
       flex-grow: 1;
     }
   }
 }
}

我們大多數項目是後臺管理的項目,自身也有一個成熟的組件庫。這樣的項目 CSS 的工作量是比較少的。所以項目開始之處,沒有指定對應 CSS 規範和架構,上訴的問題日積月累,導致現有項目 CSS 代碼狀況較差,維護起來讓人十分頭大,急需整理項目 CSS 框架和規範整體項目的 CSS。我們這邊調研幾個比較流行的 CSS 框架,以下是幾個框架簡要介紹。

CSS 框架介紹

原子化 CSS

定義

原子化 CSS 是一種 CSS 的架構方式,它傾向於小巧且用途單一的 class。

原則

  • class 的命名按照功能

  • class 的功能單一

相關資料

https://css-tricks.com/lets-define-exactly-atomic-css/

OOCSS (Object-Oriented CSS  面向對象 CSS)

定義

OOCSS (Object-Oriented CSS  面向對象 CSS) 是組織 CSS 的領先的模塊化或基於組件的系統。它是 Nicole Sullivan 在 2008 年在 Web Directions North 大會上首次提出的,核心就是編寫可複用和可維護的樣式

原則

  • 分離結構(structure)和皮膚(skin)。 您應該在基礎對象中保留結構和位置,並在擴展類中保留視覺特徵(如 background 或  border)。這樣您就不必覆蓋視覺屬性。

  • 分離容器(container)和內容(content)。 永遠不要在 CSS 中模仿 HTML 的結構。換句話說,不要在樣式表中引用標籤或 ID。相反,嘗試創建和應用描述相關標籤使用的類。並將嵌套類保持在最低限度。

相關資料

http://oocss.org/

SMACSS (Scalable and Modular Architecture for CSS)

定義

SMACSS(Scalable and Modular Architecture for CSS)編寫模塊化、結構化和可擴展的 CSS。

原則: SMACSS 認爲 CSS 有 5 個類別,我們通過這 5 種類別來拼湊出完整的 class

  • Base 基礎樣式

  • Layout 佈局樣式

  • Module 模塊樣式

  • State 狀態樣式

  • Theme 主題樣式

相關資料

http://smacss.com/

BEM( block, element, modifier

定義

首先 BEM 是一個分層系統,它把我們的網站分爲三層,這三層正好對應着 BEM 三個英文單詞的簡寫 block, element, modifier,分爲爲 塊層、元素層、修飾符層

原則

  • 使用__兩個下劃線將塊名稱與元素名稱分開

  • 使用--兩個破折號分隔元素名稱及其修飾符

  • 一切樣式都是一個類,不能嵌套

相關資料

https://getbem.com/

ITCSS

定義

理智、可擴展、可管理 CSS 架構

原則: 類似 SMACSS 對 CSS 元素進行了分層

  • Settings – 與預處理器一起使用,包含顏色、字體等定義

  • Tools – 工具與方法,比如 mixins,Settings 與 Tools 都不會產生任何 CSS 代碼,僅僅是輔助函數與變量

  • Generic – 通用層,比如 reset htmlbody 的樣式

  • Elements – 對通用元素的樣式重置,比如  a p div 等元素的樣式重置 Objects – 類似 OOCSS 中的對象,描述一些常用的基礎狀態

  • Components – 對組件樣式的定義,一個 UI 元素基本由 Objects 與 Components 組成

  • Utilities – 工具類,比如 .hidden

相關資料

https://getbem.com/

考慮到我們自身項目項目是一個後臺管理類的項目,有成熟組件庫。日常 CSS 開發工作量和複雜度不高。我們也希望有一個快速可以落地的框架方案,且實現的成本較低。我們對比幾個框架後,選擇 CSS 原子化作爲我們的 CSS 的架構方案。CSS 原子化提供現成的解決方案,幾乎就是拿就用( tailwindcss  ,windicss )。而且成體接入和改造成本也是最低的,不用自己再製定命名規則和使用規範。

CSS 原子化是如何解決這些問題的

首先我們看看前文中提到組件使用 CSS 原子化是如何實現的,項目中已引入 winidicss。

<div class="overflow-hidden mr-1">
  <a href="https://www.zcygov.cn/" class="float-left mr-1">
    <img
      width="30"
      src="logo.png"
      alt="zcy"
    />
  </a>
  <div class="overflow-hidden text-sm">@小明 14 分鐘之前</div>
</div>

這邊如果需要 頭像在右側的,只需要將 float-left 替換成 float-right 即可。

基本上解決了項目現有的 CSS 問題,而且 CSS 的維護性有了很大的提高,CSS 編碼的成本相對於以前有明顯的降低。

使用體驗

功能類優先的 原子化 CSS 框架,帶來便利的同時,也是存在一些問題的。最突出的問題就是 html 上類過多,如果要實現一個相同功能,需要複製一個很長的字符串。這個情況下的可讀性和複用性是比較差的。

比如一個簡單按鈕的例子:涉及到背景,字體,邊距,邊框的設置,類就很多

<button
class
>
  Button
</button>

而且相同樣式複用需要整塊的複製。雖然這提供屬性化(https://windicss.org/features/attributify.html)的模式,Shortcuts(https://windicss.org/features/shortcuts.html)和指令(https://cn.windicss.org/features/directives.html)來解決相同功能類集合過長,過多的問題。但是實際上可以發現,原子化框架自身是無法解決這個問題的。

當然你有可以通過設計變量的方式來解決這個問題,但其實上和命名一個類名沒有多大的區別。

const myButtonClass = "bg-blue-400 text-sm text-white font-mono font-light py-2 px-4 border-2 border-rounded border-blue-200"

<button
className={myButtonClass}
>
  Button
</button>

在選定一個 CSS 框架作爲項目的 CSS 規範的時候,需要考慮自身項目的現狀,如果項目本身 CSS 複雜度較高,整體工作量較多,原子化的 CSS 是不太適合的。

總結

原子化的 CSS 可以幫助我們的項目解決 CSS 命名,代碼重複,不斷膨脹的問題,但它也不是一勞永逸的,實際使用中還是會有問題,關鍵在與開發者自身的取捨,權衡利弊。不要一個規則用到底,遇到問題也不變通。工具和思想發明其實也是爲了解決你實際的問題。你會發現 windicss (https://cn.windicss.org/posts/v30-utilities.html) 這類工具優先的 css 框架,也是添加蠻多額外的功能來彌補原子化 CSS 框架的缺陷,提升自身使用體驗。

參考連接

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/oMNhcQbN2ycOXkn-av1JVQ