Use Krysalicss with Astro
Astro speaks SCSS natively through its bundled Vite pipeline. Install the framework, import an SCSS entry from a layout, and the rest is authoring HTML. No integration plugin needed.
Install
Astro uses Vite under the hood and treats .scss files the same way Vite
does: install the sass package and the framework.
pnpm add -D sass @adnap/krysalicss Wire the SCSS entry
Create a single SCSS entry under src/styles/. The framework's sass
export condition resolves @adnap/krysalicss to src/krysalicss.scss
— no alias config needed.
// src/styles/app.scss
@use '@adnap/krysalicss'; Import the entry once from a layout. Astro emits the result as a global stylesheet on every page that uses the layout, deduplicated automatically:
---
// src/layouts/BaseLayout.astro
import '../styles/app.scss';
interface Props {
title: string;
}
const { title } = Astro.props;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>{title}</title>
</head>
<body>
<slot />
</body>
</html> You can also @use the framework inside an inline <style is:global lang="scss">
block, but the dedicated entry keeps overrides discoverable and avoids
recompiling the same SCSS module graph for every page.
Override a variable
Place the configured @use ahead of the framework entry in your SCSS
file. Sass picks up the override on first load:
// src/styles/app.scss
@use '@adnap/krysalicss/module/navbar' with (
$gap: 1.5rem,
$item-padding-x: 1rem,
);
@use '@adnap/krysalicss'; See Override component variables for the full override surface (per-component, root-level, selectors, palettes).
Strip unused modules
Pass $feature-list to the framework entry. Astro/Vite compiles only
the slices you ask for:
// src/styles/app.scss
@use '@adnap/krysalicss' with (
$feature-list: (
base-reset,
base-global,
typography-base,
typography-title,
typography-link,
typography-content,
layout-container,
layout-flex,
element-button,
module-card,
module-navbar,
),
); See Tree-shake to specific modules for the full flag inventory and the per-module import alternative.
Light + dark theme switching
The dark theme listens for prefers-color-scheme automatically. For a
manual toggle, set the class on <html> from an inline script with
is:inline so Astro emits it verbatim before hydration — that avoids
the flash of light theme on first paint.
---
// src/layouts/BaseLayout.astro
import '../styles/app.scss';
---
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script is:inline>
try {
const saved = localStorage.getItem('theme');
if (saved === 'dark') document.documentElement.classList.add('theme-dark');
} catch {}
</script>
</head>
<body>
<slot />
</body>
</html> The toggle button itself is a small island. The bundled Vue toggle component in the Krysalicss docs is one example; the same pattern works in any UI integration Astro supports:
<script setup lang="ts">
function toggle() {
const root = document.documentElement;
root.classList.toggle('theme-dark');
localStorage.setItem(
'theme',
root.classList.contains('theme-dark') ? 'dark' : 'light',
);
}
</script>
<template>
<button class="button" @click="toggle">Toggle theme</button>
</template> See also
- Use Krysalicss with Vite: when you need a standalone Vite project.
- Use Krysalicss with Next.js: the App Router recipe.
- Override component variables: the
@use … with ()reference for all overrideable knobs.