Fundamentals

Variables and Modes

Learn how to use theme variables and modes in your CSS.

Overview

This document explains how to define and use variables and modes in the Master CSS framework. Variables allow for reusable values throughout your styles, while modes enable conditional styling for different contexts like light/dark themes.

Master CSS Variables and ModesMaster CSS Variables and Modes

For a classic example, use the primary token in your markup:

<div class="bg:#000000@light">…</div> <div class="bg:#ffffff@dark">…</div> <div class="bg:primary">…</div>

Design tokens are a fundamental part of design systems and are crucial for maintaining design consistency and efficiency in projects, especially in larger organizations or projects with complex design requirements. They help bridge the gap between design and development, promoting collaboration and ensuring a cohesive user experience.


Understanding variables

Variables in Master CSS provide a way to define reusable values that can be referenced throughout your styling. They help maintain consistency and make theme changes simpler.

Defining variables

Variables are defined in the variables section of your configuration file. The basic syntax follows a hierarchical structure:

export default {    variables: {        full: '100%',                                                           spacing: {            md: 20,                                                             },        color: {            black: '#000',              /*  <─┐ */                                  primary: '$color-black',    /*  ──┘  linked to black */             }    }}
  • Variable black is parsed as a color-type variable.
  • Variable primary is linked to $color-black and parsed as a color-type variable.
  • Variable full is parsed as a string-type variable.
  • Variable md is parsed as a number-type variable.

Spacing variables should be defined in spacing section.

Using variables in classes

Once defined, you can use these variables in your markup. The syntax for using variables is straightforward:

<div class="bg:black">…</div><div class="bg:primary">…</div><div class="w:full">…</div><div class="m:md">…</div>
Generated CSS
@layer base, theme, preset, components, general;@layer general {    .m\:md {        margin: 1.25rem    }    .bg\:black {        background-color: rgb(0 0 0)    }    .bg\:primary {        background-color: rgb(0 0 0)    }    .w\:full {        width: 100%    }}

Contextual resolution of variables

Master CSS resolves variable names like primary based on their usage context. When used with color-related properties — such as background-color or its shorthand bg — the system maps primary accordingly:

<div class="background-color:primary">…</div><div class="bg:primary">…</div>

This contextual alias resolution avoids conflicts with similarly named variables and ensures consistent, predictable behavior. For example, variables.primary always maps to a color property when used in a color context, never to unrelated properties. This design promotes concise, semantic markup without sacrificing clarity.

Namespace-aware variable mapping

Variables can be defined within the namespace of a specific CSS property and applied using shorthand syntax. For example, you can define a custom font-family variable in your configuration:

export default {    variables: {        'font-family': {            'open-sans': 'Open Sans'         }    }}

Once defined, you can reference the variable in your markup using the shorthand property:

<div class="font-family:open-sans">…</div><div class="font:open-sans">…</div>

This ensures that open-sans is only interpreted as a font-family value, promoting both clarity and brevity in your code.

Variable inlining mechanism

For non-mode variables, optimization is achieved by directly inlining values #000 and removing intermediate references variables.primary.

.bg\:primary {    background-color: #000;}

You can also use native CSS variable declarations explicitly, but it will not generate --primary: #000 rules and you will have to define them manually as usual.

<div class="fg:var(--color-primary)">…</div>

It will be compiled to:

.fg\:var\(--color-primary\) {    color: var(--color-primary);}

Modes for variables

Modes in Master CSS allow you to define different variable values based on the context, such as light or dark themes. This enables you to create responsive designs that adapt to user preferences or system settings.

Modes can be applied to individual classes using the @<mode> syntax:

<div class="bg:black@dark">…</div><div class="bg:white@light">…</div>
Generated CSS
@layer base, theme, preset, components, general;@layer general {    @media (prefers-color-scheme:dark) {        .bg\:black\@dark {            background-color: oklch(0% 0 none)        }    }    @media (prefers-color-scheme:light) {        .bg\:white\@light {            background-color: oklch(100% 0 none)        }    }}

However, when attempting to implement a complete design system, marking the mode in the template not only clutters the markup but also makes your design structure harder to standardize and maintain.

Defining variables with modes

Variable modes are defined in the modes section of your configuration file. For example, add color variables in different modes.

export default {    variables: {        color: {            primary: '#ff0000'        }    },    modes: {        light: {            color: {                primary: '#000000'             }        },        dark: {            color: {                primary: '#ffffff'             }        }    }}
  • The dark mode defines a primary color of #000000.
  • The light mode defines a primary color of #ffffff.
  • The default defines a primary color of #ff0000.

Using mode variables in classes

You can use mode variables like primary in your markup by applying the same variable name in different contexts without confusion.

<div class="bg:primary">…</div>
Generated CSS
@layer base, theme, preset, components, general;@layer theme {    :root {        --color-primary: rgb(255 0 0)    }    @media (prefers-color-scheme:light) {        :root {            --color-primary: rgb(0 0 0)        }    }    @media (prefers-color-scheme:dark) {        :root {            --color-primary: rgb(255 255 255)        }    }}@layer general {    .bg\:primary {        background-color: var(--color-primary)    }}

Since Master CSS recognizes that the primary variable is mode-dependent, it compiles it into a standard CSS custom property and accesses it via the var(--primary) syntax.

Mode triggers

Master CSS supports three mode triggers, allowing you to choose how modes are applied in your styles. The available triggers are:

  • media Uses media queries to apply the mode based on user preferences.
  • class Applies the mode based on a class name.
  • host Applies the mode based on the shadow host element's class.
export default {    modeTrigger: 'media' /* default */ }

For example, apply the background color #000 in dark mode:

<div class="bg:black@dark">

By default, drive theme styles through 'media' queries:

@media (prefers-color-scheme: dark) {    .bg\:#000000 {        background-color: #000000    }}

Drive theme styles through 'class' names:

.dark .bg\:#000000 {    background-color: #000000}

Drive theme styles through shadow DOM's 'host':

:host(.dark) .bg\:#000000 {    background-color: #000000}

Default mode

The default mode is applied when no specific mode is specified. You can set the default mode in your configuration file:

export default {    defaultMode: 'light', /* default */     modeTrigger: 'class'}

With default 'light' mode:

.light, :root {    --color-primary: 0 0 0;}

No default mode false:

.light {    --color-primary: 0 0 0;}

The defaultMode has no effect with 'media' trigger, as CSS always applies either light or dark color preferences based on the user's system settings.


Implementing mode switching

You can use the prefers-color-scheme media query to detect the user's system preference. However, CSS does not allow you to control the user's prefers-color-scheme.

Using class-driven styles

To enable manual mode switching, use a class-based approach instead.

export default {    modeTrigger: 'class' }

Then you can control the theme mode by adding the dark class to the <html>:

<html class="dark">    <body>        <div class="bg:primary">…</div>    </body></html>

Detect and store user preferences

To detect and store user preferences, use JavaScript to check the user's system preference and store it in localStorage. This allows you to persist the user's choice across sessions.

const key = 'theme-preference';const defaultPreference = 'system';const preference = localStorage.getItem(key) || defaultPreference;const value = preference === 'system'    ? matchMedia('(prefers-color-scheme:dark)').matches ? 'dark' : 'light'    : preference;document.documentElement.classList.add(value);if (['dark', 'light'].includes(value)) {    document.documentElement.style.colorScheme = value;}

This code checks the user's preference and applies the appropriate class to the <html> element. It also sets the color-scheme property to ensure proper rendering of colors in the selected mode.


  • Master UI


© 2025 Aoyue Design LLC.MIT License
Trademark Policy