---
# System prepended metadata

title: 05. SCSS 程式開發標準

---

# 05. SCSS 程式開發標準

文件建立人員: 蔡勝豐
文件建立時間: 2021/02/07 6:25 PM
最後修改人員: 蔡勝豐
最後修改時間: 2021/03/08 6:25 PM
文件類型: 開發標準文件
文件版本: v 1.0

# 目的

1. 規範SCSS(CSS)統一格式
2. 此文件目的是在於幫助大家更好書寫及維護SCSS

# 範圍

1. 請寫下此技術文件適用影響之範圍

# 修訂歷程

| 修訂人員 | 修訂內容 |修訂日期 | 版本 |
| -------- | -------- | -------- | -------- |
| 蔡勝豐     | 初版     | 20210308     | 1.0.0

# 1.命名格式
* 以有意義的名詞或形容詞進行命名
* 名詞或形容詞首字為小寫
* 各詞之間用"-"來進行連接


# 2.語法格式
* 使用兩個空格代表縮進，而非使用Tab
* 理想上，每行保持為100個字符寬度
* 正確書寫多行CSS規則
* 有意義的使用空格


以 font-family 屬性為例：

```sass
// 推薦方式
.foo{
  display: block;
  overflow: hidden;
  padding: 0 1em;
}

// 不推薦方式
.foo {
    display: block; overflow: hidden;

    padding: 0 1em;
}

```

