Use Krysalicss with Vite

Drop Krysalicss into a Vite project — vanilla, React, Vue, Svelte, or Solid. The recipe is the same: install, import a SCSS entry from your app code, and let Vite's built-in Sass pipeline do the rest.

Install

Add Vite's preferred Sass implementation (sass) and the framework:

Terminal
pnpm add -D sass @adnap/krysalicss

Vite v5+ auto-detects sass-embedded when present; either implementation works. You don't need a plugin: Vite resolves .scss imports out of the box once sass is installed.

Wire the SCSS entry

Create one SCSS entry file under src/styles/ and @use the framework's batteries-included entry from there. The sass condition in Krysalicss's package.json exports resolves the bare specifier @adnap/krysalicss straight to src/krysalicss.scss — no ~ prefix, no path mapping.

src/styles/app.scss
// src/styles/app.scss
@use '@adnap/krysalicss';

Then import the SCSS entry from your app's TS/JS entry point. Vite compiles it as part of the regular build and HMR pipeline:

src/main.ts
// src/main.ts
import './styles/app.scss';

The Sass implementation Vite uses can be tuned in vite.config.ts. The modern-compiler API is the supported path going forward and unblocks mixed deprecation messages on newer Sass releases:

vite.config.ts
// vite.config.ts
import { defineConfig } from 'vite';

export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        api: 'modern-compiler',
      },
    },
  },
});

Override a variable

Every !default knob in the framework is overridable from the consumer SCSS entry. Place the configured @use before the framework @use or Sass picks up the default first.

src/styles/app.scss
// src/styles/app.scss
@use '@adnap/krysalicss/element/button' with (
  $border-radius: 999px,
  $padding-x: 1.5rem,
);
@use '@adnap/krysalicss';

See Override component variables for the full pattern (root-level overrides, palette swaps, selector retargeting).

Strip unused modules

Pass a $feature-list of <category>-<name> tokens to the framework entry. Vite compiles only the slices you ask for; everything else is dropped from the bundle.

src/styles/app.scss
// src/styles/app.scss
@use '@adnap/krysalicss' with (
  $feature-list: (
    base-reset,
    base-global,
    typography-base,
    typography-title,
    typography-link,
    layout-container,
    layout-flex,
    element-button,
    module-card,
  ),
);

This works at the Sass layer — your final CSS bundle drops everything not in the list. See Tree-shake to specific modules for the full inventory of flags.

Light + dark theme switching

The framework ships default and dark themes. The dark theme emits under both @media (prefers-color-scheme: dark) and .theme-dark, so OS preference works automatically; a manual toggle just adds or removes the class on <html>.

src/main.ts
// src/main.ts
const root = document.documentElement;
const saved = localStorage.getItem('theme');
if (saved === 'dark') root.classList.add('theme-dark');

document.querySelector('#toggle')?.addEventListener('click', () => {
  root.classList.toggle('theme-dark');
  localStorage.setItem(
    'theme',
    root.classList.contains('theme-dark') ? 'dark' : 'light',
  );
});

import './styles/app.scss';

To avoid a flash of light theme before hydration, set the class with an inline <script> in index.html ahead of the framework stylesheet import — see the tutorial for the pattern.

See also