css模塊化

為什么要CSS模塊化?

你是否為class命名而感到苦惱?
你是否有怕跟別人使用同樣class名而感到擔(dān)憂?
你是否因?qū)蛹?jí)結(jié)構(gòu)不清晰而感到煩躁?
你是否因代碼難以復(fù)用而感到不爽?
你是否因?yàn)閏ommon.css的龐大而感到恐懼?

如果有,恭喜你來對(duì)了地方!本文會(huì)為您一一解決這些難題!

那么如何解決CSS命名問題?

我們看一下CSS是怎么規(guī)范的:使用有意義的或通用的ID和class命名。ID和class的命名應(yīng)反映該元素的功能或使用通用名稱,而不要用抽象的晦澀的命名。反映元素的使用目的是首選;使用通用名稱代表該元素不表特定意義,與其同級(jí)元素?zé)o異,通常是用于輔助命名;使用功能性或通用的名稱可以更適用于文檔或模版變化的情況。

常用命名(多記多查英文單詞):page、wrap、layout、header(head)、footer(foot、ft)、 content(cont)、menu、nav、main、submain、sidebar(side)、logo、banner、 title(tit)、popo(pop)、icon、note、btn、txt、iblock、window(win)、tips等

注:類型選擇器避免同時(shí)使用標(biāo)簽、ID和class作為定位一個(gè)元素選擇器;從性能上考慮也應(yīng)盡量減少選擇器的層級(jí)。

如何構(gòu)建結(jié)構(gòu)清晰的CSS?

大家都說CSS學(xué)和寫都簡單,那么寫了多年CSS的同學(xué)是否有靜下來思考過,自己寫CSS是有較為系統(tǒng)的和具有一定規(guī)范的,而不是草率的寫CSS。另外就是自己寫的CSS在團(tuán)隊(duì)中,別的同學(xué)是否能看到代碼就知道您寫的是什么?如果沒有,那不仿看看這里提到的一些概念與思想,比如:Sass 、SCSS、LESS、BEM、OOCSS、AMCSS等。讓我們一起來深入了解css吧?

  • 首先了解一下BEM(我個(gè)人比較喜歡的)

BEM的意思就是塊(block)、元素(element)、修飾符(modifier),是由Yandex團(tuán)隊(duì)提出的一種前端命名方法論。這種巧妙的命名方法讓你的CSS類對(duì)其他開發(fā)者來說更加透明而且更有意義。BEM命名約定更加嚴(yán)格,而且包含更多的信息,它們用于一個(gè)團(tuán)隊(duì)開發(fā)一個(gè)耗時(shí)的大項(xiàng)目。

命名約定的模式如下:

.block{}   // 塊即是通常所說的 Web 應(yīng)用開發(fā)中的組件或模塊。每個(gè)塊在邏輯上和功能上都是相互獨(dú)立的。
.block__element{}  // 元素是塊中的組成部分。元素不能離開塊來使用。BEM 不推薦在元素中嵌套其他元素。
.block--modifier{}   // 修飾符用來定義塊或元素的外觀和行為。同樣的塊在應(yīng)用不同的修飾符之后,會(huì)有不同的外觀。

BEM不是一個(gè)框架,它只是一種思想

BEM優(yōu)缺點(diǎn)

優(yōu)點(diǎn):BEM 的優(yōu)點(diǎn)在于所產(chǎn)生的 CSS 類名都只使用一個(gè)類別選擇器,可以避免傳統(tǒng)做法中由于多個(gè)類別選擇器嵌套帶來的復(fù)雜的屬性級(jí)聯(lián)問題。在 BEM 命名規(guī)則中,所有的 CSS 樣式規(guī)則都只用一個(gè)類別選擇器。因此所有樣式規(guī)則的特異性(specificity)都是相同的,也就不存在復(fù)雜的優(yōu)先級(jí)問題。這可以簡化屬性值的層疊規(guī)則。代碼清單中的命名規(guī)則的好處在于每個(gè) CSS 類名都很簡單明了,而且類名的層次關(guān)系可以與 DOM 節(jié)點(diǎn)的樹型結(jié)構(gòu)相對(duì)應(yīng)。
缺點(diǎn): CSS 類名會(huì)比較長而且復(fù)雜。乍看之下,根據(jù) BEM 命名規(guī)則產(chǎn)生的 CSS 類名都會(huì)很復(fù)雜,但實(shí)際上在熟悉了命名規(guī)則之后,可以很容易理解其含義。

  • 我們?cè)倏匆幌翺OCSS(面向?qū)ο驝SS)

