CSS
Vantris ships a full CSS pipeline powered by lightningcss: url() rewriting, @import inlining, CSS Modules, Sass/Less, PostCSS, and CSS code splitting — with identical behaviour in dev and build. In dev, CSS hot-swaps with no reload.
Importing CSS
Import a stylesheet from JavaScript and it's injected into the page:
import "./styles/app.css";- In dev, the import becomes a style-injecting module — editing the file swaps the
<style>in place, no reload, no lost state. - In the build, it's processed and emitted as a hashed
.csswith a<link>injected into the HTML.
You can also link a stylesheet directly in index.html; it's served as text/css in dev and hashed/rewritten in the build if it points into rootDir.
url() and @import
The pipeline handles the two things that break naïve CSS bundling:
url()rewriting —background: url("./bg.png")resolves and hashes the asset, respectingbase.@importinlining —@import "./base.css"is inlined into the output so the browser doesn't make extra round-trips.
Aliases work inside CSS too:
@import "@/styles/base.css";
background: url("@/images/hero.png");See Aliases.
CSS Modules
Any file ending in *.module.css is treated as a CSS Module — class names are locally scoped and exposed as a JS object:
/* Button.module.css */
.primary {
color: white;
background: #8b5cf6;
}import styles from "./Button.module.css";
export function Button() {
return <button className={styles.primary}>Click</button>;
}The imported object maps your local names to the generated, collision-free class names. This works in dev and build.
Sass & Less
Sass and Less are supported when installed — they're optional peer dependencies, so add the one you use:
npm install -D sassnpm install -D lessThen import .scss, .sass, or .less files (including *.module.scss for scoped modules):
import "./styles/app.scss";
import styles from "./Card.module.scss";Everything else in the pipeline (url(), @import, code splitting) applies to the compiled output.
PostCSS
If a postcss.config.* file exists at the project root, Vantris runs your CSS through PostCSS automatically — no config field needed. Add your plugins there:
// postcss.config.js
export default {
plugins: {
autoprefixer: {},
},
};Install the PostCSS plugins you reference as dev dependencies.
CSS code splitting
Stylesheets imported by lazily-loaded (dynamic-import) chunks are split into their own .css files and loaded alongside their chunk — so a route's CSS ships only when that route loads, in the build. This is automatic.
Hot Module Replacement for CSS
CSS HMR is automatic and needs no opt-in. Editing any stylesheet — plain, CSS Modules, Sass, or Less — updates the <style> in place with no reload and no lost state. See HMR.
The base path
All emitted CSS URLs — url(), @imported assets, injected <link>s — respect base, so a build deployed under a sub-path or a CDN resolves its assets correctly. See Building → base.
Summary
| Feature | Dev | Build | Notes |
|---|---|---|---|
| Plain CSS import | ✅ | ✅ | Style-injecting in dev, hashed in build. |
url() rewriting | ✅ | ✅ | Hashed, base-aware. |
@import inlining | ✅ | ✅ | |
| CSS Modules | ✅ | ✅ | *.module.css / .scss. |
| Sass / Less | ✅ | ✅ | Optional peer dep. |
| PostCSS | ✅ | ✅ | Auto when postcss.config.* exists. |
| CSS code splitting | — | ✅ | Per lazy chunk. |
| Hot-swap (HMR) | ✅ | — | No reload, no opt-in. |