Claude
Skills
Sign in
Back

css-modules

Included with Lifetime
$97 forever

CSS Modules with Lightning CSS and PostCSS for component-scoped styling. Covers *.module.css patterns, TypeScript integration, Vite configuration, and composition. Use when building complex animations, styling third-party components, or migrating legacy CSS.

Design

What this skill does


# CSS Modules

## Overview

CSS Modules provide locally-scoped CSS by automatically generating unique class names at build time. This prevents style conflicts and enables true component encapsulation.

## When to Use CSS Modules

| Use Case | CSS Modules | Tailwind |
|----------|-------------|----------|
| Complex animations | Best | Good |
| Third-party component styling | Best | Harder |
| Legacy CSS migration | Best | Refactor needed |
| Rapid prototyping | Slower | Best |
| Design system utilities | Not ideal | Best |
| Component encapsulation | Best | N/A |
| Team with CSS expertise | Best | Either |

**Hybrid Approach**: Use both together - Tailwind for utilities, CSS Modules for complex components.

---

## Documentation Index

### Vite Integration

| Topic | URL | Description |
|-------|-----|-------------|
| CSS Modules in Vite | https://vite.dev/guide/features#css-modules | Vite's built-in support |
| Lightning CSS | https://vite.dev/guide/features#lightning-css | Fast CSS transforms |
| PostCSS | https://vite.dev/guide/features#postcss | PostCSS configuration |

### Lightning CSS

| Topic | URL | Description |
|-------|-----|-------------|
| Documentation | https://lightningcss.dev/docs.html | Official docs |
| CSS Modules | https://lightningcss.dev/css-modules.html | Module support |
| Transpilation | https://lightningcss.dev/transpilation.html | Browser targeting |
| Bundling | https://lightningcss.dev/bundling.html | CSS bundling |

### CSS Modules Spec

| Topic | URL | Description |
|-------|-----|-------------|
| CSS Modules | https://github.com/css-modules/css-modules | Specification |
| Composition | https://github.com/css-modules/css-modules#composition | Composing classes |
| Scoping | https://github.com/css-modules/css-modules#naming | Local vs global |

### TypeScript Integration

| Topic | URL | Description |
|-------|-----|-------------|
| typed-css-modules | https://github.com/Quramy/typed-css-modules | Generate .d.ts files |
| vite-plugin-css-modules-dts | https://github.com/mrcjkb/vite-plugin-css-modules-dts | Vite plugin |

---

## CSS Modules Fundamentals

### File Naming Convention

```
src/
├── components/
│   ├── Button/
│   │   ├── Button.tsx
│   │   ├── Button.module.css      # CSS Module
│   │   └── Button.test.tsx
│   └── Card/
│       ├── Card.tsx
│       ├── Card.module.css        # CSS Module
│       └── index.ts
```

Files ending in `.module.css` are automatically processed as CSS Modules.

### Basic Usage

```css
/* Button.module.css */
.button {
  padding: 0.5rem 1rem;
  border-radius: 0.375rem;
  font-weight: 500;
  transition: background-color 150ms ease;
}

.primary {
  background-color: hsl(221, 83%, 53%);
  color: white;
}

.primary:hover {
  background-color: hsl(224, 76%, 48%);
}

.secondary {
  background-color: hsl(0, 0%, 96%);
  color: hsl(0, 0%, 9%);
}
```

```tsx
// Button.tsx
import styles from './Button.module.css'

interface ButtonProps {
  variant?: 'primary' | 'secondary'
  children: React.ReactNode
}

export function Button({ variant = 'primary', children }: ButtonProps) {
  return (
    <button className={`${styles.button} ${styles[variant]}`}>
      {children}
    </button>
  )
}
```

### Generated Class Names

```html
<!-- Input -->
<button class="${styles.button} ${styles.primary}">

<!-- Output (generated) -->
<button class="Button_button_x7d9f Button_primary_a3k2j">
```

### Local vs Global Scope

```css
/* Local by default */
.button {
  /* Generates: Button_button_hash */
}

/* Explicit local */
:local(.button) {
  /* Same as above */
}

/* Global (escape hatch) */
:global(.external-library-class) {
  /* Kept as-is: .external-library-class */
}

/* Global within local */
.card :global(.markdown-body) {
  /* Scoped parent, global child */
}
```

