Skip to content

Sass sass:string:引號、擷取與字串處理

Sass 字串模組 sass:string 的函式

CSS 裡有兩種字串:content: "文字" 需要引號,font-family: sans-serif 不能有引號。sass:string 管的主要就是這件事,順帶提供擷取與搜尋。

scss
@use "sass:string";

引號的處理

scss
string.quote(sans-serif)     // "sans-serif"
string.unquote("sans-serif") // sans-serif

典型情境是從 map 取出的關鍵字被存成帶引號的字串:

scss
$config: (display: "flex");

.a { display: map.get($config, display); }               // display: "flex"; ❌
.b { display: string.unquote(map.get($config, display)); } // display: flex; ✅

插值本來就會去掉引號

#{map.get($config, display)} 也能達到同樣效果。單純要去引號時用 插值 就好unquote() 適合用在函式內部需要回傳無引號值的時候。

反過來,content 需要引號:

scss
.crumb::after {
  content: string.quote($name);   // 不論原本有沒有引號都補上
}

擷取與長度

scss
string.length("primary")        // 7
string.slice("primary", 1, 3)   // "pri"
string.slice("btn-primary", 5)  // "primary",只給起點就取到底
string.slice("primary", -3)     // "ary",負數從尾端算

索引從 1 開始,不是 0

string.slice($s, 1, 3) 取的是第一到第三個字元。list 也是同樣的規則。

一個實用例子,去掉開頭的 #

scss
@function strip-hash($hex) {
  @if string.slice($hex, 1, 1) == "#" {
    @return string.slice($hex, 2);
  }
  @return $hex;
}

搜尋

scss
string.index("btn-primary", "-")     // 4
string.index("btn-primary", "xyz")   // null,找不到

搭配 slice() 就能做簡單的切割:

scss
@function before-dash($s) {
  $i: string.index($s, "-");
  @return if($i, string.slice($s, 1, $i - 1), $s);
}

before-dash("btn-primary")   // "btn"

插入

scss
string.insert("btnprimary", "-", 4)   // "btn-primary"
string.insert("primary", "btn-", 1)   // "btn-primary"

大小寫

scss
string.to-upper-case("primary")   // "PRIMARY"
string.to-lower-case("PRIMARY")   // "primary"

unique-id:產生唯一名稱

scss
$name: string.unique-id();   // 例如 u2f8b31c9

@keyframes #{$name} {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframescounter 的名稱是全域的,元件庫裡用它避免撞名。

每次編譯結果都不同

產出的 CSS 會因此每次都不一樣,不利於快取比對與 diff 檢視。除非真的需要,否則手動加專案前綴更好。

沒有 replace 函式

Sass 沒有內建的字串取代,需要的話自己寫:

scss
@use "sass:string";

@function str-replace($s, $search, $replace: "") {
  $i: string.index($s, $search);

  @if $i {
    @return string.slice($s, 1, $i - 1)
      + $replace
      + str-replace(
          string.slice($s, $i + string.length($search)),
          $search,
          $replace
        );
  }

  @return $s;
}

這是遞迴的寫法,處理 SVG data URI 的字元轉義時常用到。

什麼時候不必用這個模組

單純串接字串用 插值 就好:

scss
$prefix: "btn";
$name: "primary";

.#{$prefix}-#{$name} { }   // ✅ 清楚

sass:string 留給真正需要擷取、搜尋、替換的場合。

常見問題

什麼時候需要 unquote?

當一個值被存成帶引號的字串,但輸出時不能有引號的時候,例如從 map 取出的 CSS 關鍵字。不過多數情況用插值就會自動去掉引號,不必特地呼叫這個函式。

字串的索引從 0 還是 1 開始?

從 1 開始,這與大多數程式語言不同。負數則代表從尾端往回數,-1 是最後一個字元,擷取整段時很方便。

string.length 算的是字元還是位元組?

算的是字元數,所以一個中文字算一個。要注意它算的是不含引號的內容長度。

串接字串該用插值還是這個模組?

單純串接用插值就好,意圖清楚也不必記引號規則。需要擷取、搜尋、替換這類真正的字串處理時才用 sass:string

延伸閱讀