OOCSS 表示的是面向?qū)ο?CSS(Object Oriented CSS),是一種把面向?qū)ο蠓椒▽W(xué)應(yīng)用到 CSS 代碼組織和管理中的實(shí)踐。 OOCSS最關(guān)鍵的一點(diǎn)就是:提高他的靈活性和可重用性。這個(gè)也是OOCSS最重要的一點(diǎn)。OOCSS主張是通過在基礎(chǔ)組件中添加更多的類,從而擴(kuò)展基礎(chǔ)組件的CSS規(guī)則,從而使CSS有更好的擴(kuò)展性。

我們有一個(gè)容器是頁面page的1/4寬,有一個(gè)藍(lán)色的背景,1px灰色的邊框,10px的左右邊距,5px的上邊距,10px的下邊距,以前對(duì)于這樣一個(gè)樣式,我們常常給這個(gè)容器創(chuàng)建一個(gè)類,并把這些樣式全部加上。像下面這樣。

// template
<div class="size1of4"></div>
// style
.size1of4 {
  background: blue;
  border: 1px solid #ccc;
  margin: 5px 10px 10px;
  width: 25%;
}

然而使用oocss的話,我們不這樣做,我把為這個(gè)容器創(chuàng)建更多的類,并且每個(gè)樣式對(duì)應(yīng)一個(gè)類,這樣是為了后面可以重復(fù)使用這些組件的樣式,避免重復(fù)寫相同的樣式,就拿這個(gè)實(shí)例來說,我們給這個(gè)容器增加下面的類:bgBlue,solidGray,mts,mlm,mrm,mbm

// template
<div class="size1of4 bgBlue solidGray mts mlm mrm mbm"></div>
// style
.size1of4 {width: 25%;}
.bgBlue {background:blue}
.solidGray {border: 1px solid #ccc}
.mts {margin-top: 5px}
.mrm {margin-right: 10px}
.mbm {margin-bottom: 10px}
.mlm {margin-left: 10px}

OOCSS的優(yōu)點(diǎn)

  • 減少CSS代碼
  • 具有清潔的HTML標(biāo)記,有語義的類名,邏輯性強(qiáng)的層次關(guān)系
  • 語義標(biāo)記,有助于SEO
  • 更好的頁面優(yōu)化,更快的加載時(shí)間(因?yàn)橛泻芏嘟M件重用)
  • 可擴(kuò)展的標(biāo)記和CSS樣式,有更多的組件可以放到庫中,而不影響其他*
    的組件
  • 能輕松構(gòu)造新的頁面布局,或制作新的頁面風(fēng)格

OOCSS的缺點(diǎn)

  • OOCSS適合真正的大型網(wǎng)站開發(fā),因?yàn)榇笮途W(wǎng)站用到的可重用性組件特別的多,如果運(yùn)用在小型項(xiàng)目中可能見不到什么成效。所以用不用OOCSS應(yīng)該根據(jù)你的項(xiàng)目來決定。

  • 如果沒用巧妙的使用,創(chuàng)建組件可能對(duì)于你來說是一堆沒用的東西,成為一爛攤子,給你的維護(hù)帶來意想不到的杯具,說不定還是個(gè)維護(hù)的噩夢(mèng)。

  • 最好給每一個(gè)組件備寫一份說明文檔,有助于調(diào)用與維護(hù)

  • AMCSS(屬性模塊)

屬性模塊或者說AM,其核心就是關(guān)于定義命名空間用來寫樣式。通俗的講就是,給一個(gè)元素加上屬性,再通過屬性選擇器定位到這個(gè)元素。達(dá)到避免過多的使用class。