---

## Composition

### composes Keyword

Share styles between classes:

```css
/* base.module.css */
.flexCenter {
  display: flex;
  align-items: center;
  justify-content: center;
}

.interactive {
  cursor: pointer;
  transition: all 150ms ease;
}
```

```css
/* Button.module.css */
.button {
  composes: flexCenter from './base.module.css';
  composes: interactive from './base.module.css';
  padding: 0.5rem 1rem;
}
```

### Multiple Compositions

```css
.primaryButton {
  composes: button;
  composes: primary from './colors.module.css';
  composes: rounded from './shapes.module.css';
}
```

### Usage in React

```tsx
// Composed class automatically includes all composed classes
<button className={styles.primaryButton}>
  {/* Renders: Button_primaryButton_x Button_button_y colors_primary_z shapes_rounded_w */}
</button>
```

---

## Vite Configuration

### Lightning CSS (Recommended)

Lightning CSS is 100x faster than PostCSS for transforms:

```bash
npm install lightningcss browserslist
```

```typescript
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import browserslistToTargets from 'lightningcss/browserslist'
import browserslist from 'browserslist'

export default defineConfig({
  plugins: [react()],
  css: {
    transformer: 'lightningcss',
    lightningcss: {
      targets: browserslistToTargets(browserslist('>= 0.25%')),
      cssModules: {
        // Class name pattern
        pattern: '[name]__[local]_[hash:5]',
        // Or for production:
        // pattern: '[hash:8]'
      }
    }
  },
  build: {
    cssMinify: 'lightningcss'
  }
})
```

### Class Name Patterns

| Pattern | Example Output |
|---------|----------------|
| `[name]__[local]_[hash:5]` | `Button__primary_a3k2j` |
| `[local]_[hash:8]` | `primary_a3k2j9x1` |
| `[hash:8]` | `a3k2j9x1` (production) |

### Lightning CSS Features (Included)

Lightning CSS automatically handles:
- Vendor prefixing (replaces autoprefixer)
- Modern syntax transpilation
- Nesting
- Custom media queries
- Color functions (oklch, lab, lch)

### PostCSS Configuration (When Needed)

For plugins Lightning CSS doesn't support:

```javascript
// postcss.config.js
export default {
  plugins: {
    'postcss-import': {},
    'postcss-custom-media': {},
    // Don't use: autoprefixer (Lightning CSS handles this)
    // Don't use: postcss-nested (Lightning CSS handles this)
  }
}
```

**Note**: Use Lightning CSS for transforms, PostCSS only for unsupported plugins.

---

## TypeScript Integration

### Type Declarations

Without types, TypeScript doesn't know the shape of CSS modules:

```typescript
// This would error without declarations
import styles from './Button.module.css'
styles.button  // TS error: Property 'button' does not exist
```

### Option 1: Wildcard Declaration (Simple)

```typescript
// src/vite-env.d.ts or src/types/css-modules.d.ts
declare module '*.module.css' {
  const classes: { [key: string]: string }
  export default classes
}
```

**Pros**: No extra tooling
**Cons**: No autocomplete, no type safety

### Option 2: Generated Declarations (Recommended)

```bash
npm install -D vite-plugin-css-modules-dts
```

```typescript
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import cssModulesDts from 'vite-plugin-css-modules-dts'

export default defineConfig({
  plugins: [
    react(),
    cssModulesDts({
      // Generate .d.ts next to .module.css files
      outputDir: '.',
    })
  ]
})
```

Generated files:

```typescript
// Button.module.css.d.ts (auto-generated)
declare const styles: {
  readonly button: string
  readonly primary: string
  readonly secondary: string
}
export default styles
```

**Pros**: Full autocomplete, type safety, catches typos
**Cons**: Generated files in source (add to .gitignore)

### Option 3: CLI Generation

```bash
npm install -D typed-css-modules

# Generate declarations
npx tcm src --pattern '**/*.module.css'

# Watch mode
npx tcm src --pattern '**/*.module.css' --watch
```

Add to `package.json`:

```json
{
  "scripts": {
    "css:types": "tcm src --pattern '**/*.module.css'",
    "css:types:watch": "tcm src --pattern '**/*.module.css' --watch"
  }
}
``

Related in Design