[翻譯]CSS模組-未來的編碼方式,css編碼

來源:互聯網
上載者:User

[翻譯]CSS模組-未來的編碼方式,css編碼
前言

這是Glen Maddern發佈於2015年8月19日的一篇文章,主要是之前翻譯的文章《理解CSS模組方法》裡提到這篇文章,現在算是順藤摸瓜跟進來看看。

這裡的翻譯都是根據我自己的理解進行的,所以不是一句一句的來的,有哪些不對的也在所難免,水平有限,希望大家指出。 本文

如果想在最近CSS開發思想上找到一個轉變點,最好去找Christopher Chedeau 2014年11月在NationJS上發表的“css in js”演講。這是一個分界線,各種不同的思想,就像高速粒子似的在自己的方向上快速發展。例如:在React及一些依賴React的項目中寫樣式, React Style,jsxstyle和Radium是其中三個,最新的,最巧妙的,和最可行的方法。如果發明是在一種探索的情況下相鄰的可能(adjacent possible),那麼christopher是創造了很多接近相鄰(adjacent)可能性。

這些問題,以不同的形式存在於大的CSS程式碼程式庫中。christopher指出,這些問題都可能通過在js中寫代碼來解決。但這種解決方案引入了其自身的複雜性和特性。只要看一下,在之前提到的項目中(React Style,jsxstyle和Radium),處理在:hover狀態下range的方法。這個問題,在瀏覽器端css中已經早被解決了。

CSS Modules team找到問題的關鍵--保持和CSS一致,使用styles-in-js的方式編寫。雖然我們還是堅持看好使用了CSS的形式,但還有要感謝對我們提供很多建議的朋友。

我們一直在絞盡腦汁地思考CSS,怎樣去編寫更好。 第1步:預設局部範圍

在css模組中,每一個檔案都是獨立編譯的,因此你可以使用一些CSS短命名-不用擔心命名衝突。下面看一下,提交按鈕的4種狀態的例

常規的CSS書寫方法

用Suit或BEM命名、一些CSS樣式、一段html。代碼如下:

css程式碼片段:

 

/* components/submit-button.css */

.Button { /* all styles for Normal */ }

.Button--disabled { /* overrides for Disabled */ }

.Button--error { /* overrides for Error */ }

