Jump to Navigation Jump to Main Content Jump to Footer
Home » Docs » Features » Theme.json configuration with modern Sass (SCSS) features (@use, @forward)

Theme.json configuration with modern Sass (SCSS) features (@use, @forward)

Chisel theme combines WordPress’s theme.json design tokens with a modular SCSS architecture. Global styles (color palette, typography, spacing, etc.) are declared in theme.json and emitted as CSS Custom Properties, while SCSS composes styles via @use/@forward for clear, dependency‑safe modules.

Overview

  • theme.json: Defines colors, typography, spacing scale, layout, and custom tokens exposed as CSS variables.
  • Sass modules: Design system split into settings (Sass variables) and tools (functions/mixins) using @use/@forward.
  • Goal: Create styles with stable design tokens while staying aligned with WordPress Global Styles.

theme.json highlights

Colors

Custom palette (Primary, Secondary, Greys, etc.) available in CSS as --wp--preset--color--{slug} and in SCSS via get-color($slug)

Example:

{
  "settings": {
    "color": {
      "palette": [
        { "slug": "primary", "color": "#dd2424", "name": "Primary" },
        { "slug": "background", "color": "#ffffff", "name": "Background" }
      ]
    }
  }
}
JSON

SCSS Usage:

@use '~design' as *;

.my-component {
  color: get-color('primary');
  background-color: get-color('background');
}
SCSS

Typography

Fluid font sizes and a curated scale (tiny → huge).

  • Font Sizes: Available via get-font-size($slug) (e.g., normallargehuge).
  • Font Families: Defined in theme.json and loaded via local assets. Access via get-font-family('body') or get-font-family('headings').

Example:

{
  "settings": {
    "color": {
      "typography": {
        "fontSizes": [
          { "slug": "tiny", "size": "0.75rem", "name": "tiny" },
          { "slug": "normal", "size": "1rem", "name": "Normal" },
          { "slug": "large", "size": "1.25rem", "name": "Large", "fluid": { "min": "1.125rem", "max": "1.25rem" } }
        ],
        "fontFamilies": [
          {
            "fontFamily": "Roboto,sans-serif",
            "slug": "body",
            "name": "Roboto",
            "fontFace": [
              {
                "fontFamily": "Roboto",
                "fontWeight": "300",
                "fontStyle": "normal",
                "fontStretch": "normal",
                "fontDisplay": "swap",
                "src": ["file:./assets/fonts/roboto-300.woff2"]
              },
              {
                "fontFamily": "Roboto",
                "fontWeight": "700",
                "fontStyle": "normal",
                "fontStretch": "normal",
                "fontDisplay": "swap",
                "src": ["file:./assets/fonts/roboto-700.woff2"]
              }
            ]
          }
        ]
      }
    }
  }
}
JSON

SCSS Usage:

@use '~design' as *;

.my-component {
  font-family: get-font-family('body');
  font-size: get-font-size('normal');
}
SCSS

Custom Tokens

Chisel defines a robust set of custom tokens in settings.custom for consistent design system usage:

  • Spacing (Margin/Padding/Gap): tiny to huge scale.
  • Border Radius: tiny to full.
  • Border Width: tiny to large.
  • Box Shadow: Levels 1-4.
  • Transitions: slownormalfast.
  • Line Height/Letter Spacing.

How theme.json and Sass connect

Theme tokens are CSS variables. SCSS functions in src/design/tools/_theme.scss provide ergonomic wrappers:

// src/design/tools/_theme.scss
@function get-padding($name) {
  @return var(--wp--custom--padding--#{$name});
}

@function get-transition($name: 'normal') {
  @return var(--wp--custom--transition--#{$name});
}
SCSS

This ensures that if you change a value in theme.json, all your SCSS automatically reflects the change without recompiling, because it relies on the CSS variable.

Best practice: Create components using functions/tokens instead of literals:

@use '~design' as *;

.card {
  padding: get-padding('medium');
  color: get-color('foreground');

  @include bp('medium') {
    // bp() is defined in design/tools/_breakpoints.scss
    padding: get-padding('large');
  }
}
SCSS

Using @use and @forward

Chisel uses the modern Sass module system to prevent global variable namespace pollution.

Global Design Import

In your component files, import the design system:

@use '~design' as *;

.c-card {
  padding: get-padding('medium'); // Function from 'tools'
  background: get-color('white');

  @include bp('medium') { // Mixin from 'tools/breakpoints'
    padding: get-padding('large');
  }
}
SCSS

Specific Imports

If you only need settings (like Sass variables for breakpoints or grid config):

@use '../design/settings' as settings;

.c-grid {
  gap: map.get(settings.$gaps, 'normal');
}
SCSS

Extending the Design System

  1. Add a new tool/mixin: Create src/design/tools/_my-mixin.scss.
  2. Forward it: Edit src/design/tools/_index.scss to add @forward 'my-mixin';.
  3. Use it: @use '~design' as *; @include my-mixin();.

Why this architecture?

  1. Single Source of Truth: theme.json controls the values.
  2. Performance: CSS variables allow browser-native theming and updates without CSS bloat.
  3. Maintainability: Sass modules (@use) make dependencies explicit—no more guessing where a variable comes from.
  4. Standards: Fully aligned with WordPress Full Site Editing (FSE) and Gutenberg block styles.

Using @use and @forward (Sass modules) — short guide

@use

@use imports a Sass module once and namespaces its members (variables, mixins, functions).

Basic:

@use '../design/tools';      // access as tools.$var, tools.fn(), tools.mixin()
@use '../design/tools' as *; // flatten into current scope (be careful with naming)
@use '../design/tools' as t; // custom namespace
SCSS

With configuration (override module variables at load time):

@use '../design/settings' with (
  $root-font-size: 18px
);
SCSS

@forward

@forward re-exports members from another module to build a public API.

In the theme, src/design/_index.scss.This means consumers can just:

@forward 'tools';
SCSS
@use '../design' as *; // gets everything forwarded by tools/_index.scss
SCSS

You can curate exports in a tools/_index.scss:

// src/design/tools/_index.scss
@forward 'breakpoints';
@forward 'px-to-rem';
@forward 'theme';
// etc.
SCSS

Why modules (vs @import):

  • Single evaluation, no duplication.
  • Namespacing avoids collisions.
  • Clear, composable public API via @forward.

Do you like Chisel?

Give it a star on GitHub!