// template
<div am- Row ></div>
<div am- Column = "12"> Full < /div> 
</ div> <div am- Row > <div am- Column = "4"> Thirds </div> 
<div am- Column = "4"> Thirds </div> 
<div am- Column = "4"> Thirds < /div> </ div> 
// style 
[am- Row ] { /* max-width, clearfixes */ } 
[am- Column ~= "1" ] { /* 1/12th width, floated */ } 
[am- Column ~= "2" ] { /* 1/6th width, floated */ } 
[am- Column ~= "3" ] { /* 1/4th width, floated */ } 
[am- Column ~= "4" ] { /* 1/3rd width, floated */ } 
[am- Column ~= "5" ] { /* 5/12th width, floated */ } /* etc */ 
[am- Column ~= "12" ] { /* 100% width, floated */ }

你會(huì)注意到第一件事情就是有am-前綴。這也是AM核心部分,確保屬性模塊不會(huì)與現(xiàn)有屬性沖突。你可以使用你自己喜歡的任何前綴名,我常使用的是ui-、css-或者其他前綴,但這些示例中使用的是am-前綴。HTML的有效性對(duì)你或你的項(xiàng)目來說是非常重要,就類似于使用data-前綴開頭定義的屬性類似。
你可能會(huì)注意到的第二件事情就是類似于1、4或12這樣的值,使用類名變得極為麻煩——造成沖突的機(jī)會(huì)很多。但定義了我們自己的命名空間,實(shí)際上將空間變得很小,用于工作中不會(huì)造成沖突。為了更好的工作,可以自由選擇最簡明而且有意義的標(biāo)記。

我們雖然有這么多的好的方案去解決css的一些難題,但是有沒有一種東西或者工具來代替我們?nèi)プ鲞@些呢,作為一個(gè)程序員我們不喜歡做太麻煩的事情。那么接下來我們談一談css的構(gòu)建工具

OK,我們來探索一下webpack是怎么實(shí)現(xiàn)模塊化的。

With :local (without brackets) local mode can be switched on for this selector. :global(.className) can be used to declare an explicit global selector. With :global (without brackets) global mode can be switched on for this selector.
webpack會(huì)把class分為兩種,一種是local(本地的),一種是global(全局的)。默認(rèn)導(dǎo)出的都是本地的,但是你可以通過 :global(...)開關(guān)來控制導(dǎo)出全局。下面我們看一下栗子。

// 輸入
: local (.className) { background: red; }
: local .className { color: green; } 
: local (.className .subClass) { color: green; } 
: local .className .subClass : global (. global - class -name) { color: blue; } 
// 導(dǎo)出 
._23_aKvs-b8bW2Vg3fwHozO { background: red; } 
._23_aKvs-b8bW2Vg3fwHozO { color: green; } 
._23_aKvs-b8bW2Vg3fwHozO ._13LGdX8RMStbBE9w-t0gZ1 { color: green; } 
._23_aKvs-b8bW2Vg3fwHozO ._13LGdX8RMStbBE9w-t0gZ1 . global - class -name { color: blue; }

:local(className)被編譯為唯一可識(shí)別的標(biāo)示,:global(className)原樣輸出,當(dāng)然我們也可以控制導(dǎo)出的格式。配置如下:

{
  test: /\.css$/ ,
  use : [
    {
     loader: 'css-loader',
     options: {
       modules: true ,
       localIdentName: '[path][name]__[local]--[hash:base64:5]'
     }
   }
 ]
}
CSS的scoped實(shí)現(xiàn)?

現(xiàn)在在各種框架中都會(huì)有scoped屬性,使我們的css具有模塊化性質(zhì),不會(huì)污染到其他模塊,那么scoped是如何實(shí)現(xiàn)的呢?我們一起來揭開它神秘的面紗吧?

如果你是一個(gè)勤奮好學(xué)的同學(xué),你一定會(huì)發(fā)現(xiàn)在HTML的style標(biāo)簽中有一個(gè)scoped屬性。讓我們來一起看一下這個(gè)屬性的神奇吧。

一直以來,文檔上的STYLE元素通常都是作用域全局的,選擇器按照全局的CSS優(yōu)先規(guī)則來設(shè)置的。要實(shí)現(xiàn)局部的選擇需要先選到容器元素,再用后代選擇器來實(shí)現(xiàn)。scoped屬性可以讓STYLE元素不再作用于全局,而從當(dāng)前STYLE元素所在的容器開始選擇后代。

