Dart Sass module for working with colors and creating themes
npm install ungic-sass-themeprefers-color-scheme for automatic theme switching.
.light and .dark classes.
ungic-sass-theme to your project:
sh
npm install ungic-sass-theme
`
---
$3
Define your color palette, brightness, and grayscale settings in a separate file:
š Example: myproject/themes/default.scss
`scss
$colors: (
primary: #07f857,
secondary: #3d3931,
success: #cce678,
danger: #e6787d,
info: #4bafee,
warning: #eee84b,
system: (#C6530C, #ef8646),
text-color: (#192d20, #fff9ea),
background-color: (#fff9ea, #192d20)
);
$config: (
brightness: (
offset-brighten: 0,
offset-dim: 0,
saturation-brighten: (0, 0),
saturation-dim: (0, 0)
),
relative-light-limit: true,
gray: (
saturation: 5%,
hue: blue
)
);
$palettes: (
primary: (
lighten: #e8f2c7,
darken: #4c5d15
),
secondary: (
lighten: #f5f3e6,
darken: #2a2925
)
);
// Default inverse mode (only as fallback)
$inverse-mode: false;
`
---
$3
š Example: myproject/theme.scss
`scss
@use "sass:meta";
@use "./themes/default" as theme-config; // Import theme config
@use "ungic-sass-theme" with (
$theme: meta.module-variables(theme-config) // Pass theme config
);
@forward "ungic-sass-theme";
`
---
$3
Now you can start using your theme immediately:
`scss
@use "./theme" as theme;
body {
background-color: theme.color(background-color); // or theme.bgc()
color: theme.color(); // or theme.color(text-color)
}
.btn {
color: theme.primary();
border: 2px solid theme.color(primary); // Same as theme.primary();
&:hover {
/ Adjust brightness automatically based on the theme (light = lighter, dark = darker) /
color: theme.primary(.2);
/ Relative theme-based adjustments /
border-color: theme.primary(theme.subs(2));
}
}
`
---
šØ Theme Inversion & Variable Rendering
The module now fully supports dynamic theme inversion via CSS variables, prefers-color-scheme, and class-based switching.
š¹ Previously, theme inversion was controlled globally:
`scss
$inverse-mode: false;
`
š¹ Now, inversion is dynamic and can be controlled via:
- Automatic detection (prefers-color-scheme)
- Manual class switching (.light, .dark)
---
$3
With include-vars(), themes adapt to the user's system preferences:
`scss
@mixin include-vars($with-media: true) {
$current-theme: getThemeType();
@if ($with-media) {
@media (prefers-color-scheme: light) {
@if ($current-theme == "light") {
@include render-default-vars();
} @else {
@include render-inverse-vars();
}
}
@media (prefers-color-scheme: dark) {
@if ($current-theme == "dark") {
@include render-default-vars();
} @else {
@include render-inverse-vars();
}
}
} @else {
@include render-default-vars();
}
@at-root .#{$current-theme} & {
@include render-default-vars();
}
$reverse-theme: if($current-theme == "light", "dark", "light");
@at-root .#{$reverse-theme} & {
@include render-inverse-vars();
}
@include store.resetAll();
}
`
š Themes switch automatically based on system settings!
---
$3
Manually switch themes using classes:
`html
...
`
ā
If .light or .dark is set, the theme will follow this class.
ā
If no class is set, the theme defaults to browser settings.
---
$3
#### š Per-Component Variable Rendering
Each component can generate its own variables:
`scss
.my-component {
background-color: color(primary, 0.7);
color: color();
padding: 44px;
max-width: 400px;
border-radius: 26px;
border: 2px solid gray(0.85);
@include include-vars(); // Render variables within this component
}
`
š¹ This ensures isolated, component-specific styles.
---
#### š Global Variable Rendering
To apply variables globally:
`scss
@include render-vars('.my-component');
`
š This ensures consistency across all .my-component elements.
---
š Why Choose Ungic SASS Theme?
ā Automates light & dark themes
ā Removes the need for hardcoded color logic
ā Scales effortlessly with large projects
ā Easily integrates with existing Sass frameworks
ā Supports both automatic and manual theme switching
---
$3
The Ungic SASS Theme Module now includes a pre-rendering feature, allowing developers to generate and store color variables upfront instead of dynamically computing them at runtime.
This is particularly useful when creating design systems, UI libraries, or multiple theme configurations, ensuring all colors are available in a single generated file.
---
šØ Why Use Pre-Rendering?
By default, colors are only generated when used inside a component or global scope. This keeps the final CSS optimized but might not be ideal for libraries, where you want a predefined set of color variables.
Pre-rendering allows you to:
ā
Generate all color variations upfront ā no need for per-component computation.
ā
Store variables in a single file ā avoid duplication across components.
ā
Create multiple themes with different configurations ā simply switch files.
ā
Reduce runtime overhead ā variables are already calculated.
ā
Ensure consistency ā all components reference the same colors.
---
āļø How Pre-Rendering Works
Pre-rendering creates a fixed color scale with a specified step size ($step-number), generating colors in the range of -1 to 1.
š¹ Instead of defining colors dynamically in each component, pre-rendering allows storing all possible color variations upfront in CSS variables.
š¹ However, this method has limitations (see Pros & Cons section below).
---
š Pre-Rendering Mixin
`scss
@mixin prerender-vars($selector: "body", $step-number: 0.05, $with-media: true) {
$colors: getColors(); // Get all theme colors
$color-names: map.keys($colors); // Extract color names
$colors: list.append($color-names, "gray"); // Include grayscale
@include store.resetAll(); // Reset variable store
// Loop through all colors
@each $color-name in $colors {
$step: -1; // Start from -1
@while $step <= 1 {
$generated-color: color($color-name, $step); // Generate color variation
$step: $step + $step-number; // Increment step
}
}
@include render-vars($selector, $with-media); // Apply rendering
}
`
---
š How to Use It
Instead of manually defining color variables inside each component, use prerender-vars() to generate a theme-wide set of colors:
`scss
@include prerender-vars();
`
This will:
- Precompute all shades of every theme color.
- Store them in CSS variables.
- Make them accessible globally without recalculating in components.
---
š¹ Pre-Rendering vs. On-Demand Rendering
| Feature | Pre-Rendering (prerender-vars()) | Dynamic Rendering (color() inside component) |
|----------------------|------------------------------------|-----------------------------------|
| Performance | š¢ Optimized (generated once) | š“ Recomputed in each component |
| Flexibility | š“ Limited color adjustments | š¢ Full color customization |
| File Size | š“ Larger (all variations stored) | š¢ Smaller (only needed colors) |
| Best for... | š¦ Libraries, UI frameworks | šØ Individual UI components |
---
ā
Pros & ā Cons of Pre-Rendering
$3
ā One-time computation ā No need to recalculate colors in each component.
ā No duplication ā Colors are stored once in a dedicated file.
ā Better for design systems ā Ensures color consistency across projects.
ā Multiple themes support ā Create different theme files and load them dynamically.
$3
ā Limited flexibility ā Only generates a fixed color scale (step size is developer-defined).
ā Cannot generate any color dynamically ā Only predefined variations are available.
ā No access to advanced color parameters ā The lightness and brightness controls available in color() are not supported in pre-render.
ā Might increase CSS size ā Generates all possible variations, even if some are unused.
---
šÆ When Should You Use Pre-Rendering?
$3
ā You are building a UI library where colors should be predefined.
ā You need multiple themes as separate files (theme-first.css, theme-secondary.css).
ā You want all color variations stored upfront instead of computing them dynamically.
$3
ā You need dynamic, real-time color generation (e.g., custom gradients, on-the-fly calculations).
ā You want maximum flexibility for theme colors inside components.
ā You prefer lighter CSS output, as pre-rendering generates all variations.
---
šØ Example: Multi-Theme Pre-Rendering
You can create separate theme files using prerender-vars():
$3
`scss
@use "base-theme" with ($theme: first-theme-config);
@include prerender-vars();
`
$3
`scss
@use "base-theme" with ($theme: secondary-theme-config);
@include prerender-vars();
``