4.4 Importing CSS into Figma (CF002)

Importing CSS into Figma is a crucial part of the bidirectional design token workflow enabled by Kolibri Sync. This feature directly supports the primary goals of Kolibri Sync: streamlining handoff (PG001) and reducing manual work and errors (PG002). By importing existing CSS variables into Figma color tokens, the import functionality bridges the gap between development and design. Decisions encoded in CSS can be represented as Figma color variables or color styles, ensuring that what is implemented in code stays aligned with what’s designed.

This page details the technical implementation and design choices of the Import feature.

Note: The step-by-step guide for CF002 is in the Appendix A8.

Import Parameters and Design Choices

1. Destination

The import process allows mapping CSS either to Figma Color Styles or to Figma color variables. The choice is presented as radio buttons, ensuring the user understands that the options are mutually exclusive and that only one destination can be selected for import.

  • Selecting Styles creates or updates Figma Color Styles. This option supports both solid colors and gradients, for example --button-gradient: linear-gradient(45deg, red, blue). Although Styles do not support modes, they can reference existing variables in the document.

  • Selecting variables creates or updates Figma color variables in a specified collection and assigns them to one or more modes, such as Light or Dark.

In essence, Styles are for visual assets like gradients, while variables are for structured token systems with theming capabilities.

Radio buttons for selection destination

2. Collection (Variables only)

As variables are selected for import, a dropdown specifies the target collection. Since variables must belong to a collection, selecting it at import time ensures they are placed in the correct location and remain organized within the design system. The dropdown lists all collections in the document, for example, “Palette,” “Semantic,” or “Utility,” making all options easily visible.

dropdown control for getting collections

3. Mode(s) (Variables only)

Modes are selected from dropdown controls and define the context in which variable values are applied, such as Light or Dark. Selecting modes at import time ensures correct assignment and enables theme-aware imports using the CSS light-dark() function.

Based on our research, light-dark() was chosen over other dark theme color mapping methods described in the Light and Dark Mode in CSS section, due to its simplicity, native browser support, and concise syntax for resolving to light or dark values.

Two configurations are supported:

  • Single-mode: One mode is selected and all values are written to that mode.

  • Dual Light/Dark: A second dropdown is added using the + button. When Light and Dark are selected, light-dark() inputs are split into their respective modes.

Contextual dropdown control

4. CSS Input and Import Button

The text area accepts CSS custom property declarations; the Import button processes them for the selected destination. A left-side area displays real-time color previews as rectangular swatches to align with each declaration. For simplicity and to support our incremental approach, previews are currently shown only for standard named colors and MDN-recommended literal color syntaxes, such as hsl(240deg 100% 50%), rgb(0 0 255), or #0000FF. Previews do not appear for values expressed via references or theme functions (such as var() or light-dark()), for gradients, or any color-mix() expressions.

Textarea to write CSS variables in

Supported CSS Input Syntax

This section describes the CSS syntax Kolibri Sync supports when importing design tokens into Figma. The plugin expects the following syntax for variable declarations:

--variable-name: value;

Each declaration must commence with a double-hyphen prefix (--) for the variable name and terminate with a semicolon (;). This precise adherence ensures accurate and consistent interpretation of design tokens during the import process.

Variable naming conversion

On import, custom property identifiers are normalized to conform to Figma’s hierarchical naming convention. The leading double hyphen (--) is removed, internal hyphens (-) are rewritten as forward slashes (/), and each path segment is capitalized (first letter uppercase). For example, --color-blue-500 becomes Color/Blue/500. This change affects names only; it does not change what the variables mean or how references between them work.

Kolibri Sync uses Figma’s figma.util.rgba to import standard CSS color literals with consistent results. Supported formats include hex colors, rgb and rgba, hsl and hsla, and CSS named colors. These formats are supported for both style and variable import.

:root {
  /* Hex Colors (3-digit, 6-digit, 8-digit with alpha) */
  --hex-3: #0af;        
  --hex-6: #00aaff;
  --hex-8: #00aaffcc;   
  
  /* RGB and RGBA */
  --rgb: rgb(0, 170, 255);
  --rgba: rgba(0, 170, 255, 0.8);  
  
  /* HSL and HSLA */
  --hsl: hsl(200, 100%, 50%);
  --hsla: hsla(200, 100%, 50%, 0.8);  
  
  /* Named Colors */
  --named-blue: deepskyblue;
  --named-gray: slategray;
  --named-accent: rebeccapurple;
}

