【譯】如何更好的編寫CSS

原文:How to get better at writing CSScss

做者:Thomas Lombarthtml

譯者:JeLewine前端

廢話很少說,我們就開門見山吧:想寫出優質的CSS代碼將會是很是痛苦的。不少開發者都不想作CSS開發。我能夠作你想作的一切,可是,除了CSSnode

當我在構建應用時,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吧。

注意:這不是關於如何設計優雅應用程序的文章。它是關於學習如何編寫和組織可維護的CSS代碼的。

SCSS

在這篇文章裏我將會用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代碼:BEM方法論

我已經記不清有多少次在個人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

一些筆記

  • 當您使用BEM時,你爲類命名,也只能是爲類命名。沒有ID,沒有標籤。只有
  • 塊/元素能夠嵌套到其餘塊/元素中,但它們必需要能徹底獨立。記住這個詞:獨立。所以,請不要由於你想將按鈕放在標題下就將margin寫在按鈕上,不然您的按鈕將與您的標題徹底綁定。請改用其餘公用類來代替這個操做。
  • 是的,你的HTML文件將會過載。但不要擔憂,與BEM帶給您帶來的好處相比,這是一個小小的缺點。

一個例子

下面是一個對你的小練習。轉到你最喜歡或最經常使用的網站,並嘗試使用BEM。

例如,下面就是我在Google商店中的想象:

谷歌商店BEM

輪到你了。要保持好奇人們如何能夠作的更好。你必須本身去搜索,嘗試和創造,這樣才能更好的貼合你本身的需求。

將它們合在一塊兒

你會發現下面的一些例子充分的展現了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;
  }
}
複製代碼

樣例1

<!--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;
    }
  }
}
複製代碼

樣例2

【譯者注:原文是在文章中插入了codepen。爲了方便閱讀,直接對輸出結果進行了截圖。有興趣的讀者能夠直接訪問這兩個地址:樣例1樣例2

組織CSS文件:7-1模式

你堅持看到這兒了?優秀! 如今讓咱們看看如何組織CSS文件。這部分將真正幫助你提升工做效率,並可以讓你當即找到必需要修改的CSS代碼的位置。

爲此,咱們將瞭解7-1模式。

你可能會想這是個什麼玩意【譯者注:711便利店?233】。

相信我,這很簡單。你只須遵照下面2條規則:

  1. 將全部的局部文件寫入7個不一樣的文件夾中。
  2. 將它們所有導入位於根級別的一個main.scss文件中。

就是這樣。

7個文件夾

  • base:在這裏,把全部的腳手架代碼都放進去。經過腳手架,我指的是每次啓動一個新項目時要寫的全部CSS代碼。例如:排版規則、動畫、公用(公用類,我指的是margin-right-largetext-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個文件夾了!

接下來,你又兩個選擇:

  1. 你但願你的CSS代碼組織遵循7-1模式,所以你保留了abstactcomponentslayoutbase
  2. 你更喜歡有一個大文件夾,把全部的局部文件和你的main.scss文件放在一塊兒。因此你會產生如下相似的東西:
sass/
  _animations.scss
  _base.scss
  _buttons.scss
  _header.scss
  ...
  _variables.scss
  main.scss
複製代碼

這徹底取決於你本身。

你把我說服了!可是我該怎麼用呢?個人意思是,瀏覽器並不支持SCSS,不是嗎?

說的好!如今到了咱們的最後一步了。咱們將學習如何將SCSS文件編譯成CSS。

從SCSS到CSS

爲此,你須要先安裝Node.jsNPM(或Yarn)

咱們將使用一個名爲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"
  },
  ...
}
複製代碼
  • 將包括那些已編譯的CSS文件的引用連接添加到你的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代碼的準備。我但願你喜歡這篇文章。若是是這樣的話,請隨時在評論中給我反饋。那麼,下次再見啦!

相關文章
相關標籤/搜索