Skip to content

CSS

Bunup handles CSS automatically. Just import it and it works.

Quick Start

Import CSS in your TypeScript files:

src/index.ts
typescript
import './styles.css';
import { Button } from './components/button';

export { Button };
src/styles.css
css
.button {
  background-color: #007bff;
  color: white;
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
}

Bunup automatically bundles your CSS into dist/index.css with cross-browser compatibility.

Any CSS imports encountered in your files will be bundled together into dist/index.css.

To generate separate CSS files instead of a single index.css output, add them as entry points rather than importing them in your files:

bunup.config.ts
typescript
import { defineConfig } from 'bunup';

export default defineConfig({
  entry: [
    'src/index.ts',
    'src/components/button.css'
    'src/components/alert.css'
  ],
});

This creates individual CSS files in your build output:

plaintext
dist/
├── index.js
└── components/
    ├── button.css
    └── alert.css

CSS Modules

CSS modules prevent style conflicts by automatically scoping class names. Just add .module.css to your filename:

TIP

New to CSS modules? Check out this guide to learn what they are and why they're useful.

src/components/button.module.css
css
.primary {
  background-color: #007bff;
  color: white;
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
}
src/components/button.tsx
tsx
import styles from "./button.module.css";

export function Button({ children }) {
  return (
    <button className={styles.primary}>
      {children}
    </button>
  );
}

That's it! Bunup handles the rest automatically.

Sharing Styles

Reuse styles with the composes property:

src/components/button.module.css
css
.base {
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.primary {
  composes: base;
  background-color: #007bff;
  color: white;
}

.secondary {
  composes: base;
  background-color: transparent;
  color: #007bff;
  border: 1px solid #007bff;
}

Rules:

  • composes must come first in the class
  • Works only with single class selectors (not #id or .class1, .class2)

From other files:

src/components/button.module.css
css
.primary {
  composes: base from "../shared.module.css";
  background-color: #007bff;
  color: white;
}

WARNING

Avoid conflicting properties when composing from separate files.

Distributing CSS

Export CSS files for package consumers:

package.json
json
{
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "types": "./dist/index.d.ts"
    },
    "./styles.css": "./dist/index.css"
  }
}

Users can then import your styles:

javascript
import 'your-package/styles.css';
import { Button } from 'your-package';

<Button />

TIP

Use the inject styles option to bundle CSS directly into JavaScript so users do not need a separate CSS import.

Browser Compatibility

Bunup automatically ensures cross-browser compatibility:

  • Converts modern CSS syntax to work in older browsers
  • Adds vendor prefixes (-webkit-, -moz-, etc.) where needed
  • Targets: Chrome 87+, Firefox 78+, Safari 14+, Edge 88+

TypeScript Support

Bunup automatically creates TypeScript definitions for CSS modules. Get autocomplete and type safety for free.

src/components/button.module.css
css
.primary {
  background-color: #007bff;
  color: white;
}

.secondary {
  background-color: transparent;
  color: #007bff;
}

Bunup generates this TypeScript file:

src/components/button.module.css.d.ts
ts
declare const classes: {
  readonly primary: string;
  readonly secondary: string;
};

export default classes;

You get:

  • Autocomplete when typing styles.
  • Errors for typos like styles.primry
  • Safe refactoring when renaming CSS classes

Development

Type definitions generate automatically when you build. For the best experience with CSS modules, use watch mode:

sh
bunup --watch

Watch mode instantly regenerates type definitions when CSS module files change. Change a class name and save, you'll immediately see TypeScript errors wherever the old class name is used.

Configuration

Exclude from Git

Since type definitions are auto-generated, exclude them from version control:

.gitignore
plaintext
**/*.module.*.d.ts

Disable type generation

Turn off automatic type generation if you prefer to handle it manually:

sh
bunup --no-css.typed-modules
ts
import { defineConfig } from 'bunup';

export default defineConfig({
  css: {
    typedModules: false
  }
});

Released under the MIT License.