.Button--in-progress { /* overrides for In Progress */

html程式碼片段:

 

<button class="Button Button--in-progress">Processing...</button>

上面代碼運行不錯,我們有4種狀態的類名,BEM命名,避免了使用嵌套選取器。使用大寫字母開頭的單詞Button作為選取器,避免與之前或引用樣式的類名衝突。並且我們使用--modifier文法來消除基礎樣式。

到現在為止,這都是一段不錯的可維護的代碼。但也引入了嚴格的命名規範。但這也是能用標準CSS,做到的最好的方式了。 CSS模組書寫方法

使用CSS模組,你不用擔心使用一些短命名了。可以像下面這樣。

 

/* components/submit-button.css */

.normal { /* all styles for Normal */ }

.disabled { /* all styles for Disabled */ }

.error { /* all styles for Error */ }

.inProgress { /* all styles for In Progress */

看,你不用在任何地方再去加長長的首碼。為什麼可以這樣做,我們可以像其它語言一樣,不用在本地變數前加長長的首碼,只要把CSS對應的檔案名稱改成submit-botton.css

這可以讓在JS中使用requireimport載入的CSS模組檔案,可以被編譯出來。

 

/* components/submit-button.js */

import styles from './submit-button.css';

buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`

真正在頁面使用的樣式名,是動態產生的唯一標識。CSS模組把檔案編譯成ICSS格式的檔案,這種格式檔案可以方便CSS和JS進行通訊。當你運行程式,會得到類似下面的代碼

 

<button class="components_submit_button__normal__abc5436"> Processing...</button>

得到類似結果,說明運行成功~ 命名規範

還是拿按鈕的例子來說

 

/* components/submit-button.css */

.normal { /* all styles for Normal */ }

.disabled { /* all styles for Disabled */ }

.error { /* all styles for Error */ }

.inProgress { /* all styles for In Progress */

所有類名都是獨立的,不是一個是基類名,其它的用來修改。在CSS模組中,所有類必須包括所有的屬性和樣式。這讓你在JS中使用類名時有很大的不同。

 

/* 不要像這樣 */

`class=${[styles.normal, styles['in-progress']].join(" ")}`

/* 不同之處是使用單獨的類名 */

`class=${styles['in-progress']}`

/* 最好使用駝峰式 */

`class=${styles.inProgress}`

當然,如果你是按照代碼量來收錢的,你可以按照你的方式繼續。 一個React例子

這裡不是關於React特有的CSS模組。但React提供了,在使用CSS模組時,特別優秀的體驗。下面做一個複雜點的例子。

 

/* components/submit-button.jsx */

import { Component } from 'react';

import styles from './submit-button.css';

export default class SubmitButton extends Component {

render() {

let className, text = "Submit"

if (this.props.store.submissionInProgress) {

className = styles.inProgress text = "Processing..."

} else if (this.props.store.errorOccurred) {

className = styles.error

} else if (!this.props.form.valid) {

className = styles.disabled

} else {

className = styles.normal

}

return <button className={className}>{text}</button>

}

}

你可以使用你的樣式,不用再擔心全域衝突,讓你可以專註於組件開發,而不是在寫樣式上。一旦離開之前的頻繁在CSS,js之間切換方式,你就再也不想回去了。

但這隻是開始,當你考慮樣式合并時,CSS模組又沒法使用了。 第2步 一切皆為組件

前面提到CSS模組需要每種狀態都包含所有所需的樣式。

這裡假設你需要多個狀態,我們對比一下CSS模組和BEM命名。

 

/* BEM Style */

innerHTML = `<button class="Button Button--in-progress">`

/* CSS Modules */

innerHTML = `<button class="${styles.inProgress}">`

等一下,如何在所有狀態共用樣式呢?答案是CSS模組的最有力工具-組件

 

.common { /* all the common styles you want */ }

.normal { composes: common; /* anything that only applies to Normal */ }

.disabled { composes: common; /* anything that only applies to Disabled */ }

.error { composes: common; /* anything that only applies to Error */ }

.inProgress { composes: common; /* anything that only applies to In Progress */ }

關鍵詞composes指出.normal包含.common中的樣式,就像sass裡的@extend關鍵詞一樣。sass是通過重寫css選取器來實現的。css模組則是通過改變js中使用的類名來實現。 SASS:

使用前面的BEM例子,使用一些SASS的@extend

 

.Button--common { /* font-sizes, padding, border-radius */ }

.Button--normal { @extends .Button--common; /* blue color, light blue background */}

.Button--error { @extends .Button--common; /* red color, light red background */}

這將編譯為

 

.Button--common, .Button--normal, .Button--error { /* font-sizes, padding, border-radius */ }

.Button--normal { /* blue color, light blue background */ }

.Button--error { /* red color, light red background */ }

你只需要在你的標籤上引用一個類名,可以得到通用的和專屬的樣式。功能很強大,但你必須知道,這也存在著特殊情況和陷阱。Hugo Giraudel 匯總了一些問題,想瞭解更多,請點擊《為什麼你應該避免使用SASS的@extend》 使用CSS模組

composes關鍵詞和@extend使用方法類似,但工作方式是不同的。看個例子

 

.common { /* font-sizes, padding, border-radius */ }

.normal { composes: common; /* blue color, light blue background */ }

.error { composes: common; /* red color, light red background */ }

在瀏覽器中將會被編譯為

 

.components_submit_button__common__abc5436 { /* font-sizes, padding, border-radius */ }

.components_submit_button__normal__def6547 { /* blue color, light blue background */ }

.components_submit_button__error__1638bcd { /* red color, light red background */ }

在js代碼中,import styles from "./submit-button.css"將得到

 

styles: {
common: "components_submit_button__common__abc5436",
normal: "components_submit_button__common__abc5436 components_submit_button__normal__def6547", error: "components_submit_button__common__abc5436 components_submit_button__error__1638bcd"
}

還是使用styles.normalstryles.error,在DOM中將被渲染為多個類名

 

<button class="components_submit_button__common__abc5436 components_submit_button__normal__def6547"> Submit</button>

這就是composes的功能,你可以合并多個樣式,但不用去修改你的JS代碼,也不會重寫你的CSS選取器。 第3步.檔案間共用代碼

使用SASS或LESS工作,通過@import來引用同一個工作空間的檔案。你可以聲明變數,函數,並在其它檔案中使用。很不錯的方法,但在各個不同的項目中,變數命名有可能衝突。那麼你就得重構你的代碼,編寫如variables.scsssettings.scss,你也不清楚哪些組件依賴於哪些個變數了。你的settings檔案會變得很大。

也有更好的解決方案(《使用Webpack構建更小巧的CSS》),但由於SASS的全域屬性,還是有很大的限制。

CSS模組一次只運行一個單獨的檔案,因此不會汙染全域範圍。js代碼用使用importrequire來引用依賴,CSS模組使用compose從另一個檔案引用樣式。

 

/* colors.css */

.primary { color: #720; }

.secondary { color: #777; }/* other helper classes... */

/* submit-button.css */

.common { /* font-sizes, padding, border-radius */ }

.normal { composes: common; composes: primary from "../shared/colors.css"; }

使用組件,我們可以像引用本地類名一樣,引用colors.css檔案的類。而且,組件變化的類名在輸出時會被改變,但CSS檔案本身並不變化,composes塊也會在產生瀏覽器端CSS之前被去除。

 

/* colors.css */
.shared_colors__primary__fca929 { color: #720; }
.shared_colors__secondary__acf292 { color: #777; }

 

/* submit-button.css */
.components_submit_button__common__abc5436 { /* font-sizes, padding, border-radius */ }
.components_submit_button__normal__def6547 {}

 

 

<button class="shared_colors__primary__fca929 components_submit_button__common__abc5436 components_submit_button__normal__def6547"> Submit </button>

 

實際上,在瀏覽器端,normal沒有自身的樣式。這是好事情,你可以添加新的語義化的對象,但不用去添加CSS樣式。我們還可以做得更多一點,

在全站開發中增加類名和視覺的一致性,在瀏覽器端減少樣式代碼的大小。

旁註:可以使用csso檢測並移除空類。 第4步:單一職責模組

組件的強大之處在於描述一個元素是什麼,而不修飾它的樣式。它以一種不同的方式來映射頁面實體(元素)和樣式實體(樣式規則)。

看一箇舊的CSS例子

 

.some_element { font-size: 1.5rem; color: rgba(0,0,0,0); padding: 0.5rem; box-shadow: 0 0 4px -2px; }

一個元素,一些樣式,很簡單。儘管這樣,還是存在一些問題:color,font-size,box-shadow,padding,這些都在這裡指定了,但無法在其它地方使用。

我們用SASS重構一下。

 

$large-font-size: 1.5rem;
$dark-text: rgba(0,0,0,0);
$padding-normal: 0.5rem;
@mixin subtle-shadow { box-shadow: 0 0 4px -2px; }
.some_element {
@include subtle-shadow;
font-size: $large-font-size;
color: $dark-text;
padding: $padding-normal;
}

比舊的CSS樣式有很大的改進,我們只是定義了很少的一部分。事實上像$large-font-size是排版,$padding-normal是布局,這些都僅僅用名字表達含義,不會在任何地方運行。如果要聲明一個box-shadow變數,但它並不能表達自身含義,這時就必須使用@mixin@extend了。 使用CSS模組

通過使用組件,我們可以在組件中,注釋寫明哪些可以重複使用的類名。

 

.element {
composes: large from "./typography.css";
composes: dark-text from "./colors.css";
composes: padding-all-medium from "./layout.css";
composes: subtle-shadow from "./effect.css";
}

使用檔案系統,而不是命名空間,來劃分不同用途的樣式。自然會出現引用多個單一用途的檔案。

如果你想從一個檔案中引用多個類,這裡有一個簡便的方法:

 

/* this short hand: */
.element {
composes: padding-large margin-small from "./layout.css";
}
/* is equivalent to: */
.element {
composes: padding-large from "./layout.css";
composes: margin-small from "./layout.css";
}

使你在網站開發上,每一種視覺對應一個類名。用上面的方式,來開發你的網站,變為一種可能。

 

.article {
composes: flex vertical centered from "./layout.css";
}
.masthead {
composes: serif bold 48pt centered from "./typography.css";
composes: paragraph-margin-below from "./layout.css";
}
.body {
composes: max720 paragraph-margin-below from "layout.css";
composes: sans light paragraph-line-height from "./typography.css";
}

這是一種我有興趣進一步探索的技術。在我看來,它結合了像Tachyons的原子CSS技術,像Semantic UI樣式類名的可讀性,單一職責等優勢。

但CSS模組的故事才剛剛開始,希望你能去在現在或將來使用它,並傳播它。 上手

通過使用CSS模組,希望能協助你和你的團隊,即可以交流當前的CSS知識和產品,又可以更舒服,更高效地完成工作。我們已經儘可能保持文法的簡單,並寫了一些例子,當你可以使用這些例子裡的代碼時,你就可以使用它進行工作了。這裡有一些關於Webpack,JSPM和Browseriry項目的DEMO,希望對你有所協助。我們一直看有哪些新的環境可以運行CSS模組:正在適配伺服器端NODEJS和Rails。

為了使事情更簡單,這裡做了一個Plunkr,可以直接動手,不用安裝。開始吧

 

如果你準備使用了,可以看一看CSS模組源碼,如果有什麼問題,可以在issue裡進行討論。CSS模組組,規模小,無法涵蓋所有的應用情境。

期待你們的討論。

祝:寫樣式開心。

原文:CSS Modules

原文連結:http://glenmaddern.com/articles/css-modules

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.