<div>
  <style scoped >
    span {color:red;}
  </style> 
  <span> 我是第1個(gè)DIV內(nèi)的SPAN </span>
</div> 
<div> 
  <style scoped > 
    span {color:green;}
  </style> 
  <span> 我是第2個(gè)DIV內(nèi)的SPAN </span> 
</div>
<div> 
  <span> 我是第3個(gè)DIV內(nèi)的SPAN </span> 
</div>

結(jié)果:

結(jié)果

我們可以看見第三個(gè)div并沒有被第一及第二個(gè)style所感染,也就是說帶有scoped屬性的css是一個(gè)獨(dú)立的作用域,不會(huì)影響到其它模塊?。√昧?,那我們以后在style里面加上scoped屬性就可以完美解決啦

慢!BUT,這種方法只有在火狐瀏覽器才生效,其它瀏覽器即使最新的chrome瀏覽器也不支持哦。我@#¥%……

不要急年輕人,我們來看一下vue的代碼,當(dāng)我們?cè)趕tyle中加了scoped屬性后

微信圖片_20170816201320.png

咦,這不就是我們剛剛講過的AMCSS(屬性模塊)的應(yīng)用嗎?也就是說vue在編譯的時(shí)候,把帶有scoped屬性的的模塊,加上了一個(gè)唯一的屬性,然后通過類名+屬性選擇器的方法來實(shí)現(xiàn)模塊化!

其實(shí)其他框架也是用的類似的方法,我們?cè)倏匆幌?,小程序wepy框架的實(shí)現(xiàn)吧?

微信圖片_20170817161148.png

這個(gè)是我們剛才講過OOCSS(面對(duì)對(duì)象CSS)??!

對(duì)的,這樣結(jié)合框架來講是不是能夠更能深刻理解我們剛才講過的內(nèi)容了啊?

如何按需加載css?

有時(shí)候我們需要把一些有用的常見的css放到一個(gè)common.css里面,但是當(dāng)我們項(xiàng)目足夠大的時(shí)候,common的內(nèi)容就會(huì)變得異常龐大,而且難以維護(hù)。

首先我們不得不說一下當(dāng)下有幾個(gè)比較火的CSS預(yù)處理器,Less、Sass 、Stylus和postCss,這是一個(gè)CSS史上的巨大飛躍。他主要提供了以下功能

  • 嵌套語法
  • 變量
  • @import
  • 混入
  • 繼承
  • 函數(shù)
  • 邏輯控制

了解了css預(yù)處理器,那么我們?nèi)绾蝺?yōu)化我們的common.css呢?

要想解決這個(gè)問題,我們首先來看一看LESS中的mixin是如何運(yùn)作的。

// 你可以混合“類”選擇器或者“id”選擇器,例如:
.a, #b {
  color: red;
}
.mixin-class
{
  .a();
}
.mixin-id {  
  #b();
}

以上將得到:

.a, #b {
  color: red;
}
.mixin-class
{
  color: red;
}
.mixin-id {
  color: red;
}  

小提示:當(dāng)你調(diào)用混合集的時(shí)候,括號(hào)可加可不加。

.a();  //這兩種調(diào)用方式效果是一樣的
.a;

如果你想要?jiǎng)?chuàng)建一個(gè)混合集,但是卻不想讓它輸出到你的樣式中,你可以在混合集的名字后面加上一個(gè)括號(hào)。

.my-mixin {
  color: black;
}
.my-other-mixin() {
  background: white;
}
.class {
  .my-mixin;
  .my-other-mixin;
}

輸出:

.my-mixin {
  color: black;
}
.class {
  color: black;
  background: white;
}

好了,我們知道這個(gè)原理就可以用less中的mixins重新修改我們的common.less了,而且不會(huì)顯得非常臃腫,我們可以按需加載我們的樣式了,是不是很棒啊

我們的CSS模塊化就講到這里了,有什么意見或建議可以聯(lián)系我哦!

我的公眾號(hào)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容