Configuration
NuvoUI core is configured with Sass module configuration: you pass variables in a with (...) clause when you load it. Every setting has a default, so an empty configuration works; you set only what you change.
Loading core with with ()
Section titled “Loading core with with ()”@use "@nuvoui/core" as * with ( $generate-utility-classes: true, $brand: #4361ee, $feature-flags: ("animations": false));- Configure once. Sass loads a module once per compilation, so the configuration goes on the first
@useof core. A second@use ... withof the same module fails withThis module was already loaded, so it can't be configured using "with". - Only known variables. A variable that core does not declare fails with
This variable was not declared with !default in the @used module.This is also how removed 1.x settings such as$primaryand$secondaryare reported. - Maps replace, they do not merge. A scale map such as
$spacingsor$font-sizesreplaces the default map, so include every key you use. The exceptions are$feature-flags, where a missing flag counts as on, and the theme maps, which hold overrides only.
One configuration for many files
Section titled “One configuration for many files”In a project with several stylesheets, put the configuration in one partial and load that partial everywhere.
@forward "@nuvoui/core" with ( $generate-utility-classes: true, $brand: #4361ee);@use "../nuvoui" as *;
.card { @include apply(p(4), bg(surface), rounded(lg));}Core emits CSS when it is loaded: the reset, the base element styles, the tokens and, when enabled, the utility classes. Within one compilation that CSS is emitted once, however many files load the partial. A stylesheet compiled on its own, as a separate entry point, emits it again.
What core emits
Section titled “What core emits”| Output | Emitted when |
|---|---|
Reset (@layer reset) |
Always |
Base element styles and .sr-only (@layer base) |
The base flag is on (default) |
Tokens: fixed :root block, light block, dark block, operating system fallback |
The theme flag is on (default) |
Tooltips (@layer components) |
The tooltips flag is on (default), with or without utility classes |
| Utility classes | $generate-utility-classes: true and the feature’s flag |
Reset, base and components live in cascade layers (@layer reset, base, components). Utility classes and your own CSS are not in a layer, so they always win over the base styles without !important.
$generate-utility-classes
Section titled “$generate-utility-classes”$generate-utility-classes decides whether the utility classes are emitted. It is false by default: a project that styles everything through apply() gets mixins, functions, tokens and base styles, and no classes.
// Mixins and tokens only@use "@nuvoui/core" as *;// Mixins, tokens and every utility class@use "@nuvoui/core" as * with ($generate-utility-classes: true);The prebuilt stylesheet in the package (dist/nuvoui.css and dist/nuvoui.min.css) is compiled with utility classes on and the default configuration.
Feature flags
Section titled “Feature flags”$feature-flags turns groups of output on and off. Every flag is on by default, and a flag missing from your map counts as on, so the map lists only what you turn off.
@use "@nuvoui/core" with ( $generate-utility-classes: true, $feature-flags: ( "animations": false, "backdrops": false, "tooltips": false ));Turning a flag off removes output, never mixins: every mixin stays available in apply(). Each flag owns its classes completely.
| Flag | Controls |
|---|---|
alignments |
Vertical alignment classes (align-top, align-middle) |
animations |
Animation classes (animate-spin, hover-ready) |
backdrops |
Backdrop filter classes |
base |
Base element styles and .sr-only; needs no utility classes |
borders |
Border width, colour, style and radius classes |
container |
.container, .container.flex, .container.grid |
container-queries |
Query container classes (container-inline-size, container-sidebar) |
cursors |
Cursor classes |
displays |
Display, visibility, overflow and truncation classes; not .flex or .grid |
flex |
.flex, .flex.inline, .flex@{breakpoint} and every flex modifier and child class |
grid |
.grid, .grid.inline, .grid@{breakpoint}, every grid modifier and the span classes |
opacity |
Opacity classes |
position |
Position, offset and inset classes |
shadows |
Shadow classes |
sizing |
Width, height, minimum and maximum size classes |
spacing |
Padding, margin, gap and space classes |
theme |
All tokens and the colour classes |
tooltips |
Tooltip styles |
transforms |
Transform classes |
transitions |
Transition, duration, easing and delay classes |
typography |
Font size, weight, line height, tracking, alignment, case, decoration and wrapping classes |
z-index |
Z-index classes |
Three flags need more care:
typographywas namedconfig-typoin 1.x. The old key is ignored in 2.0 (a missing flag counts as on), so("config-typo": false)no longer turns anything off. Rename it.flexandgridown every flex and grid class, including.container.flexand.container.grid. With("displays": false), flex and grid layouts keep working.themeoff removes every token as well as the colour classes. Scale mixins then output raw values (p(4)gives1rem),token()and colour words such asbg(brand),bg(red, 600)ortext-color(muted)raise an error that says the theme flag is off, and base styles use the raw$font-family.black,whiteandtransparentstill compile, as plain CSS colours.
// Keep layout, drop the display utilities@use "@nuvoui/core" with ( $generate-utility-classes: true, $feature-flags: ("displays": false));$parent-selector
Section titled “$parent-selector”$parent-selector scopes the utility classes and the base element styles under a selector. Use it to add NuvoUI to part of a page that has other styles, such as a widget or a documentation site.
@use "@nuvoui/core" with ( $generate-utility-classes: true, $parent-selector: ".app");.app .p-4 { padding: var(--nu-space-4);}@layer base { body.app, .app:not(body) { background-color: var(--nu-bg-base); /* ... */ } .app h1 { /* ... */ }}| Output | Scoped by $parent-selector |
|---|---|
| Utility classes | Yes: .app .p-4 |
Base element styles and .sr-only |
Yes: .app h1, and the body rules on the scope element |
| Light tokens | On :root (global); nested light sections use .app [data-theme="light"] |
| Dark, inverse, operating system fallback and high contrast tokens | No: global |
| Reset | No: global |
Tokens stay global so that every scope, and any CSS outside it, reads the same values. This site uses $parent-selector: ".nuvoui": the live examples render inside a .nuvoui element, while the documentation layout around them keeps its own styles.
The default is "", which emits unscoped classes.
$enable-dark-mode
Section titled “$enable-dark-mode”$enable-dark-mode (default true) controls the dark theme. With false, core emits no dark token block, no prefers-color-scheme fallback, no data-theme="inverse" sections and no dark high contrast block; the dark-mode mixin outputs nothing. $dark-theme and $high-contrast-dark are then not used.
@use "@nuvoui/core" with ( $enable-dark-mode: false);Other settings
Section titled “Other settings”| Variable | Default | Purpose |
|---|---|---|
$breakpoints |
xs 480px to 2xl 1536px |
Responsive suffixes, media query mixins, container widths |
$base-size |
1rem |
html font size in the base styles |
$column-count |
12 |
Flex fill-* columns, grid cols-*, rows-* and spans |
$enable-debugger |
false |
Emits styles for a breakpoint debugging overlay (.NuvoUI-Debugger-Wrapper) |
The default breakpoints:
| Suffix | Media query |
|---|---|
@xs | @media (min-width: 480px) |
@sm | @media (min-width: 640px) |
@md | @media (min-width: 768px) |
@lg | @media (min-width: 1024px) |
@xl | @media (min-width: 1280px) |
@2xl | @media (min-width: 1536px) |
Scale maps
Section titled “Scale maps”Each map is described on the page that uses it.
| Maps | Page |
|---|---|
$spacings, $percentages, $control-heights, $control-padding-inline |
Spacing, Sizing |
$border-widths, $border-radii |
Borders |
$shadow-sizes, $shadow-colors |
Shadows |
$z-indexes, $z-index-levels |
Z-index |
$opacities |
Opacity |
$font-family, $font-sizes, $font-weights, $line-heights |
Typography |
$durations, $delays, $timing-functions, $transition-default-duration, $transition-default-ease |
Transitions |
$grid-item-sizes |
Grid |
$brand, $success, $danger, $warning, $info, $color-primitives, $basic-colors |
Colours |
$light-theme, $dark-theme, $high-contrast-light, $high-contrast-dark |
Theming |
Base element styles read some keys from these maps: $spacings 1, 2 and 4, $border-radii xs, $border-widths 1 and 4, $font-sizes sm, base, lg, xl, 2xl, 3xl and 4xl, $font-weights normal and bold, $line-heights normal and tight, $control-heights and $control-padding-inline md, and the keys named by $transition-default-duration and $transition-default-ease. Removing one of them while the base flag is on raises an error that names the missing key and the map.
Reading configuration in SCSS
Section titled “Reading configuration in SCSS”Every configuration variable is exported, so your own SCSS can read the configured values for compile-time maths.
@use "sass:map";@use "@nuvoui/core" as nuvo;
.sidebar { width: map.get(nuvo.$spacings, 64); @include nuvo.media-up(lg) { width: calc(map.get(nuvo.$breakpoints, lg) / 4); }}Derived lists and internals are not public. $primitive-color-names (derived from $color-primitives) can be read but not configured; $theme-tokens, $color-names, $color-names-with-basic, $translate-values, $negative-translate-values, $colors-primitives, $digit-map, $colors and $color-cache are not exported, and neither are the functions to-css-var(), to-color(), from-hex(), hex-to-dec(), luminance(), is-valid-color(), is-valid-shade() and validate-theme-tokens() or the validate-tokens mixin.
For values that should follow the theme, read tokens with token() instead. See Tokens.