Chepter 10: Sass String
Sass String Functions — the tools from the sass:string module that let you slice, dice, search, combine, quote, and manipulate strings like a pro.
In 2026 (Dart Sass era), string manipulation is done via the sass:string module — no more old global functions like str-index() or quote() without a namespace. This keeps your code clean, traceable, and future-proof.
1. Why String Functions Matter in Sass
Strings appear everywhere:
- Font families: “Helvetica Neue”, Arial, sans-serif
- CSS values: url(‘/images/bg.jpg’), calc(100% – 20px)
- Custom properties: –brand: “MyCompany”
- Generated selectors: .btn–#{variant}
- Content: content: “→”
String functions help you:
- Build dynamic values
- Clean up / normalize input
- Extract parts (e.g., file extensions)
- Quote/unquote safely
- Generate unique IDs
- Search & replace patterns
Without them, you’d write ugly hacks with interpolation + conditionals.
2. Loading the Module (Modern 2026 Way)
Always load explicitly:
|
0 1 2 3 4 5 6 |
@use 'sass:string'; |
Then call functions like string.quote(…) (You can alias: @use ‘sass:string’ as str; → str.quote(…))
3. The Full List of sass:string Functions (Dart Sass 1.97+ in 2026)
Here are all the main ones with explanations, playground-style examples, and real-use cases.
string.quote($string) / quote($string)
→ Returns $string wrapped in double quotes (even if already quoted).
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@use 'sass:string'; @debug string.quote(Helvetica); // "Helvetica" @debug string.quote("Helvetica"); // "Helvetica" @debug string.quote(Helvetica Neue); // "Helvetica Neue" (spaces need quotes) .font-stack { font-family: string.quote("Inter") + ", system-ui, sans-serif"; // → font-family: "Inter", system-ui, sans-serif; } |
Use case: Force quoting for font names, content strings, or custom properties that might contain spaces/special chars.
string.unquote($string) / unquote($string)
→ Removes quotes if present; returns unquoted string.
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
@debug string.unquote("Helvetica"); // Helvetica @debug string.unquote(Helvetica); // Helvetica (already unquoted) @debug string.unquote("calc(100% - 20px)"); // calc(100% - 20px) $raw-calc: "calc(100vw - 80px)"; .responsive { width: string.unquote($raw-calc); // becomes valid calc() expression } |
Use case: When you have quoted strings from variables/maps but need them unquoted for CSS functions like calc(), url(), etc.
string.index($string, $substring) / str-index($string, $substring)
→ Returns 1-based index of first occurrence of $substring in $string, or null if not found.
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@debug string.index("Hello World", "World"); // 7 @debug string.index("Hello World", "o"); // 5 (first 'o') @debug string.index("Sass is fun", "CSS"); // null $font: "Helvetica Neue"; @if string.index($font, "Neue") != null { .modern { font-family: $font; } } |
Use case: Check if a font name contains “Mono” / “Serif”, detect file extensions, validate strings.
string.slice($string, $start-at, $end-at: -1)
→ Extracts substring from $start-at to $end-at (1-based, negative = from end).
|
0 1 2 3 4 5 6 7 8 9 |
@debug string.slice("Hello Sass!", 7); // "Sass!" @debug string.slice("Hello Sass!", 7, 10); // "Sas" @debug string.slice("filename.min.css", -4); // ".css" (from end) @debug string.slice("2026-02-20", 1, 4); // "2026" |
Use case: Get file extension, extract year from date string, trim prefixes/suffixes.
string.insert($string, $insert, $index)
→ Inserts $insert at position $index (1-based).
|
0 1 2 3 4 5 6 |
@debug string.insert("Hell Sass!", "o ", 5); // "Hello Sass!" |
Use case: Rare, but useful for building strings incrementally.
string.replace($string, $search, $replace)
→ Replaces first occurrence of $search with $replace.
|
0 1 2 3 4 5 6 7 |
@debug string.replace("dark-theme light-theme", "dark", "light"); // "light-theme light-theme" |
Use case: Swap color modes in class names, replace placeholders.
string.to-upper-case($string) / string.to-lower-case($string)
→ Converts case.
|
0 1 2 3 4 5 6 7 |
@debug string.to-upper-case("inter"); // "INTER" @debug string.to-lower-case("Arial Black"); // "arial black" |
Use case: Normalize class names, generate consistent IDs.
string.unique-id()
→ Returns a random, valid CSS identifier (unquoted), unique per compilation.
|
0 1 2 3 4 5 6 7 8 9 10 11 |
@debug string.unique-id(); // something like "aB7cD9eF2gH4" // Very useful for CSS-in-JS like uniqueness or debugging [data-unique="#{string.unique-id()}"] { // ... } |
Use case: Generate unique IDs for animations, components in large apps, avoid conflicts.
4. Real-World Combined Example – Utility Mixin + Functions
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
@use 'sass:string' as str; @function clean-font-name($font) { $unquoted: str.unquote($font); @if str.index($unquoted, " ") != null { @return str.quote($unquoted); } @else { @return $unquoted; } } @mixin font-family-safe($fonts...) { $quoted: (); @each $font in $fonts { $quoted: append($quoted, clean-font-name($font), $separator: comma); } font-family: $quoted; } .serif { @include font-family-safe(Georgia, "Times New Roman", serif); // → font-family: Georgia, "Times New Roman", serif; } |
5. Quick Tips & Gotchas (2026)
- Indexes are 1-based (not 0-based like JS/Python)
- Negative indexes count from end (-1 = last char)
- Strings can be quoted or unquoted — functions handle both
- Use #{} interpolation carefully — unquoted strings can break if they contain spaces/special chars
- For advanced regex-like → Sass doesn’t have it; keep logic simple or pre-process outside Sass
- Old global names (str-index, quote, etc.) still work but show deprecation warnings — always use module namespace now
You’ve now got string manipulation superpowers! This pairs beautifully with maps/lists for dynamic class generation, themes, etc.
Next — want to build a full typography utility system using string + math + map functions? Or dive into sass:selector for selector magic? Or combine string functions with custom @functions for a component naming convention?
Just tell me — we’re rolling strong! 🚀
