SASS variables
CDS 4 styles are written in SASS/SCSS, and part of the internal setup — the base reset, global typography, font, grid and breakpoints — is extracted into SASS variables flagged with !default. You can override them when building your application through the standard module configuration mechanism: @use '…' with (…).
SASS variables are the compile-time configuration layer. Colors, spacing and the rest of the component design tokens live in CSS variables (
--cds-*) and are configured by themes at runtime — see Theming. Start with the theme; drop down to SASS variables when you need to change the base layer itself: reset, typography, grid.
Setup
Vite compiles SCSS out of the box — you only need the preprocessor itself:
npm install -D sass-embeddedpnpm add -D sass-embeddedyarn add -D sass-embeddedbun add -d sass-embeddedThe classic sass works too, but sass-embedded is noticeably faster. To speed up large builds, opt into the modern compiler API:
// vite.config.ts
export default defineConfig({
css: {
preprocessorOptions: {
scss: { api: 'modern-compiler' }
}
}
});Plugging in with a configuration
Normally the base styles are plugged in as ready-made CSS — import '@central-design-system/components/styles'. To override SASS variables, replace that import with your own SCSS file: in SCSS the @central-design-system/components/styles entry point resolves to the sources of the base layer (the sass export condition in package.json), and your configuration is applied at compile time.
// main.ts
import { createApp } from 'vue';
- import '@central-design-system/components/styles';
+ import './styles/main.scss';// src/styles/main.scss
@use '@central-design-system/components/styles' with (
$reset: false,
$body-font-family: ('Inter', sans-serif)
);The component styles themselves need nothing extra: they are precompiled and ship with the components' JS chunks — both with selective and with full registration (see Tree-shaking).
Wrap a value containing commas —
$body-font-familywith several fonts, for instance — in parentheses, otherwise SASS reads it as several arguments.
A settings file
Module configuration is applied once, on the first load. If you need the values not only in the entry point but also in your application's component styles, extract them into a separate settings file and use that everywhere:
// src/styles/settings.scss
@forward '@central-design-system/components/styles/settings' with (
$body-font-family: ('Inter', sans-serif),
$grid-gutter: 24px
);// src/styles/main.scss
@use './settings'; // configures the CDS variables
@use '@central-design-system/components/styles'; // the base is built with them<!-- Component.vue -->
<style lang="scss">
@use '@/styles/settings' as s;
.card {
gap: s.$grid-gutter;
font-family: s.$body-font-family;
}
</style>Every <style> block is compiled separately, so "configure it in main.scss and read it straight from the package" won't work — a direct @use '@central-design-system/components/styles/settings' in a component would return the default values. A shared settings file guarantees identical values at every compilation point.
The styles/settings entry contains variables only and emits not a single byte of CSS — it's safe to include in any number of files.
Global variables
| Variable | Default | What it does |
|---|---|---|
$reset | true | Emit the base layer's CSS reset |
$legacy-reset | false | Reset for compatibility with CDS 3 markup |
$enable-typography | true | Global typography (h1–h6, .h1–.h6 and so on) |
$body-font-family | var(--cds-font-family), 'PT Root UI VF', … | body font |
$font-size-root | var(--cds-base-unit) (16px) | Root font size |
$line-height-root | 1.5 | Root line height |
$border-color-root | transparent | Default border color |
$border-style-root | solid | Default border style |
$border-radius-root | var(--cds-border-radius-200) | Base corner radius |
$size-scale | 4px | Step of the size scale |
$sizes | ('xs', 'sm', 'md', 'lg', 'xl') | Size names |
$rounded | map | Radius scale (sm, md, lg, xl, pill, circle, …) |
Grid and breakpoints
| Variable | Default | What it does |
|---|---|---|
$prefix | 'cds' | Prefix of the grid CSS classes |
$flex-grid-columns | 16 | Number of flex grid columns (12 is supported too) |
$grid-gutter | 32px | Grid gutter |
$grid-gutter-condensed | 1px | Gutter of the condensed grid |
$grid-breakpoints | map | Breakpoints: width, columns and spacing for xs–xl |
The grid variables belong to the same settings module, while the breakpoint and grid mixins live in a separate styles/breakpoints entry — which emits no CSS either:
@use '@/styles/settings' as s;
@use '@central-design-system/components/styles/breakpoints' as bp;
.sidebar {
gap: s.$grid-gutter;
@include bp.cds-breakpoint-up('md') {
width: 320px;
}
}SASS breakpoints affect your styles and the grid mixins. The runtime breakpoints of
useDisplayare configured separately, through thedisplayoption ofcreateCds(see Display & Platform). The two sets match by default; when you change one, don't forget the other.
Component variables and vite-plugin
Without the plugin, @use … with configures the base layer only: component CSS is precompiled. The @central-design-system/vite-plugin plugin lifts that limitation — it recompiles the styles of every component you use with your settings file:
// vite.config.ts
import cds from '@central-design-system/vite-plugin';
export default defineConfig({
plugins: [
vue(),
cds({ styles: { configFile: 'src/styles/settings.scss' } })
]
});The settings file is the same, but you have to forward styles/component-settings — the aggregate that includes both global and component variables:
// src/styles/settings.scss
@forward '@central-design-system/components/styles/component-settings' with (
$border-radius-root: 0, // global
$button-border-radius: 9999px // component-level
);With the plugin you don't need to change the @central-design-system/components/styles import in main.ts — it starts meaning "the configured base layer" on its own, and component styles are rebuilt on the fly. The plugin can also auto-import components from templates (autoImport: true by default), which makes registration in createCds({ components }) optional.
What SASS can't configure
- Component-local variables (
$button-border-radiusand friends fromstyles/_CdsX.variables.scss). Unavailable without the plugin: component CSS is published precompiled, so its local variables are frozen at the moment the library was built. With@central-design-system/vite-pluginthey are configured throughstyles/component-settings— the plugin recompiles the published SCSS sources of the components with your settings file (see above). - Turning off individual utility classes. Instead of a toggle map, pick an entry point by content:
styles/core— layers, fonts and reset only;styles/common— plus typography and helpers. - CSS layers.
@layer cds-*is always on: the layer order is declared in the base style layer, and ordinary application CSS (outside@layer) always beats the design system's styles — there is nothing to turn off here.
Pitfalls
- Variables only in the settings file. Any styles or imports of regular style files inside
settings.scssget duplicated into every file that includes it. Styles belong inmain.scss; the settings file holds variables, mixins and functions. - Configure before the module's first load.
@use … withfails with amodule was already loadederror if the settings module has already been loaded without a configuration higher up the chain. Include the settings file first. - Build speed. With ready-made CSS there is nothing to compile; with a configuration the base layer is built together with the application. The volume is small, but the difference shows on cold builds —
sass-embeddedandapi: 'modern-compiler'keep it to a minimum. - Resolution assumes a bundler. Bare imports such as
@use '@central-design-system/components/styles'are resolved by Vite and webpack (sass-loader) through thesassexport condition. In plainsassCLI without a bundler you'll have to point the paths at the files insidenode_modulesby hand.