Skip to content

Wat is Sass string interpolatie (#{}) en wanneer gebruik je het? ​

Inleiding ​

Sass (Syntactically Awesome Style Sheets) is een populaire CSS-preprocessor die ontwikkelaars helpt om stylesheets efficiënter, onderhoudbaarder en krachtiger te maken. Het biedt features zoals variabelen, nesting, mixins, en functies. Een minder vaak besproken maar soms cruciale feature is string interpolatie, aangeduid met #{}. Hoewel het misschien niet dagelijks wordt gebruikt, is het essentieel om te begrijpen wanneer en waarom je het nodig hebt, vooral bij het werken met moderne CSS-features zoals Custom Properties en design system tokens.

Wat is Sass string interpolatie? ​

String interpolatie in Sass is een manier om de waarde van een Sass-variabele of het resultaat van een Sass-functieaanroep in te voegen in je CSS-code, specifiek als een letterlijke string. Dit doe je door de Sass-expressie (zoals een variabele $mijn-var of een functieaanroep mijn-functie()) te omhullen met #{}.

scss
// Voorbeeld: Variabele interpoleren in een selector
$element-name: 'modal';

// Interpolatie wordt gebruikt om de class-naam dynamisch te maken
.#{$element-name}-header {
  font-weight: bold;
}

// Gecompileerde CSS Output:
// .modal-header {
//   font-weight: bold;
// }

Het fundamentele verschil met het direct gebruiken van een variabele (zoals color: $primary-color;) is dat interpolatie de tekstuele representatie van de waarde invoegt, ongeacht het Sass-datatype (getal, kleur, string, lijst, etc.). Het dwingt Sass om de waarde als platte tekst te behandelen op die specifieke plek in de code.

Scenario's die interpolatie vereisen ​

Wanneer is deze #{} syntax nu precies nodig? Het komt neer op situaties waarin Sass de waarde van een expressie moet behandelen als onderdeel van een string in de uiteindelijke CSS, in plaats van als een waarde die Sass zelf verder zou kunnen interpreteren of berekenen.

De belangrijkste use cases zijn:

  1. Waarden voor CSS custom properties (variabelen) definiëren: Dit is tegenwoordig een zeer veelvoorkomend scenario, zeker bij het gebruik van design systems. CSS Custom Properties (--property-name: value;) slaan hun value op als een string. Als je de waarde voor een custom property wilt instellen met een Sass-variabele of een functie zoals cds.get() (om een token op te halen), heb je interpolatie nodig.

    scss
    // Sass (met een hypothetische cds.get functie)
    @use 'path/to/cds-tokens' as cds;
    
    .component {
      // Correct: Interpolatie nodig bij definitie van custom property
      --_component-background-color: #{cds.get('cds.sys.color.surface')};
      --_component-padding: #{cds.get('cds.sys.spacing.m')};
    
      // Gebruik van de custom properties
      background-color: rgb(var(--_component-background-color));
      padding: var(--_component-padding);
    }
    
    // Mogelijke CSS Output (afhankelijk van cds.get resultaat):
    // .component {
    //   --_component-background-color: 255, 251, 254; /* Bijv. RGB als string */
    //   --_component-padding: 1rem;
    //   background-color: var(--_component-background-color);
    //   padding: var(--_component-padding);
    // }

    Waarom precies is interpolatie hier nodig? ​

    Dit heeft te maken met het fundamentele verschil tussen hoe Sass werkt en hoe CSS Custom Properties werken:

    • Sass is een Preprocessor (Compile Time): Sass doet zijn werk voordat de browser de CSS ziet. Het compileert je .scss naar een statisch .css bestand. Wanneer Sass cds.get() uitvoert, krijgt het een Sass-datatype terug (bv. een Sass Kleur, String of Getal).
    • Custom Properties zijn een Browser Feature (Runtime): De browser leest het .css bestand. De waarde van een custom property (--naam: waarde;) wordt door de browser eerst als een soort onbewerkte string behandeld. Pas bij gebruik (var(--naam)) interpreteert de browser die waarde volledig.
    • Het Conflict: Als je schrijft --_mijn-kleur: cds.get('cds.sys.color.primary');, voert Sass cds.get() uit en krijgt bijvoorbeeld een Sass Kleur-object. Maar Sass weet niet hoe het dit object precies als tekst moet formatteren voor de custom property. Moet het rgb(0,0,255) zijn? #0000ff? Of misschien 0, 0, 255 (zonder rgb()) omdat het later in rgb(var(--_mijn-kleur)) gebruikt wordt? Sass kent de runtime context van de browser niet en kan geen veilige aanname doen over de correcte tekstuele formattering.
    • De Oplossing (#{}): String interpolatie #{cds.get(...) } lost dit op. Het zegt tegen Sass: "Voer cds.get() uit, neem het resultaat, en plak de letterlijke stringrepresentatie ervan hier neer. Probeer het niet slim te formatteren." Dit geeft de ontwikkelaar de controle over de exacte tekst die in het CSS-bestand terechtkomt, passend bij hoe de custom property bedoeld is om gebruikt te worden.
  2. Dynamische selectors: Class-namen, ID's of delen van attribuutselectors dynamisch samenstellen op basis van variabelen.

    scss
    // Sass
    $themes: 'light', 'dark';
    $component: 'button';
    
    @each $theme in $themes {
      .#{$component}--theme-#{$theme} {
        // Interpolatie voor class-namen
        border: 1px solid grey;
      }
    }
    
    // CSS Output:
    // .button--theme-light { border: 1px solid grey; }
    // .button--theme-dark { border: 1px solid grey; }
  3. Dynamische property-namen: Minder gebruikelijk, maar soms handig in complexe mixins om dynamisch property-namen te genereren.

    scss
    // Sass
    @mixin margin-sides($prefix: 'margin', $value: 1em) {
      #{$prefix}-left: $value; // Interpolatie voor property-naam
      #{$prefix}-right: $value; // Interpolatie voor property-naam
    }
    
    .item {
      @include margin-sides('padding', 5px);
    }
    
    // CSS Output:
    // .item {
    //   padding-left: 5px;
    //   padding-right: 5px;
    // }
  4. Binnen url() en andere string-contexten: Bij het samenstellen van URL-paden of andere waarden die expliciet als strings moeten worden behandeld.

    scss
    // Sass
    $asset-base-path: '/static/img';
    $icon-set: 'ui';
    
    .icon-close {
      background: url('#{$asset-base-path}/#{$icon-set}/close.svg');
    }
    
    // CSS Output:
    // .icon-close { background: url("/static/img/ui/close.svg"); }

