漫談 CSS 方法論
大家好,我是 CUGGZ。
CSS 方法論是一種面向 CSS、由個人和組織設計、已被諸多專案檢驗且公認有效的最佳實踐。這些方法論都會涉及結構化的命名約定,並且在組織 CSS 時可提供相應的指南,從而提升程式碼的效能、可讀性以及可維護性。
根據 State of CSS 2020 的調查結果顯示,目前使用最多的五種分別為:BEM、ACSS、OOCSS、SMACSS、ITCSS。
下面就分別看看這五種 CSS 方法論!
1. BEM
BEM 全稱為 Block Element Modifier,分別表示塊(Block)、元素(Element)、修飾符(Modifier),它是由 Yandex 團隊提出的一種 CSS 命名方法。這種命名方法讓 CSS 便於統一團隊開發規範和方便維護。該方法論由以下三部分組成:
- Block:儘量以元素的性質來命名物件,例如:.list、.card、.navbar;
- Element:使用__ 兩個下劃線來連線 Block 物件,例如:.list__item、.card__img、.navbar__brand;
- Modifier:使用-- 兩個連字元連線 Block 或 Element 物件,例如:.list__item--active、.card__img--rounded、.navbar--dark。
在 BEM 中並沒有那些抽象的規則,它是基於功能為導向(Function-Oriented Programming, FOP)而設計的,不存在像是 .pl-3 這種難以理解的 class 名稱,為了保證 BEM 能夠合理的將元素模組化,需要遵守以下規則:
- 不能使用class 以外的選擇器來編寫樣式;
- 不要過度模組化,應該適當控制元素的模組化深度。
(1)Block 塊
所謂的 Block 就是指應用中可獨立存在的元素,類似於 SMACSS 中的 Layout 或 Module,這裡稱其為塊。需要遵守以下規範:
- Block 名稱需要清楚的表達其用途、功能、意義,且具有唯一性;
- Block 可以放在頁面上的任何位置,也可以相互巢狀;
- 單詞之間可以使用駝峰形式或者使用- 將其分隔。
參考以下程式碼:
.list { /* ... */ } .card { /* ... */ } .navbar { /* ... */ } .header { /* ... */ }
(2)Element 元素
如果把塊描述為一個元素,那就可以將 Element 描述為此元素的子元素。參考以下規則:
- Element 名稱需要清楚的表達元素的用途及意義;
- Element 和 Element 之間可以相互巢狀;
- Element 與Block 之間使用__ 兩個下劃線連線;
- 單詞之間可以使用駝峰式或者使用- 將其分隔。
參考以下程式碼:
.list__item { /* ... */ } .card__img { /* ... */ } .navbar__brand { /* ... */ } .header__title { /* ... */ }
這裡需要注意,Element 無法獨立於 Block 之外,其存在的目的就是子元素,元素既然不存在,那何來的子元素?如果使用 SCSS 來編寫樣式,可以改用 & 父選擇器來:
.list { display: flex; &__item { flex: 0 0 25%; } }
這樣可讀性就變好了一些,然後就可以將這些樣式應用於 HTML 元素上了:
<ul class="list"> <li class="list__item"></li> <li class="list__item"></li> <li class="list__item"></li> <li class="list__item"></li> </ul>
BEM 沒有過多複雜的概念,而且通過 class 名稱就可以知道 HTML 元素的結構,更容易理解和使用。
下面再來看一個 Element 相互巢狀的例子:
<ul class="list"> <li class="list__item"> <a href="list__item__link"></a> </li> <li class="list__item"> <a href="list__item__link"></a> </li> </ul>
一個元素通常不會只有兩層結構,很多時候都具有三層以上的結構。此時使用 BEM 編寫的程式碼就會像上面這樣。這裡的問題在於這樣的處理會造成巢狀越來越深,導致 class 名稱越來越長,HTML程式碼可讀性越來越差。如果存在多層巢狀,可以嘗試進行以下修改:
<ul class="list"> <li class="list__item"> <a href="list__link"></a> </li> <li class="list__item"> <a href="list__link"></a> </li> </ul>
這也就意味著,所有的子元素都僅僅會被 .list 所影響,link 不會綁死在 item 下,link 可以自由的放在 list 的任何位置。
(3)Modifier 修飾符
Modifier 就像 OOCSS 中的 Skin 與 SMACSS 中的 State,主要用來表示 Block 或 Element 的行為及樣式。參考以下規範:
- Modifier 名稱需要清楚的表達元素樣式、狀態或行為;
- Modifier 與 Block 或 Element 之間使用-- 兩個連字元連線;
- 單詞之間可以使用駝峰式或者使用 - 將其分隔。
參考以下程式碼:
.list__item--active { /* ... */ } .card__img--rounded { /* ... */ } .navbar--dark { /* ... */ } .header__title--size-s { /* ... */ }
Modifier 也是無法單獨存在的,Modifier 必定是作用於某個物件,這裡所指的物件可能是 Block 或 Element。如果使用的是 SCSS,可以改用 &父選擇器:
.list { display: flex; &__item { flex: 0 0 25%; &--active { color: #fffc3d; } } &--dark { color: #fff; background-color: #272727; } }
然後就可以將樣式應用在 HTML 元素上了:
<ul class="list list--dark"> <li class="list__item"></li> <li class="list__item list__item--active"></li> <li class="list__item"></li> <li class="list__item"></li> </ul>
從上面 HTML 程式碼中就可以很明顯的看到其關聯性,很容易的辨認出哪些是 Block,哪些是 Element,哪些是 Modifier,並進一步推斷出哪部分的 HTML 可以獨立使用,這也是 BEM 的初衷。
2. OOCSS
(1)基本概念
OOCSS 是 Object Oriented CSS 的縮寫,意為面向物件的CSS。它是所有 CSS 方法論中最早提出的一個,由 Nicole Sullivan 提出。可以把它理解為將 CSS 模組化。
OOCSS 提倡樣式可重用性,在編寫 CSS 樣式時需要遵循以下規則:
- 應儘量避免使用後代選擇器(.navbar ul) 或 id 選擇器(#list);
- 應儘量避免樣式依賴於結構,嘗試使用class 替代標籤選擇器。
(2)主要原則
OOCSS 有兩個主要原則:結構與樣式分離和容器與內容分離。
OOCSS 作者對這兩個原則的描述
1)結構與樣式分離(Separate structure and skin)
結構與樣式之間就像 .btn 與 .btn-primary 的關係一樣。來看例子:
$theme-colors: ( primary: blue, success: green, ); .btn-primary { display: inline-block; padding: 0.375rem 0.75rem; color: #fff; background-color: map-get($theme-colors, primary); border: 1px solid map-get($theme-colors, primary); border-radius: 0.25rem; }
平時我們可能習慣性的把全部樣式都寫在同一個class 中,就像上面程式碼一樣。此時如果我們需要新增一個主題為 success 的按鈕呢?你可能會這樣做:
.btn-primary { display: inline-block; padding: 0.375rem 0.75rem; color: #fff; background-color: map-get($theme-colors, primary); border: 1px solid map-get($theme-colors, primary); border-radius: 0.25rem; } .btn-success { display: inline-block; padding: 0.375rem 0.75rem; color: #fff; background-color: map-get($theme-colors, success); border: 1px solid map-get($theme-colors, success); border-radius: 0.25rem; }
這時,兩個按鈕就會有很多重複的樣式,每增加一個主題的按鈕,就需要增加一組樣式,這就有點浪費時間了。而 OOCSS 中的結構與樣式分離主要就是為了改善這個問題,將以上程式碼根據 OOCSS 的規範進行改寫:
.btn { display: inline-block; padding: 0.375rem 0.75rem; color: black; background-color: transparent; border: 1px solid transparent; border-radius: 0.25rem; } .btn-primary { color: #fff; background-color: map-get($theme-colors, primary); border: 1px solid map-get($theme-colors, primary); }
在 OOCSS 的概念中,表現型的 style 就屬於樣式,封裝型的 style 就屬於結構,如下所示:
- 樣式(skin):color、background-color、border-color;
- 結構(structure):display、box-sizing、padding。
那這樣做的用意是什麼呢?button 按鈕一般是這樣來使用這些樣式的:
< button class = "btn btn-primary" > Primary </ button >
這樣就可以很明確的知道這個元素的結構與樣式,以後如果想要增加不同主題的按鈕,就只需要編寫像.btn-success、.btn-danger這樣的樣式類即可,而無需再編寫按鈕的結構。
當然,也可以藉助 Sass 中的 @each 來更快速地實現多種主題按鈕的樣式:
$theme-colors: ( primary: blue, success: green, danger: red, ); .btn { display: inline-block; padding: 0.375rem 0.75rem; color: black; background-color: transparent; border: 1px solid transparent; border-radius: 0.25rem; } @each $key, $value in $theme-colors { .btn-#{$key} { color: #fff; background-color: $value; border: 1px solid $value; } }
按鈕在定義時只需新增對應的樣式即可:
button class="btn btn-primary">Primary</button> <button class="btn btn-success">Success</button> <button class="btn btn-danger">Danger</button>
相信通過上面的例子,你已經瞭解了什麼是結構與樣式分離。如果以 OOCSS 中的 OO (Object Oriented) 來描述的話,這裡的結構(Structure)就是所指的元素。以上面例子來說,我們封裝了 button 元素,以後如果要使用 button 的話,只需要編寫 .btn 結構樣式名稱與對應的樣式(skin)即可。
2)容器與內容分離(Separate container and content)
接下來看看容器與內容該如何分離。容器與內容之間就像 .card 與 .btn 的關係一樣。來看例子:
.card { position: relative; display: flex; flex-direction: column; min-width: 0; word-wrap: break-word; } .card button { display: inline-block; padding: 0.375rem 0.75rem; }
在編寫 CSS 樣式時,通常都是根據 HTML 的結構來編寫。從上面的程式碼中可以看出,.card 裡面有個 button。這樣編寫樣式就會失去靈活度,button 就完全被繫結在了 .card 裡面,OOCSS 中的容器與內容分離主要就是用來改善這個問題的,將上面的程式碼根據 OOCSS 的規範進行改寫:
.card { position: relative; display: flex; flex-direction: column; min-width: 0; word-wrap: break-word; } .btn { display: inline-block; padding: 0.375rem 0.75rem; }
容器與內容分離旨在將兩個不同的父子元素給分離出來,藉此達到父子元素不相互依賴的目的。且父子元素只存在名稱上的關係,實際上兩者都可以單獨存在並可以在不同的區域使用。這裡的 .card 就屬於容器,.btn 就屬於內容,如下所示:
- 容器(container):.container、.col-4、.header;
- 內容(content):.btn、.input、.dropdown。
需要注意,並非所有的元素都必須遵守容器與內容分離的原則,來看下面的例子:
.col-4 { flex: 0 0 100% * (4/12); position: relative; padding-left: 15px; padding-right: 15px; } .card { position: relative; display: flex; flex-direction: column; min-width: 0; word-wrap: break-word; &-body { margin: 10px auto; } }
一個物件可能同時是容器與內容。對於 .col-4 物件來說,.card 就屬於內容,而對於 .card-body 物件來說,.card就屬於容器。那你可能會想,為什麼不把 .card-body 做分離呢?不是說容器必須與內容作分離嗎?這裡的 .card-body 如果獨立存在本身是沒有任何意義的,需與.card 搭配才會有意義,在這種情況下,.card-body 屬於 .card 的繼承,就無須將其分離出來,與前面的.btn 不同,.btn 獨立存在是可以重複使用在其他元素上的。
通過上面的例子,相信大家已經理解了 OOCSS 的基本思想。其實,Bootstrap 就是根據 OOCSS 規範實現的,來看例子:
<nav class="navbar navbar-light bg-light"> <a class="navbar-brand">Navbar</a> <form class="form-inline"> <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search" /> <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button> </form> </nav>
可以看到,這段程式碼中包含了 .navbar、.navbar-light等 class,這些就屬於 OOCSS 中的結構與樣式分離,而.form-inline、.btn 等 class 就屬於容器與內容分離。如果對 OOCSS 方法論感興趣,可以閱讀一下 Bootstrap 的原始碼,其處理的細膩程度可以說是將 OOCSS 發揮的淋漓盡致。
3. SMACSS
SMACSS 全稱為 Scalable and Moduler Architecture for CSS,意為可擴充套件的模組化 CSS 結構,由 Jonathan Snook 提出。SMACSS 不僅包含了結構與樣式分離的概念,還具有極具特色的結構化命名的概念。所謂的結構化命名,就是將元素做結構分類並限制其命名,以此達到易擴充套件和模組化的目的。
SMACSS 相對於 OOCSS 更偏向於整體結構的分類及模組化 CSS,其中結構的分類包括:
- Base(基礎):不需要特別的提供字首,且不會使用到class、id 選擇器,目的在於設定元素基本樣式。例如:html、*:before、img;
- Layout(佈局):使用l- 或layout- 為次要佈局樣式提供字首,目的在於將佈局樣式與其他樣式做區分。例如:.l-header、.l-sidebar、.l-grid;
- Module(模組):使用塊本身命名為子元素樣式提供字首,目的在於快速瞭解其相關性。例如:.card、.card-header、.card-body;
- State(狀態):使用is- 為狀態樣式提供字首,通過語意化方式瞭解當前狀態。例如:.is-active、.is-hidden、.is-collapsed;
- Theme(狀態):不需要特別的提供字首,使用物件本身的名稱覆蓋其原先的主題樣式。例如:.l-header-dark、.card-dark。
(1)Base 規則
Base 主要面向某些物件的基本及預設樣式,也就是全域性的初始化(重置)樣式。在編寫這些樣式時應該遵循以下規則:
可以使用元素選擇器、後代選擇器、子選擇器以及任何偽類將基本樣式應用於元素;
不應該使用class、id 選擇器來設定元素預設的樣式;
不應該使用!important 來設定元素預設的樣式(其權重過高,無法被覆蓋)。
參考如下程式碼:
html, form { margin: 0; padding: 0; } *, *:before, *:after { box-sizing: border-box; } img { max-width: 100%; height: auto; }
(2)Layout 規則
SMACSS 中的 Layout 根據重用性將頁面劃分成主要佈局樣式和次要佈局樣式,主要佈局樣式是指不發生重用的元素,而次要佈局樣式就是指會發生重用的元素,在編寫樣式時應該遵守以下規則:
- 主要佈局樣式通常使用id 選擇器進行設定;
- 次要佈局樣式通常使用class 選擇器進行設定;
- 次要佈局樣式可提供l- 或layout- 字首用以將佈局樣式與基本樣式做區分;
- 參考 OOCSS 中的容器與內容分離的概念。
參考如下程式碼:
#header, #article, #footer { width: 960px; margin: auto; } #article { border: solid #CCC; border-width: 1px 0 0; }
和 SMACSS 規則不同的是,在 Layout 規則中的主要佈局樣式是可以使用 id 選擇器來定義的。如果想要在特定情況下更改其佈局樣式,可以與次要佈局樣式搭配使用:
#article { float: left; } #sidebar { float: right; } .l-flipped #article { float: right; } .l-flipped #sidebar { float: left; }
根據 CSS 層疊的特性,可以讓元素應用到更高層的佈局樣式,以覆蓋其預設的樣式。這裡需要注意,所謂的主要佈局樣式和次要佈局樣式都只是名稱上的定義,不要將自己的思維侷限在只能使用主要佈局樣式,也就是全部使用 id選擇器來編寫佈局樣式。大部分情況下,次要佈局樣式比主要佈局樣式使用的更多。參考下面的例子:
<div id="featured"> <h2>Featured</h2> <ul> <li><a href="…">…</a></li> <li><a href="…">…</a></li> … </ul> </div>
如果不考慮 SMACSS 中的次要佈局樣式寫法,我們可能會為 div 新增名為featured的id,然後通過 id 選擇器來設定樣式:
.l-grid { margin: 0; padding: 0; list-style-type: none; } .l-grid > li { display: inline-block; margin: 0 0 10px 10px; }
這樣就相當於把元素完全繫結死了,這裡的 #featured 只能用在div 標籤上。這不就是 OOCSS 要解決的問題嗎?可以根據 SMACSS 中的次要佈局樣式規則來解決這個問題:
.l-grid { margin: 0; padding: 0; list-style-type: none; } .l-grid > li { display: inline-block; margin: 0 0 10px 10px; }
其實 SMACSS 中的次要佈局樣式就像是 OOCSS 中的容器與內容分離原則,目的都是將依賴性降到最低。其實對於次要佈局樣式,就相當於在 OOCSS 的基礎上,加上其命名限制中的 -l 字首就可以了。
(3)Module 規則
Module 主要面向應用中的可重用元素的樣式,與 Layout 不同的地方在於其元素更為準確。基於 Module 的元素都應該以獨立元素的方式存在。在編寫是需要遵循以下規則:
不應該使用元素選擇器、id 選擇器設定元素樣式;
- 僅使用class 選擇器設定元素樣式;
- 使用元素本身命名為子元素樣式提供字首;
- 參考 OOCSS 中的結構與樣式分離概念。
參考如下程式碼:
<div class="card"> <div>Card Header</div> <div>Card Footer</div> </div>
這時我們可能會這樣編寫樣式:
.card > div { padding-left: 20px; }
這樣寫的問題在於,.card 中的 div 被繫結死了,如果想要針對裡面不同的 div 編寫樣式,就需要做出調整。SMACSS 中的 Module 建議都使用 class 選擇器來編寫樣式:
.card-header { padding-left: 20px; } .card-footer { padding-left: 20px; }
這樣就解決了 div 被繫結死的問題,同時代碼的可讀性也增加了。SMACSS 的作者建議不要使用div、span這種元素選擇器來定義樣式,而是使用 class 選擇器來強調語意化及可重用性。繼續來看下面的例子:
.pod { width: 100%; } .pod input[type='text'] { width: 50%; } #sidebar .pod input[type='text'] { width: 100%; }
前面提到,基於 Module 的元素應該能夠在應用的任意部分使用。這時編寫的的樣式就會像上面的程式碼這樣,程式碼越來越複雜,可能一不小心就忽略了CSS的優先順序,導致樣式被錯誤的覆蓋。SMACSS 建議使用以下方式來寫:
.pod { width: 100%; } .pod input[type='text'] { width: 50%; } .pod-constrained input[type='text'] { width: 100%; }
然後為指定物件新增元素與子元素 class 名稱:
<div class="pod pod-constrained">...</div>
其實它的概念就像 OOCSS 中的結構與樣式分離,只不過這裡稱之為子類化(Subclassing),通過將樣式抽離出來,以後再不同元素中使用模組時,只需要新增模組名稱與子類化模組名稱即可。
(4)State 規則
State 主要面向 Layout 或 Module 在應用上的特效及動作,其概念類似於 BEM 中的Modifier,為了保證樣式可以作用於物件,允許使用 @important。在編寫時可以參照以下規則:
- State 可以巢狀在 Layout 或 Module 中;
- 可以使用 JavaScript 改變樣式;
- 提供 is- 字首用以區分此樣式為狀態樣式;
- 可以合理的使用!important 來覆蓋樣式;
參考如下程式碼:
<ul class="nav"> <li class="nav-item"> <a class="nav-link is-active" href="#">Link</a> </li> <li class="nav-item"> <a class="nav-link" href="#">Link</a> </li> <li class="nav-item"> <a class="nav-link is-disabled" href="#">Link</a> </li> </ul>
與上面介紹的子模組樣式不同的地方在於,狀態樣式不需要繼承於任何物件,而只是單純的將樣式應用於物件,可以參考 Bootstrap 中的 .active 或 .disabled 樣式,作用就類似於上面的 is-active 與 is-disabled,為了保證狀態樣式可以作用於指定物件,在 State 中允許使用 @important。
(5)Theme 規則
Theme 主要面向應用中為主視覺定義的 Layout 或 Module 樣式,例如主題切換。在編寫時需要遵循以下規則:
- 直接使用 Layout 或 Module 定義的class 覆蓋其樣式。
參考如下程式碼:
// index.css .mod { border: 1px solid; } // themeA.css .mod { border-color: blue; }
這裡需要注意,不需要使用獨立的 class 去新增主題樣式,在 Theme 的規則中建議使用與原來 Layout 或 Module 中相同的樣式名稱,而 themeA.css 樣式會在 index.css 之後才載入,這樣就可以達到覆蓋樣式的目的,如果應用中有很多主題樣式,也只需要新增像 themeB.css 這樣的樣式檔案即可:
.mod { border-color: red; }
4. ITCSS
ITCSS 全稱為 Inverted Triangle CSS,意為倒三角CSS,由 Harry Robers 開發。ITCSS 是一種可擴充套件和可管理的架構,獨立於前處理器存在。它出現的主要目的是幫助組織專案的 CSS 檔案,從而解決由級聯和選擇器的特殊性引起的問題。
ITCSS 的目標是通過分層組織 CSS 檔案,實現了自下而上的特異性。它基於分層的概念把專案中的樣式分為七層:
上層定義的程式碼比下層定義的程式碼影響更大。因此,上層會影響下層,下層不會影響上層。下層將繼承上級的樣式,越往下越具體。
ITCSS 通過三個關鍵指標對 CSS 專案進行排序:
- 通用到顯式(explicitness):在 ITCSS 的分層中,每一層的權重是越來越大,作用的範圍越來越小。從通用的規則到非常明確的規則;
- 低特異性到高特異性(specificity):開始的時候選擇器具有最低的特異性(優先順序),隨著層數的增加,特異性也在不斷變大。因此,要儘量避免在低特異性選擇器之前編寫高特異性選擇器;
- 深遠到本地化(reach):上層定義的樣式會影響很多HTML的表現,隨著層數的增加,影響範圍逐漸減小。
(1)SETTINGS
第一層 SETTINGS 表示設定,這一層包含專案的所有全域性設定。通常會定義一些全域性變數,例如顏色、字型大小等,這一層不會生成實際的 CSS。
$main-color: #6834cb; $main-font-size: 24px;
(2)TOOLS
第二層 TOOLS 表示工具,如果使用了前處理器,可以在這一層定義 function 和 mixins。Tools 層位於 Settings 層之後,因為 mixin 可能需要全域性設定中的一些變數來作為預設引數。同樣,這一層也不會生成實際的 CSS。
@function sum($numbers...) { $sum: 0; @each $number in $numbers { $sum: $sum + $number; } @return $sum; } @mixin sample-mixin () { ... }
(3)GENERIC
第三層 GENERIC 表示通用,可以在這一層來定義重置或者標準化瀏覽器的基本樣式,這一層很少會被修改。這也是第一個實際會生成 CSS 的層。
* { padding: 0; margin: 0; } *, *::before, *::after { box-sizing: border-box; }
(4)ELEMENTS
第四層 ELEMENTS 表示元素,通常用來定義影響 HTML 單個標籤的樣式,例如 h1、p 標籤的預設樣式:
h1 { color: $main-color; font-size: $main-font-size; }
(5)OBJECTS
第五層 OBJECTS 表示物件,可以在這一層定義整個專案中可重用的頁面結構類。與上一層相比,這一層對 DOM 的影響更小,具有更高的特異性(優先順序),並且更加明確,因為現在將 DOM 的部分作為目標來設定了樣式。
.grid-container { display: grid; grid-template-columns: auto auto auto auto; }
(6)COMPONENTS
第六層 COMPONENTS 表示 UI 元件,與物件不用,元件是頁面的特定部分。比如搜尋框的樣式,為元件定義的樣式只會影響到對應的元件。這一層比上一層更加明確,因為現在為 DOM 設計了明確的樣式。
.c-btn { display: flex; justify-content: center; align-items: center; ... &--primary { background-color: #ff5959; color: #fff; } &--large { font-size: 16px; padding: 16px 14px; ... } }
(7)TRUMPS
這一層也稱為 Utilities,包含所有那些覆蓋之前層中定義的任何其他規則的規則。它是唯一允許使用 !important 的層。
.d-none { display: none!important; }
(8)專案結構
那這七層結構的 CSS 檔案該如何組織呢?主要有兩種方式:
- 每一層一個資料夾:
- 檔名使用層的名字作為字首:
在使用樣式時,就需要按照層的順序來引用這些 CSS,就像這樣:
@import "settings.global.scss"; @import "settings.colors.scss"; @import "tools.functions.scss"; @import "tools.mixins.scss"; @import "generic.box-sizing.scss"; @import "generic.normalize.scss"; @import "elements.headings.scss"; @import "elements.links.scss"; @import "objects.wrappers.scss"; @import "objects.grid.scss"; @import "components.site-nav.scss"; @import "components.buttons.scss"; @import "components.carousel.scss"; @import "trumps.clearfix.scss"; @import "trumps.utilities.scss"; @import "trumps.ie8.scss";
5. ACSS
ACSS 的全稱為 Atomic CSS,意為原子CSS。它專注於建立很多小型的 CSS 樣式類,以便在 HTML 上使用。這種方法旨在提供高度精細和可重用的樣式,而不是為每個元件提供規則。這可以減少特異性(優先順序)衝突並以可預測的方式使樣式更具可變性。這種方法有助於減少程式碼冗餘和覆蓋 CSS 樣式的混淆。
參考以下程式碼:
.mb-sm { margin-bottom: 16px; } .mb-lg { margin-bottom: 32px; } .color-blue { color: #1e90ff; }
在HTML中這樣來使用:
<div class="mb-lg"> <p class="mb-lg color-blue">Blue text</p> <img class="mb-sm" /> </div>
ACSS 有一些程式設計方法,可以根據使用者新增到 HTML 的類或屬性自動生成 CSS。Atomizer 就是這樣的一個工具,它允許將 HTML 進行如下定義:
<div class="Mb(32px)"> <p class="Mb(32px) C(#1e90ff)">Blue text</p> <img class="Mb(16px)" /> </div>
這樣在構建時就會自動生成以下CSS:
.Mb\(16px\) { margin-bottom: 16px; } .Mb\(32px\) { margin-bottom: 32px; } .C\(#1e90ff\) { color: #1e90ff; }
注意,單獨使用 ACSS 會導致類的數量多到難以管理,並且 HTML 結構會非常臃腫。因此,通常只會使用 ACSS 原則來建立定義一致、可重用的宣告塊的輔助類。
- 一文給你搞定Elasticsearch技術掃盲
- Go程式語言的真正優點是什麼?
- 用Python爬了我的微信好友,他們是這樣的...
- 位元組面試也會問SPI機制?
- Volatile關鍵字能保證原子性麼?
- 種草 Vue3 中幾個好玩的外掛和配置
- Vue 狀態管理未來樣子
- 一門語言的作用域和函式呼叫是如何實現的
- 關於多執行緒同步的一切:偽共享
- Swift 與 Go:蘋果與谷歌的較量
- Android 自定義View - 柱狀波形圖 wave view
- Android技術分享|【Android踩坑】懷疑人生,主執行緒修改UI也會崩潰?
- 安卓TV外掛化9.0內聯崩潰原因及解決方案
- 測試員進階技能:如何有效地利用單元測試報告?
- Tekton 實戰完整示例
- 位元組的前端監控 SDK 是怎樣設計的
- 用Python繪製了若干張詞雲圖,驚豔了所有人
- 馬化騰:為什麼你們不在乎QQ等級,不用QQ了嗎?
- 幾個友好Java程式碼習慣建議
- Python 實現單例模式的五種寫法