Kolibri Sync parses cross-references expressed with the CSS var() function. As mention in the chapter Design Tokens in Figma color tokens (styles and variables) can reference variables (but not style). Using the var() function variable and styles can be bound to variables, allowing the color token to stay in sync with its source token. If a referenced identifier cannot be resolved at import time, the dependent declaration is skipped to avoid creating broken links in Figma.

--primary: #0066CC;
--accent: var(--primary);

Kolibri Sync supports CSS color blending via color-mix() in the sRGB color space. The plugin accepts inputs following this syntax color-mix(in srgb, <color>, <color> <percentage>), where colors may be literals or var() references.

The second color must include an explicit percentage, and the first color must not. The first color’s percentage is then computed as the remainder to reach 100%. Inputs that exclude the percentage on the second color or specify a percentage on the first color are invalid and skipped. During import, color-mix() expressions are evaluated to a single static color. This capability is available for both style and variable import.

--blended-1: color-mix(in srgb, #FF0000, #0000FF 50%);
--blended-2: color-mix(in srgb, #FF0000, #00FF00 60%);
--blended-3: color-mix(in srgb, var(--blended-1), var(--blended-2), 15%);

Kolibri Sync supports theme-aware inputs defined with light-dark(<light-mode-color>, <dark-mode-color>). When importing to Figma Variables with two modes selected (for example, Light and Dark), the importer assigns the first argument to the Light mode and the second to the Dark mode.

Accepted arguments include:

  • Color literals (e.g., #ffffff, rgb(0 0 0))

  • Variable references (var(--primary))

  • color-mix() expressions

Any nested references are resolved according to the rules described earlier in this section. This mapping is not applied when importing to Styles, and it is not applied if two modes are not configured; in those cases, the declaration is skipped.

--lightdark-1:     light-dark(#ffffff, #000000);
--lightdark-2:     light-dark(var(--primary), var(--accent));
--lightdark-3:     light-dark(color-mix(in srgb, #FF0000, #0000FF 50%), color-mix(in srgb, #FF0000, #00FF00 60%));
--lightdark-4:     light-dark(color-mix(in srgb, var(--blended-1), var(--blended-2), 15%), color-mix(in srgb, var(--blended-1), var(--blended-2), 50%));

Gradients

Kolibri Sync supports importing CSS gradients into Figma as color styles, with full coverage for linear, radial, and conic (angular) gradients. Parsing tolerates complex and mixed syntax.

Linear gradients are accepted in the form linear-gradient(<angle>, <color-stop>[, <color-stop>]*), where the first argument sets the direction and subsequent arguments define the color stops.

  • Angle formats:

    • Degrees are supported (e.g., 45deg, 127deg, 201deg).

    • Directional keywords are mapped to absolute angles: to right (90°), to left (270°), to bottom (180°), to top (0°), to bottom right (135°), to bottom left (225°), to top right (45°), and to top left (315°).

  • Color stops:

    • with positions: Stops may specify explicit positions such as #ff6b6b 0%, #4ecdc4 35%, #45b7d1 100%, which are honored exactly in the resulting gradient.

    • without positions: When positions are excluded, stops are distributed evenly across the gradient.

--gradient-1: linear-gradient(127deg, #ff6b6b 0%, #4ecdc4 35%, #45b7d1 100%);
--gradient-2: linear-gradient(to right, #a8e6cf, #ff8b94, #ffd93d);
--gradient-3: linear-gradient(201deg, #6c5ce7 0%, #fd79a8 25%, #fdcb6e 70%, #00b894 100%);
--gradient-4: linear-gradient(315deg, #74b9ff 10%, #0984e3 45%, #6c5ce7 90%);
--gradient-5: linear-gradient(89deg, #fd79a8 0%, #fdcb6e 30%, #00cec9 65%, #55a3ff 100%);

Radial gradients are accepted as radial-gradient([<shape>] [<size>] at <position>, <color-stop>[, <color-stop>]*), with optional shape, and position parameters preceding the color stops.

  • Supported shape keywords: circle creates a circular gradient; ellipse creates an elliptical gradient (default).

  • Supported position formats:

    • Keywords (center, top, bottom, left, right)

    • Combined keywords (top right, bottom left, center center)

    • Percentages (30% 40%, 70% 80%)

    • Mixed formats (top 30%, center 40%).

  • Explicit size values: Percentage-based (35.36% 35.36%, 50% 25%) or single values (25%, which applies to both dimensions for circles).

--radial-1: radial-gradient(circle at 30% 40%, #ffb347 0%, #ff6f69 60%, #355c7d 100%);
--radial-2: radial-gradient(ellipse at top right, #43cea2 10%, #185a9d 50%, #f8ffae 90%);
--radial-3: radial-gradient(circle at center, #f7971e 0%, #ffd200 40%, #21d4fd 100%);
--radial-4: radial-gradient(35.36% 35.36% at bottom left, #e0c3fc 0%, #8ec5fc 55%, #5ee7df 100%);
--radial-5: radial-gradient(circle at top, #ff9a9e 0%, #fad0c4 45%, #a1c4fd 80%, #c2e9fb 100%);

Conic gradients are accepted as conic-gradient([from <angle>] [at <position>], <color-stop>[, <color-stop>]*), with optional starting angle and position parameters. In Figma, these are called as Angular Gradients.

  • Angle units:

    • Degrees (45deg, 120deg, 200deg)

    • Turns (0.5turn, 1.25turn)

    • Radians (1.57rad, 3.14rad)

    • Gradians (100grad, 200grad)

    • Percentages (25%, converted to degrees where 25% = 90°).

  • Supported Position formats:

    • Keywords (center, top, bottom, left, right)

    • Combined keywords (top right, bottom left)

    • Percentages (50% 50%, 60% 40%, 30% 70%)

    • Mixed formats (center 20%, top 30%).

  • Color stop syntax:

    • Stops may use angle positions (#ff6b6b 0deg, #f7d794 30deg)

    • Percentage positions (#ff6b6b 0%, #f7d794 30%)

    • No positions (distributed evenly around the circle).

--conic-1: conic-gradient(from 45deg at 50% 50%, #ff6b6b 0%, #f7d794 30%, #4ecdc4 70%, #1a535c 100%);
--conic-2: conic-gradient(from 120deg at 60% 40%, #a8e6cf 0%, #ffd93d 40%, #ff8b94 80%, #a8e6cf 100%);
--conic-3: conic-gradient(from 0.5turn at center, #6c5ce7 0deg, #fdcb6e 25deg, #00b894 60deg, #fd79a8 100deg);
--conic-4: conic-gradient(at 80% 20%, #74b9ff 0%, #6c5ce7 50%, #fd79a8 75%, #fdcb6e 100%);
--conic-5: conic-gradient(from 270deg at 40% 60%, #fdcb6e, #00cec9, #55a3ff, #fd79a8);

Ignored syntax and parsing constraints

Kolibri Sync’s import is line‑oriented. It reads the CSS input one line at a time and only processes lines that match a single‑line custom property declaration of the form --name: value;. Everything else is ignored. Consequently, declarations must not span multiple lines.

Selector wrappers such as :root { ... } are treated as non‑semantic containers for parsing. Variables are processed identically whether or not they appear inside :root.

External import statements such as @import are ignored. The importer does not load additional files; only declarations present in the provided text are considered. Comments are discarded with the following constraints.

Block comments delimited by /* ... */ are ignored whether they are single‑line or multi‑line, provided they are not written inline on the same line as a declaration. Single‑line comments starting with // are also ignored when they occupy whole lines. Inline comments on the same line as a declaration are not supported and will cause that line to be skipped.

/* Document header (ignored) */
@import url('colors.css'); /* ignored */

:root {
  /*
   * Brand palette (multi-line block comment, ignored)
   */
  --primary: #0066CC;
}

--secondary: #FF6600;

/* Inline comments on the same line are not supported: */
--accent: #CC6600; /* not supported — line skipped */
--neutral: #333333; // not supported — line skipped

/* Multi-line declarations are not supported: */
--token:
  #0066CC;  /* not supported — line(s) skipped */

Overview of CSS Import Scenarios and Capabilities

Table 10 summarizes what Kolibri Sync can import for each destination:

Table 10. Overview of Kolibri Sync supported CSS syntax

Scenario
Supported
Not Supported

Import Style

  • Solid colors (#FF0000, rgb(255, 0, 0), hsl(0deg 100% 50%), red)

  • color-mix() resolved to a static color

  • Gradients (linear, radial, conic)

  • var() is referenced to a variable, missing refs are skipped

  • light-dark() function

Import Variable (Single Mode)

  • Solid colors (#FF0000, rgb(255, 0, 0), hsl(0deg 100% 50%), red)

  • color-mix() resolved to a static color

  • var() is referenced to a variable, missing refs are skipped

  • Gradients (linear, radial, conic)

  • light-dark() function

Import Variable (Light/Dark Mode)

  • light-dark() function with two values

Each value can be:

  • solid colors

  • color-mix()

  • var() references

  • Gradients (linear, radial, conic)

Last updated