Wanneer geen interpolatie gebruiken? ​

Gelukkig hoef je niet overal #{} te gebruiken. Het is niet nodig en zelfs onjuist in de volgende veelvoorkomende situaties:

  1. Directe toewijzing aan standaard CSS-properties: Als je een Sass-variabele toewijst aan een standaard CSS-property (zoals color, margin, font-size) en Sass het type begrijpt en correct kan omzetten.

    scss
    @use 'path/to/cds-tokens' as cds;
    $text-color: cds.get('cds.sys.color.on-surface'); // Sass haalt de waarde op
    $spacing-unit: cds.get('cds.sys.spacing.s'); // Sass haalt de waarde op
    
    body {
      color: $text-color; // Geen interpolatie nodig
      margin-bottom: $spacing-unit; // Geen interpolatie nodig
    }
  2. Sass-berekeningen: Wanneer je Sass gebruikt voor wiskundige berekeningen. Sass voert de berekening uit en gebruikt het resultaat.

    scss
    $base-size: 1rem;
    
    h1 {
      font-size: $base-size * 1.5; // Geen interpolatie
    }
  3. Variabelen in mixin/functie-argumenten: Wanneer je variabelen doorgeeft aan Sass-mixins of -functies waar ze als Sass-waarden (niet per se als strings) worden verwacht.

    scss
    @mixin set-border($border-style) {
      border: $border-style; // Geen interpolatie
    }
    
    .widget {
      @include set-border(1px solid black);
    }
  4. Als fallback waarde in var(): Wanneer je een Sass-variabele of functieaanroep (zoals cds.get()) gebruikt als de fallback waarde binnen een CSS var() functie, is interpolatie niet nodig. Sass evalueert de cds.get() functie tijdens het compileren en plaatst het resultaat direct in de CSS. De var() functie verwacht dit resultaat als een standaard CSS-waarde voor de fallback.

    scss
    @use 'path/to/cds-tokens' as cds;
    
    .element {
      // Fout: Interpolatie hier is overbodig en mogelijk schadelijk
      // background-color: var(--_element-bg, #{cds.get('cds.sys.color.background')});
    
      // Correct: Geen interpolatie nodig voor de fallback waarde
      background-color: var(--_element-bg-color, cds.get('cds.sys.color.surface'));
      padding: var(--_element-padding, cds.get('cds.sys.spacing.m'));
    }
    
    // Mogelijke CSS Output (afhankelijk van cds.get):
    // .element {
    //   background-color: var(--_element-bg-color, 255, 251, 254); /* Fallback is directe waarde */
    //   padding: var(--_element-padding, 1rem); /* Fallback is directe waarde */
    // }

    De #{} is alleen nodig bij het definiëren van de custom property zelf, niet bij het gebruiken ervan met een fallback in var().

Algemene aanbevelingen ​

  1. Gebruik voor custom property definities: Wees alert bij het definiëren van CSS Custom Properties met waarden uit Sass-variabelen of functieaanroepen zoals cds.get(). Interpolatie (#{}) is hier de standaard en veiligste aanpak vanwege het verschil tussen compile-time Sass en runtime CSS.
  2. Noodzakelijk voor dynamische namen: Interpolatie is essentieel als je delen van selectors of property-namen dynamisch wilt genereren met Sass-variabelen.
  3. Duidelijkheid boven alles: Interpolatie voegt een extra laag complexiteit toe. Gebruik het bewust en alleen waar het technisch vereist is om de leesbaarheid van de code te bewaren.
  4. Controleer de output: Vooral bij het werken met strings die al aanhalingstekens bevatten, kan interpolatie soms onverwacht gedrag vertonen. Inspecteer de gecompileerde CSS om zeker te zijn dat het resultaat correct is.

Conclusie ​

String interpolatie #{} is misschien geen alledaagse feature in Sass, maar het is een onmisbaar stuk gereedschap voor specifieke, moderne CSS-workflows, met name bij het integreren van design system tokens via functies zoals cds.get() in CSS Custom Properties. Het stelt ontwikkelaars in staat om de dynamische kracht van Sass te gebruiken op plaatsen waar CSS een letterlijke string verwacht, door de kloof te overbruggen tussen de compile-time wereld van Sass en de runtime wereld van de browser. Door te begrijpen wanneer interpolatie nodig is (bij custom property definities, dynamische namen) en wanneer niet (bij standaard properties, berekeningen, var() fallbacks), kun je robuustere, flexibelere en krachtigere stylesheets schrijven.