Skip to content

Sass sass:list:清單的取值、附加與合併

Sass 清單模組 sass:list 的函式

list 是有順序的一串值。CSS 裡到處都是它:margin: 8px 16pxfont-family: A, B, Ctransition: color 0.2s, background 0.3s 全都是 list。

scss
@use "sass:list";

建立

用逗號或空白分隔,括號可省略:

scss
$font: "Noto Sans TC", sans-serif;   // 逗號分隔
$border: 1px solid #ddd;             // 空白分隔
$sizes: (8px, 16px, 24px);
$empty: ();

分隔符會被記住,輸出時原樣使用。所以要拿來當 font-family 就用逗號、當 margin 就用空白。

取值

scss
$sizes: (8px, 16px, 24px);

list.nth($sizes, 1)    // 8px
list.nth($sizes, -1)   // 24px,負數從尾端算
list.length($sizes)    // 3
list.index($sizes, 16px) // 2,找不到回傳 null

索引從 1 開始

list.nth($sizes, 0) 會直接報錯。這與 CSS 的 :nth-child() 一致,但與多數程式語言相反。

附加與合併

scss
$a: (8px, 16px);

list.append($a, 24px)        // (8px, 16px, 24px)
list.join($a, (24px, 32px))  // (8px, 16px, 24px, 32px)

差別在於「加入的東西是不是清單」:

scss
list.append($a, (24px, 32px))   // (8px, 16px, (24px, 32px)) ← 巢狀
list.join($a, (24px, 32px))     // (8px, 16px, 24px, 32px)   ← 攤平

list 不可變更

兩個函式都是 回傳新的 list,原本的不會變:

scss
list.append($a, 24px);        // ❌ 結果被丟掉
$a: list.append($a, 24px);    // ✅

控制分隔符

scss
list.append($a, 24px, $separator: comma)
list.join($a, $b, $separator: space)
list.separator($a)     // comma 或 space

box-shadow 時特別重要,各組陰影之間要逗號,組內要空白:

scss
@use "sass:list";

$shadows: ();
@each $i in (1, 2, 3) {
  $shadows: list.append($shadows, 0 ($i * 2px) ($i * 4px) #0002, comma);
}

.card { box-shadow: $shadows; }

zip:配對

scss
list.zip((a, b, c), (1, 2, 3))   // ((a 1), (b 2), (c 3))

搭配 @each 的解構:

scss
$names: (sm, md, lg);
$sizes: (576px, 768px, 992px);

@each $name, $size in list.zip($names, $sizes) {
  .container-#{$name} { max-width: $size; }
}

這種需求其實用 map 更好

(sm: 576px, md: 768px) 一眼看得出對應關係,不必擔心兩個 list 長度不一致。見 對照表 map

其他

scss
list.set-nth($a, 2, 20px)   // 回傳「第 2 項換成 20px」的新 list
list.is-bracketed([1, 2])   // true,方括號的 list
list.slash(1, 2, 3)         // 產生 1 / 2 / 3 這種斜線分隔的值

list.slash() 是給 grid-areafont 簡寫這類需要斜線的地方用的,因為斜線已經不是 除法 了。

單一值也是 list

scss
list.length(16px)          // 1
list.nth(16px, 1)          // 16px

@each $x in 16px { }       // 跑一輪

Sass 把任何值都當成長度為 1 的 list。寫通用函式時很方便:

scss
@mixin sides($values) {
  @if list.length($values) == 1 {
    padding: $values;
  } @else {
    padding: list.nth($values, 1) list.nth($values, 2);
  }
}

常見問題

list 的索引為什麼從 1 開始?

這是 Sass 的設計,與 CSS 的 :nth-child() 從 1 起算一致。從其他程式語言過來的人很容易寫成 0,那會直接得到錯誤。

append 和 join 差在哪?

append 是把一個值加到清單尾端,join 是把兩個清單接成一個。要加入的東西本身是清單時,用 append 會變成巢狀清單,用 join 才會攤平成同一層。

清單可以就地修改嗎?

不行,所有函式都是回傳新的清單,原本那個不會變。要留下結果就得把回傳值指派回變數,這一點與 map 相同。

單一個值算不算清單?

算,Sass 把任何值都視為長度為一的清單。所以對一個色碼呼叫長度函式會得到 1,走訪它也會跑一輪,寫通用函式時可以省下型別判斷。

延伸閱讀