原文:How to get better at writing CSScss
做者:Thomas Lombarthtml
譯者:JeLewine前端
廢話很少說,我們就開門見山吧:想寫出優質的CSS代碼將會是很是痛苦的。不少開發者都不想作CSS開發。我能夠作你想作的一切,可是,除了CSS!node
當我在構建應用時,CSS是我挺討厭的部分。但你沒法擺脫它,對吧?個人意思是,正是由於咱們如此的專一於用戶體驗和設計,因此如今咱們纔不能跳過這一部分。ios
在開始一個項目時,一切都很正常。你有一些CSS選擇器:.title
input
#app
,這看起來很是的簡單。git
可是當你的應用變得愈來愈大時,它就開始變的愈來愈糟糕了。你對CSS選擇器感到困惑。你發現你寫的像div#app
.list
li.item a
諸如此類的東西,本身在一遍又一遍地在重複相同的代碼。你把全部代碼都放在文件末尾,由於你根本就不在意。CSS像一坨shit。而後你要狗帶了:500行的CSS徹底無法維護。github
我今天有一個小目標:讓你更好的去編寫CSS。我想讓你回首看看本身的舊項目併發出感慨:oh,boy,我怎麼能寫這麼一坨東西?npm
好吧,你可能會想,你說的有道理。可是CSS框架呢?這就是他們的用法,不是嗎?這就是咱們編寫好CSS代碼的方法。json
是的沒錯,不過這樣仍是會有一些缺點:瀏覽器
不過畢竟,你已經開始在看這篇文章了。這必定是有緣由的,不是嗎?因此,不用多說了,讓咱們開始學習如何更好的編寫CSS吧。
注意:這不是關於如何設計優雅應用程序的文章。它是關於學習如何編寫和組織可維護的CSS代碼的。
在這篇文章裏我將會用SCSS做爲例子。
SCSS是一個CSS的預處理器。簡單來講,它是一個CSS的超集:他爲CSS添加了一些很酷的功能,例如變量,嵌套,導入和mixins。
我將先談談咱們當即會使用到哪些功能。
經過SCSS,你可使用變量了。它帶來的主要好處就是可複用性。咱們假設你的應用有一組顏色。你的主色調是藍色。
因此你的應用處處都是藍色:按鈕的背景顏色,標題的顏色,連接。藍色無處不在。
忽然之間,你不喜歡藍色。你更喜歡綠色了。
// 聲明變量
$primary-color: #0099ff;
// 引入變量
h1 {
color: $primary-color;
}
複製代碼
你還可使用SCSS來嵌套代碼。看一下下面的例子:
h1 {
font-size: 5rem;
color: blue;
}
h1 span {
color: green;
}
複製代碼
能夠變成下面這樣:
h1 {
font-size: 5rem;
color: blue;
span {
color: green;
}
}
複製代碼
更具備可讀性,不是嗎?使用嵌套來編寫複雜選擇器所花費的時間更少。
出於可維護性和可讀性方面的考慮,咱們不可能將全部代碼保存在一個大文件中。在試驗或構建小型應用程序時,這麼作也許能夠知足你的需求,但在更專業的狀況下...請不要這麼作。不過幸運的是,SCSS容許咱們這樣作。
您能夠經過使用前置下劃線命名文件的方式來建立局部文件:_animations.scss
,_base.scss
,_variables.scss
等。
至於引入,咱們可使用@import
命令。例如,下面這樣是你能夠作的:
// _animations.scss
@keyframes appear {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
// header.scss
@import "animations";
h1 {
animation: appear 0.5s ease-out;
}
複製代碼
看到這裏,你可能會認爲這裏是否是搞錯了。應該是_animations.scss
而不是animations
。
不。當你用這種方式命名時,scss能夠很聰明的知道你正在討論一個局部文件。
以上就是咱們所須要瞭解到的變量,嵌套,局部文件和引入。SCSS還有一些其餘功能,像是mixins,繼承指令(@for
,@if
,...)之類的,不過我今天不會在這裏介紹他們了。
若是你想了解更多的信息,能夠查看他們文檔。他們寫的很不錯,很是容易理解。
【譯者注:這是scss中文文檔的地址】
我已經記不清有多少次在個人CSS課程裏用到這些名稱了。你懂的:.button
,.page-1
,.page-2
,.custom-input
。
咱們其實常常不知道該如何去命名。然而這是很是重要的。若是你正在構建一個應用程序,而且因爲某些緣由決定將其擱置幾個月,該怎麼辦?或者更糟糕的是,若是有人要交接該項目怎麼辦?若是你的CSS代碼沒有一個正確命名,那麼很難一目瞭然地知道你在說什麼。
BEM幫咱們解決了這個問題。BEM是一種命名約定,表明着塊元素修飾符【譯者注:原文爲Block Element Modifier。在中文前端圈內發現大部分文章都將block直譯爲"塊",其實譯者我的以爲翻譯爲"模塊"可能會讓人更好理解一點。不過本文仍是選擇和已有譯法保持一致】。
這種方法可使咱們的代碼結構化,更加模塊化和可複用。如今讓我來解釋什麼是塊,元素和修飾符。
咱們能夠把「塊」視爲組件。你還記得小時候玩的樂高積木嗎?【譯者注:小時候沒玩過,如今我也玩不起...】ok,讓咱們回到過去。
你會如何建造一個簡單的房子?你須要一個窗戶,一個屋頂,一扇門,一些牆壁,就是這樣。那些是咱們的塊。他們各自有各自的做用。
**命名:**塊名稱:.block
樣例:.card
,.form
,.post
,.user-navigation
如今,你將如何用你的樂高去搭一個窗戶呢?這發現其中也許有一些看起很像邊框,當你把四個邊框組裝在一塊兒時,一個窗戶就搭好啦。那就是咱們的元素。它們是「塊」的一部分,它們是構建「塊」的必要條件。可是,當它們離開塊時就沒有用了。
**命名:**塊名稱 + _
+ 元素名:.block_element
樣例:.post_author
,.post_date
,.post_text
如今你已經搭起了一個窗戶,不過也許你想要的是一個綠色的或小的。這些就是修飾符。它們是「塊」或「元素」上的標誌,它們用於改變行爲和表現等。
**命名:**塊名稱或元素名 + -
+ 修飾名:.block_element-modifier
, .block-modifier
樣例:.post-important
,.post_btn-disabled
margin
寫在按鈕上,不然您的按鈕將與您的標題徹底綁定。請改用其餘公用類來代替這個操做。下面是一個對你的小練習。轉到你最喜歡或最經常使用的網站,並嘗試使用BEM。
例如,下面就是我在Google商店中的想象:
輪到你了。要保持好奇人們如何能夠作的更好。你必須本身去搜索,嘗試和創造,這樣才能更好的貼合你本身的需求。
你會發現下面的一些例子充分的展現了BEM的功力。
<!--html-->
<div class="post">
<span class="post__author">Thomas</span>
<span class="post__date">3 minutes ago</span>
<p class="post__text">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laboriosam sit voluptatem aut quis quisquam veniam delectus sequi maxime ullam, inventore blanditiis quia commodi maiores fuga, facere quaerat doloremque in. Nisi!
</p>
</div>
<div class="post mt-large post--important">
<span class="post__author">Thomas</span>
<span class="post__date">2 hours ago</span>
<p class="post__text">
Voluptatem incidunt autem consequatur neque vitae aliquam, adipisci voluptatum. Ipsum excepturi dolores exercitationem rem ab similique consequatur nesciunt, tempora aut vel unde.
</p>
</div>
<!--SCSS-->
.post {
display: inline-block;
padding: 1rem;
background-color: #ccc;
border: 1px solid #222;
border-radius: 5px;
&--important {
background-color: yellow;
}
&__author {
font-size: 1.2rem;
font-weight: bold;
color: blue;
}
&__date {
float: right;
}
&__text {
line-height: 2rem;
font-size: 1.3rem;
}
}
複製代碼
<!--html-->
<div>
<button class="btn">
Click me
</button>
<button class="btn btn--danger">
Danger
</button>
<button class="btn btn--success">
Success
</button>
<button class="btn btn--small">
Small
</button>
<button class="btn btn--big">
Big
</button>
<button class="btn btn--border">
Border
</button>
</div>
<!--SCSS-->
.colors {
font-size: 1.5rem;
font-family: sans-serif;
}
.btn {
background-color: #FF6B93;
color: #fff;
text-transform: uppercase;
padding: 1.5rem 2.5rem;
border-radius: 4px;
transition: all .2s;
font-size: 1.3rem;
border: none;
letter-spacing: 2px;
cursor: pointer;
&:hover {
background-color: #D15879;
}
&:focus {
outline: none;
}
&--danger {
background-color: #FF3B1A;
&:hover {
background-color: #D43116;
}
}
&--success {
background-color: #00D123;
&:hover {
background-color: #00AB1D;
}
}
&--small {
padding: 1rem 2rem;
font-size: 1rem;
}
&--big {
padding: 1.8rem 4.5rem;
font-size: 1.7rem;
}
&--border {
background-color: #fff;
color: #FF6B93;
border: 1px solid #FF6B93;
&:hover {
background-color: #FF6B93;
color: #fff;
}
}
}
複製代碼
【譯者注:原文是在文章中插入了codepen。爲了方便閱讀,直接對輸出結果進行了截圖。有興趣的讀者能夠直接訪問這兩個地址:樣例1,樣例2】
你堅持看到這兒了?優秀! 如今讓咱們看看如何組織CSS文件。這部分將真正幫助你提升工做效率,並可以讓你當即找到必需要修改的CSS代碼的位置。
爲此,咱們將瞭解7-1模式。
你可能會想這是個什麼玩意【譯者注:711便利店?233】。
相信我,這很簡單。你只須遵照下面2條規則:
main.scss
文件中。就是這樣。
base
:在這裏,把全部的腳手架代碼都放進去。經過腳手架,我指的是每次啓動一個新項目時要寫的全部CSS代碼。例如:排版規則、動畫、公用(公用類,我指的是margin-right-large
,text-center
,……之類的類)。components
:這裏的名稱是明確的。此文件夾包含用於構建頁面的全部組件,如按鈕,表單,swipers,彈出窗口等。layout
:用於佈局頁面的不一樣部分。也就是說,頁眉,頁腳,導航,本身的網格等等。pages
:你有時可能會有一個頁面會具備一些本身特定的樣式。將它們與那些通用的樣式分開,而後將它們放在pages文件夾中。themes
:若是你的應用有不一樣的主題(黑暗模式,管理員模式等),請將它們放在此文件夾中。abstracts
:將全部函數與變量和mixin一塊兒放在這裏。vendors
:如今有什麼項目是沒有依賴外部庫的?在vendor文件夾中放入全部不依賴於你的文件。你可能但願在此處添加Font Awesome文件,Bootstrap和相似的東西。在這裏導入你全部的partials。
@import abstracts/variables;
@import abstracts/functions;
@import base/reset;
@import base/typography;
@import base/utilities;
@import components/button;
@import components/form;
@import components/user-navigation;
@import layout/header;
@import layout/footer;
...
複製代碼
是的。這看起很龐大。不過我知道你會這麼想,這種架構適用於更大的項目,而不是小的。這裏有一個適用於較小項目的版本。
首先,你不須要vendors
文件夾。只需將全部外部CSS代碼放置在頭文件中的連接標籤中便可。而後你能夠跳過themes
文件夾,由於你的應用可能只有一個主題。最後,你的頁面不會有不少特定的樣式,因此你也能夠跳過pages
這個頁面。太好了,只剩下4個文件夾了!
接下來,你又兩個選擇:
abstact
、components
、layout
和base
。main.scss
文件放在一塊兒。因此你會產生如下相似的東西:sass/
_animations.scss
_base.scss
_buttons.scss
_header.scss
...
_variables.scss
main.scss
複製代碼
這徹底取決於你本身。
你把我說服了!可是我該怎麼用呢?個人意思是,瀏覽器並不支持SCSS,不是嗎?
說的好!如今到了咱們的最後一步了。咱們將學習如何將SCSS文件編譯成CSS。
咱們將使用一個名爲node-sass
的包,它可以幫咱們將.scss
文件編譯爲.css
文件。
它的CLI(命令行界面)至關容易使用:
node-sass <input> <output> [options]
複製代碼
node-sass
提供了多種選項,不過咱們只須要兩個就夠了:
-w
: 觀察目錄或文件。這意味着node-sass可以觀察到代碼中的任何更改。一旦更改發生時,它會自動編譯爲CSS。 這在開發時很是有用。--output-style
:CSS文件的輸出模式是什麼。它能夠是如下值之一:nested
|expanded
|compact
|compressed
。咱們將使用它來構建你的CSS文件。若是你是一個有好奇心的人(我但願你是,開發人員應該保持好奇!),能夠到這裏查看完整的文檔。
如今咱們已經知道了咱們將使用哪些工具。接下來的事就很是簡單了。只要跟着下面的步驟走:
mkdir my-app && cd my-app
npm init
node-sass
庫:npm install node-sass --save-dev
index.html
和你的main.scss
文件:touch index.html
mkdir -p sass/{abstracts,base,components,layout} css
cd sass && touch main.scss
複製代碼
package.json
中你的腳本命令:{
...
"scripts": {
"watch:scss": "node-sass sass/main.scss css/style.css -w",
"build:scss": "node-sass sass/main.scss css/style.css --output style compressed"
},
...
}
複製代碼
index.html
文件的head
標籤中:<!DOCTYPE html>
<html lang=」en」>
<head>
<meta charset=」UTF-8"> <meta name=」viewport」 content=」width=device-width, initial-scale=1.0">
<meta http-equiv=」X-UA-Compatible」 content=」ie=edge」>
<link rel=」stylesheet」 href=」css/style.css」>
<title>My app</title>
</head>
<body>
<h1 class=」heading」>My app</h1>
</body>
</html>
複製代碼
就這樣,已經能夠跑起來了!當你開始coding並在瀏覽器中打開index.html
時,記得運行npm run watch:scss
。若是你想要壓縮你的css文件,跑一下npm run build:scss
就行了。
你可能在開發中更但願經過熱更新來提升效率,而不是每次都要手動重載index.html
文件。
只要跟着如下幾個簡單的步驟:
live-server
包:npm install -g live-server
。注意:這是一個全局包npm-run-all
包到你的項目依賴中:npm install npm-run-all --save-dev
。它可以讓你同時運行多個腳本命令。package.json
中:{
...
"scripts": {
"dev": "npm-run-all --parallel liveserver watch:scss ",
"liveserver": "live-server",
"watch:scss": "node-sass sass/main.scss css/style.css -w",
"build:scss": "node-sass sass/main.scss css/style.css --output-style compressed"
},
...
複製代碼
如今,當你運行npm run dev
時,你能夠當即看到你的修改,並且無需手動重載任何內容。太棒了,不是嗎?
不過你知道更棒的是什麼嗎?爲了方便你快速上手,我爲此建了一個repo。
若是你想要知道我是如何將這些技巧應用到個人項目中的,能夠查看這個repo。這裏是演示結果。我但願你能夠經過這個例子擁有更深的理解。
這就是今天要說的一切!如今,你已經作好了編寫可維護,模塊化和可複用的CSS代碼的準備。我但願你喜歡這篇文章。若是是這樣的話,請隨時在評論中給我反饋。那麼,下次再見啦!