2-1.[字符串](#1-1.字符串)
2-2.[數值](#1-2.數值)
2-3.[顏色](#1-3.顏色)
2-4.[列表](#1-4.列表)
2-5.[Maps](#1-5.Maps)
2-6.[CSS規則集](#2-6.CSS規則集)
2-7.[聲明順序](#2-7.聲明順序)


### 2-1.字符串
CSS 中不要求字符串必須用引號包裹，甚至是字符串中包含空格的，因此 Sass 也不強制要求字符串必須被引號包裹。

話雖如此，不強制要求字符串被引號包裹的畢竟是少數，所以在 Sass 中字符串應該始終被單引號所包裹，理由如下：

* 如果顏色名不被引號包裹，將會被解析為顏色值，顯然這會導致嚴重問題；
* 大多數的語法高亮機制將會因未被引號包裹的字符串而罷工；
* 提高可讀性；
* 沒有正當理由不去用引號包裹字符串。

```sass
//推薦方式
$font-stack: 'Helvetica Neue Light', 'Helvetica', 'Arial', sans-serif;

//不推薦方式
$font-stack: "Helvetica Neue Light", "Helvetica", "Arial", sans-serif;

//不推薦方式
$font-stack: Helvetica Neue Light, Helvetica, Arial, sans-serif;
```
URL 最好也用引號包裹起來：

```sass
// 推薦方式
.foo {
  background-image: url('/images/kittens.jpg');
}
// 不推薦方式
.foo {
  background-image: url(/images/kittens.jpg);
}
```

### 2-2.數值
在 Scss中，數字類型包括了長度、持續時間、頻率、角度等等無單位數字類型。Scss 允許在運行中計算這些度量值。
* [零值](#零值)
* [單位](#單位)
* [計算](#計算)

#### 2-2-1.零值
數字小於 1 時，應該在小數點前寫出 0.，永遠不要顯示小數尾部的 0。
```sass
// 推薦方式
.foo {
  padding: 2em;
  opacity: 0.5;
}

// 不推薦方式
.foo {
  padding: 2.0em;
  opacity: .5;
}
```
#### 2-2-2.單位
定義長度時，0 後面不需要加單位。
```sass
// 推薦方式
$length: 0;

// 不推薦方式
$length: 0em;
```

在 Scss 中最常見的錯誤，是簡單地認為單位只是字符串，認為它會被安全的添加到數字後面。這雖然聽起來不錯，但卻不是單位正確的解析方式。

將一個單位添加給數字的時候，實際上是讓該數值乘以 *1 個單位：
```sass
$value: 42;

// 推薦方式
$length: $value * 1px;

// 不推薦方式
$length: $value + px;
```

要刪除一個值的單位，你需要除以相同類型的 1 單位：

```sass
$length: 42px;

// 推薦方式
$value: $length / 1px;

// 不推薦方式
$value: str-slice($length + unquote(''), 1, 2);
```

#### 2-2-3.計算
最高級運算應該始終被包裹在括號中。

這麼做不僅是為了提高可讀性，也是為了防止一些 Scss 強制要求對括號內內容計算的極端情況。
```sass
// 推薦方式
.foo {
  width: (100% / 3);
}

// 不推薦方式
.foo {
  width: 100% / 3;
}
```

### 2-3.顏色
顏色在 CSS 中佔有重要地位。當涉及到操縱色彩時，Sass 通過提供少數的函數功能。
* [顏色格式](#顏色格式)
* [顏色和變量](#顏色和變量)

#### 2-3-1.顏色格式
為了盡可能簡單地使用顏色，建議顏色格式要按照以下順序排列：

CSS 顏色關鍵字
十六進制，大寫並儘可能簡寫
RGB 值
HSL 值

```sass
// 推薦方式
.foo {
  color: red;
}

// 不推薦方式
.foo {
  color: hsl(300, 100%, 100%);
}
```

#### 2-3-2.顏色和變量
當一個顏色被多次調用時，最好用一個有意義的變量名來保存它。

```sass
$sass-pink: #c69;
```

就可以在任何需要的地方隨意使用這個變量了。
不過，如果你是在一個主題中使用，不建議固定的使用這個變量。
可以使用另一個標識方式的變量來保存它。

```sass
$main-theme-color: $sass-pink;
```
簡單來說就是不要將命名寫死，而是根據功能情境來描寫。

### 2-4.列表
列表就是 Sass 的數組。列表是一個一維的數據結構，用於保存任意類型的數值（包括列表，從而產生嵌套列表）。

列表需要遵守以下規範：

* 除非列表太長不能寫在 100 字符寬度的單行中，否則應該始終單行顯示
* 除非適用於CSS，否則應該始終使用逗號作為分隔符
* 除非為空或者嵌套在另一個列表中，否則始終不要使用括；
* 始終不要添加尾部的逗號

```sass
// 推薦方式
$font-stack: 'Helvetica', 'Arial', sans-serif;

// 不推薦方式
$font-stack:
  'Helvetica',
  'Arial',
  sans-serif;

// 不推薦方式
$font-stack: 'Helvetica' 'Arial' sans-serif;

// 不推薦方式
$font-stack: ('Helvetica', 'Arial', sans-serif);

// 不推薦方式
$font-stack: ('Helvetica', 'Arial', sans-serif,);
```

當需要給列表添加一個新列表項時，請遵守其提供的 API，不要試圖手動給列表添加列表項。
```sass
$shadows: 0 42px 13.37px hotpink;

// 推薦方式
$shadows: append($shadows, $shadow, comma);

// 不推薦方式
$shadows: $shadows, $shadow;
```

### 2-5.Maps
在 Sass 中，樣式開發者可以使用 map 這種數據結構。但不建議使用 map 存儲複雜數據類型。

map 的使用應該遵循下述規範：

* 冒號 : 之後添加空格
* 左開括號 ( 要和冒號 : 寫在同一行
* 如果鍵是字符串（99% 都是字符串），則使用括號包裹起來
* 每一個鍵值對單獨一行
* 每一個鍵值對以逗號 , 結尾
* 為最後一個鍵值對添加尾部逗號 ,，方便添加新鍵值對、刪除和重排已有鍵值對
* 單獨一行書寫右閉括號 )
* 右閉括號 ) 和分號 ; 之間不使用空格和換行

```sass
// 推薦方式
$breakpoints: (
  'small': 767px,
  'medium': 992px,
  'large': 1200px,
);

// 不推薦方式
$breakpoints: ( small: 767px, medium: 992px, large: 1200px );
```

### 2-6.CSS規則集
* 相關聯的選擇器寫在同一行；不相關聯選擇器分行書寫
* 最後一個選擇器和左開大括號 { 中間書寫一個空格
* 每個聲明單獨一行
* 冒號 : 後添加空格
* 所有聲明的尾部都添加一個分號 ;
* 右閉大括號 } 單獨一行

```sass
// 推薦方式
.foo, .foo-bar,
.baz {
  display: block;
  overflow: hidden;
  margin: 0 auto;
}

// 不推薦方式
.foo,
.foo-bar, .baz {
    display: block;
    overflow: hidden;
    margin: 0 auto }
```

添加與 CSS 相關的規範時，我們需要注意：

* 本地變量在其他任何變量之前聲明，並和其他聲明用空行分隔開
* 不需 @content 的混合宏在放在其他聲明之前
* 嵌套選擇器在新行聲明
* 需要 @content 的混合宏在嵌套選擇器後聲明
* 右閉大括號 } 上一行無需空行

```sass
.foo, .foo-bar,
.baz {
  $length: 42em;
  @include ellipsis;
  @include size($length);
  display: block;
  overflow: hidden;
  margin: 0 auto;
  &:hover {
    color: red;
  }
  @include respond-to('small') {
    overflow: visible;
  }
}
```

### 2-7. 聲明順序
主要以類型進行排序


```sass
.foo {
  height: 100px;
  width: 100px;
  overflow: hidden;
  position: absolute;
  bottom: 0;
  right: 0;
  background: black;
  color: white;
  font-weight: bold;
  font-size: 1.5em;
}
```


# 3.常量
命名將以全大寫方式書寫

```sass
// 推薦方式
$CSS_POSITIONS: top, right, bottom, left, center;
```

# 4.註釋
該註釋的內容
* 一個文件的結構或者作用
* 規則集的目標
* 使用幻數背後的目的
* CSS 聲明的原因
* CSS 聲明的順序
* 方法執行背後的邏輯思維

### 4-1. 寫註釋
* 以 C 風格註釋來進行CSS塊的核心的註釋
* 不能明顯看出意義的地方都應該註釋
* 註釋 SCSS 的一個特定部分時，應該使用SCSS單行註釋

```sass
/**
 * Helper class to truncate and add ellipsis to a string too long for it to fit
 * on a single line.
 * 1. Prevent content from wrapping, forcing it on a single line.
 * 2. Add ellipsis at the end of the line.
 */

.ellipsis {
  white-space: nowrap; /* 1 */
  text-overflow: ellipsis; /* 2 */
  overflow: hidden;
}
```

### 4-2. 文檔
每一個旨在代碼庫中復用的變量、函數、混合和佔位符，都應該使用 SassDoc 記錄下來作為全部 API 的一部分。

註：需要三個斜槓 ```/```
SassDoc 主要有兩個作用：

* 作為公有或私有 API 的一部分，在所有的地方使用一個註釋系統強制標準化註釋。
* 通過使用任意的 SassDoc 終端(CLI tool、Grunt、 Gulp、Broccoli、Node…)，能夠生成 API 文檔的 HTML 版本。
```sass=
/// Mixin helping defining both `width` and `height` simultaneously.
///
/// @author Hugo Giraudel
///
/// @access public
///
/// @param {Length} $width - Element's `width`
/// @param {Length} $height ($width) - Element's `height`
///
/// @example scss - Usage
///   .foo {
///     @include size(10em);
///   }
///
///   .bar {
///     @include size(100%, 10em);
///   }
///
/// @example css - CSS output
///   .foo {
///     width: 10em;
///     height: 10em;
///   }
///
///   .bar {
///     width: 100%;
///     height: 10em;
///   }

@mixin size($width, $height: $width) {
  width: $width;
  height: $height;
}
```

# 5.結構
將SCSS及CSS已有意義的方式分拆為不同等級的code librery並以資料夾進行分類,形成Css樣式表
```
sass/
|
|– base/
|   |– _reset.scss       # Reset/normalize
|   |– _typography.scss  # Typography rules
|   ...                  # Etc…
|
|– components/
|   |– _buttons.scss     # Buttons
|   |– _carousel.scss    # Carousel
|   |– _cover.scss       # Cover
|   |– _dropdown.scss    # Dropdown
|   ...                  # Etc…
|
|– layout/
|   |– _navigation.scss  # Navigation
|   |– _grid.scss        # Grid system
|   |– _header.scss      # Header
|   |– _footer.scss      # Footer
|   |– _sidebar.scss     # Sidebar
|   |– _forms.scss       # Forms
|   ...                  # Etc…
|
|– pages/
|   |– _home.scss        # Home specific styles
|   |– _contact.scss     # Contact specific styles
|   ...                  # Etc…
|
|– themes/
|   |– _theme.scss       # Default theme
|   |– _admin.scss       # Admin theme
|   ...                  # Etc…
|
|– utils/
|   |– _variables.scss   # Sass Variables
|   |– _functions.scss   # Sass Functions
|   |– _mixins.scss      # Sass Mixins
|   |– _helpers.scss     # Class & placeholders helpers
|
|– vendors/
|   |– _bootstrap.scss   # Bootstrap
|   |– _jquery-ui.scss   # jQuery UI
|   ...                  # Etc…
|
|
– main.scss             # primary Sass file
```

* [Base](#Base)
* [Layout](#Layout)
* [Components](#Components)
* [Pages](#Pages)
* [Themes](#Themes)
* [Utils](#Utils)
* [Vendors](#Vendors)
* [VendorExtensions](#VendorExtensions)
* [Main](#Main)

### Base
`base/` 文件夾存放項目中的模板文件。在這裡，可以找到重置文件、排版規範文件或者一個樣式表
（通常命名為`_base.scss`）——定義一些 HTML 元素公認的標準樣式。
* `_base.scss`
* `_reset.scss`
* `_typography.scss`

### Layout
`layout/` 文件夾存放構建網站或者應用程序使用到的佈局部分。該文件夾存放網站主體（頭部、尾部、導航欄、側邊欄…）的樣式表、柵格系統甚至是所有表單的 CSS 樣式。
* `_grid.scss`
* `_header.scss`
* `_footer.scss`
* `_sidebar.scss`
* `_forms.scss`
* `_navigation.scss`

### Components
對於小型組件來說，有一個 `components/` 文件夾來存放。相對於 `layout/` 的宏觀（定義全局線框結構），`components/` 更專注於局部組件。該文件夾包含各類具體模塊，基本上是所有的獨立模塊，比如一個滑塊、一個加載塊、一個部件… 由於整個網站或應用程序主要由微型模塊構成，`components/` 中往往有大量文件。

### Pages
如果頁面有特定的樣式，最好將該樣式文件放進`pages/`文件夾並用頁面名字。例如，主頁通常具有獨特的樣式，因此可以在 `pages/` 下包含一個 `_home.scss` 以實現需求。
* `_home.scss`
* `_contact.scss`

### Themes
`themes/`用來儲存不同主題
* `_theme.scss`
* `_admin.scss`

### Utils
`utils/` 文件夾包含了整個項目中使用到的 Sass 輔助工具，這裡存放著每一個全局變量、函數、混合宏和佔位符。
該文件夾的經驗法則是，編譯後這裡不應該輸出任何 CSS，單純的只是一些 Sass 輔助工具。
* `_variables.scss`
* `_mixins.scss`
* `_functions.scss`
* `_placeholders.scss` (通常命名為_helpers.scss)

### Vendors
用來存放所有外部庫和框架（Normalize、Bootstrap、jQueryUI…）的 CSS 文件。
* `_normalize.scss`
* `_bootstrap.scss`
* `_jquery-ui.scss`
* `_select2.scss`

### VendorExtensions
用來存放重寫的外部庫和框架的CSS文件，並使用相同的名字命名。
* `vendors-extensions/_boostrap.scss`
    
### Main
主文件（通常寫作 `main.scss`）應該是整個代碼庫中唯一開頭不用下劃線命名的 Sass 文件。除 @import 和註釋外，該文件不應該包含任何其他代碼。

文件應該按照存在的位置順序依次被引用進來：

* `vendors/`
* `utils/`
* `base/`
* `layout/`
* `components/`
* `pages/`
* `themes/`

為了保持可讀性，主文件應遵守如下準則：

* 每個 @import 引用一個文件
* 每個 @import 單獨一行
* 從相同文件夾中引入的文件之間不用空行
* 從不同文件夾中引入的文件之間用空行分隔
* 忽略文件擴展名和下劃線前綴

```
@import 'vendors/bootstrap';
@import 'vendors/jquery-ui';

@import 'utils/variables';
@import 'utils/functions';
@import 'utils/mixins';
@import 'utils/placeholders';
```


# 6.組件
幾乎所有的接口都可以被視為小組件，而且強烈建議堅持這種模式。這不僅僅會精簡整個項目中 CSS 的代碼量，而且也會比維護一個到處無邏輯的爛攤子容易得多。
組件可以是任意的，前提是遵循以下規範：

* 可以做一件事，只做一件
* 在整個項目中可以重用，具有可復用性
* 各自獨立

# 7. 條件語句
請遵守下述準則：
* 除非必要，不然不需要括號
* 務必在 @if 之前添加空行
* 務必在左開大括號 { 後換行
* @else 語句和它前面的右閉大括號 } 寫在同一行
* 務必在右閉大括號 } 後添加空行，除非下一行還是右閉大括號 }，那麼就在最後一個右閉大括號 } 後添加空行
```sass
// 建議寫法
@if $support-legacy {
  // …
} @else {
  // …
}

// 不建議寫法
@if ($support-legacy == true) {
  // …
}
@else {
  // …
}
```
* 通常將變量置於語句的左側，而將結果置於右側。
```sass
// 建議寫法
@if $value == 42 {
  // …
}

// 不建議寫法
@if 42 == $value {
  // …
}

```
* 當使用條件語句並在一些條件下有內聯函數返回不同結果時，始終要確保最外層函數有一個 @return 語句。
```sass=
// 建議寫法
@function dummy($condition) {
  @if $condition {
    @return true;
  }

  @return false;
}

// 不建議寫法
@function dummy($condition) {
  @if $condition {
    @return true;
  } @else {
    @return false;
  }
}
```



# 相關檔案與連結

1. 上傳相關檔案或附上檔案連結