Skip to main content
Technology & EngineeringCss Styling Services308 lines

Lightning CSS

"Lightning CSS: ultra-fast CSS transformer, bundler, and minifier written in Rust, with modern syntax lowering, vendor prefixing, and CSS modules"

Quick Summary23 lines
You are an expert in using Lightning CSS, the extremely fast CSS parser, transformer, bundler, and minifier built in Rust.

## Key Points

- Use Lightning CSS as both your transformer and minifier to eliminate redundant tools in your build pipeline — it replaces Autoprefixer, postcss-preset-env, and cssnano in a single pass.
- Enable the `drafts` options selectively (e.g., `customMedia`) rather than relying on unstable features without explicit opt-in, since draft specs may change.
- Lightning CSS does not process Sass, Less, or other preprocessor syntax. It works only with standard CSS (including modern spec features). Run your preprocessor first if needed.

## Quick Example

```bash
npm install --save-dev lightningcss lightningcss-cli
```

```bash
# Bundle and minify
npx lightningcss --bundle --minify --targets '>= 0.25%' input.css -o output.css

# With CSS Modules
npx lightningcss --bundle --css-modules input.css -o output.css
```
skilldb get css-styling-services-skills/Lightning CSSFull skill: 308 lines
Paste into your CLAUDE.md or agent config

Lightning CSS — CSS & Styling

You are an expert in using Lightning CSS, the extremely fast CSS parser, transformer, bundler, and minifier built in Rust.

Core Philosophy

Overview

Lightning CSS (formerly Parcel CSS) is a Rust-based CSS tool that handles parsing, transforming, bundling, and minifying CSS with exceptional speed. It automatically handles vendor prefixing, syntax lowering for older browsers, and CSS Modules — replacing the need for separate tools like Autoprefixer, postcss-preset-env, and cssnano. It supports modern CSS features like nesting, custom media queries, color functions, and cascade layers, and can lower them to syntax compatible with your target browsers.

Setup & Configuration

Installation

npm install --save-dev lightningcss lightningcss-cli

CLI Usage

# Bundle and minify
npx lightningcss --bundle --minify --targets '>= 0.25%' input.css -o output.css

# With CSS Modules
npx lightningcss --bundle --css-modules input.css -o output.css

Node.js API

import { bundle, transform, browserslistToTargets } from 'lightningcss'
import browserslist from 'browserslist'

// Transform a CSS string
const { code, map } = transform({
  filename: 'style.css',
  code: Buffer.from(`
    .foo {
      color: oklch(0.7 0.15 200);
      & .bar {
        font-size: 1rem;
      }
    }
  `),
  minify: true,
  sourceMap: true,
  targets: browserslistToTargets(browserslist('>= 0.25%')),
})

console.log(code.toString())

Bundle Multiple Files

import { bundle, browserslistToTargets } from 'lightningcss'
import browserslist from 'browserslist'

const { code, map } = bundle({
  filename: 'src/styles/main.css',
  minify: true,
  sourceMap: true,
  targets: browserslistToTargets(browserslist('>= 0.25%')),
  drafts: {
    customMedia: true, // enable @custom-media support
  },
})

Vite Integration

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

export default defineConfig({
  css: {
    transformer: 'lightningcss',
    lightningcss: {
      targets: browserslistToTargets(browserslist('>= 0.25%')),
      drafts: {
        customMedia: true,
      },
    },
  },
  build: {
    cssMinify: 'lightningcss',
  },
})

PostCSS Plugin Alternative

// postcss.config.js
const postcssLightningcss = require('postcss-lightningcss')

module.exports = {
  plugins: [
    postcssLightningcss({
      browsers: '>= 0.25%',
      lightningcssOptions: {
        minify: true,
        drafts: { customMedia: true },
      },
    }),
  ],
}

Core Patterns

Automatic Syntax Lowering

Write modern CSS and let Lightning CSS convert it for target browsers:

/* Input: modern CSS */
.card {
  color: oklch(0.7 0.15 200);
  background: color-mix(in srgb, #3b82f6 70%, transparent);
  border-radius: 8px;
  display: flex;
  gap: 16px;

  /* Native nesting */
  & .title {
    font-size: 1.25rem;
    font-weight: 600;
  }

  &:hover {
    background: oklch(0.75 0.15 200);
  }
}

/* Output: lowered for older browsers automatically */

Custom Media Queries

@custom-media --mobile (max-width: 767px);
@custom-media --tablet (min-width: 768px) and (max-width: 1023px);
@custom-media --desktop (min-width: 1024px);

.grid {
  display: grid;
  grid-template-columns: 1fr;

  @media (--tablet) {
    grid-template-columns: repeat(2, 1fr);
  }

  @media (--desktop) {
    grid-template-columns: repeat(3, 1fr);
  }
}

CSS Modules

/* components/Button.module.css */
.root {
  composes: base from './shared.module.css';
  background: #3b82f6;
  color: white;
  padding: 8px 16px;
  border-radius: 6px;
  border: none;
  cursor: pointer;
}

.root:hover {
  background: #2563eb;
}

.icon {
  margin-right: 8px;
  display: inline-flex;
}
// Node API with CSS Modules
import { bundle } from 'lightningcss'

const { code, exports } = bundle({
  filename: 'components/Button.module.css',
  cssModules: true,
  minify: true,
})

// exports contains the class name mapping:
// { root: { name: 'Button_root_a1b2c3', composes: [...] }, icon: { name: 'Button_icon_d4e5f6' } }

Cascade Layers

/* Define layer order */
@layer reset, base, components, utilities;

@layer reset {
  *, *::before, *::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
}

@layer base {
  body {
    font-family: system-ui, sans-serif;
    line-height: 1.6;
    color: #1a202c;
  }
}

@layer components {
  .card {
    padding: 16px;
    border-radius: 12px;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  }
}

@layer utilities {
  .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
  }
}

Vendor Prefixing

Lightning CSS automatically adds vendor prefixes based on your browser targets — no separate Autoprefixer needed:

/* Input */
.box {
  user-select: none;
  backdrop-filter: blur(10px);
  appearance: none;
}

/* Output (when targeting older browsers) */
.box {
  -webkit-user-select: none;
  -ms-user-select: none;
  user-select: none;
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
}

Modern Color Functions

.theme {
  --brand: oklch(0.6 0.2 260);
  --brand-light: oklch(0.8 0.15 260);
  --brand-dark: oklch(0.4 0.2 260);

  /* color-mix for transparency */
  --brand-translucent: color-mix(in oklch, var(--brand) 50%, transparent);

  /* lab / lch colors */
  --accent: lab(60% 40 -20);
}

Best Practices

  • Set browser targets using browserslistToTargets(browserslist(...)) from a shared browserslist config (e.g., .browserslistrc) so that all tools in your pipeline agree on which browsers to support.
  • Use Lightning CSS as both your transformer and minifier to eliminate redundant tools in your build pipeline — it replaces Autoprefixer, postcss-preset-env, and cssnano in a single pass.
  • Enable the drafts options selectively (e.g., customMedia) rather than relying on unstable features without explicit opt-in, since draft specs may change.

Common Pitfalls

  • Lightning CSS does not process Sass, Less, or other preprocessor syntax. It works only with standard CSS (including modern spec features). Run your preprocessor first if needed.
  • When using Vite integration, setting css.transformer: 'lightningcss' disables PostCSS entirely. Any PostCSS plugins you were using (e.g., Tailwind CSS) will stop working. Choose one pipeline or the other.

Anti-Patterns

Using the service without understanding its pricing model. Cloud services bill differently — per request, per GB, per seat. Deploying without modeling expected costs leads to surprise invoices.

Hardcoding configuration instead of using environment variables. API keys, endpoints, and feature flags change between environments. Hardcoded values break deployments and leak secrets.

Ignoring the service's rate limits and quotas. Every external API has throughput limits. Failing to implement backoff, queuing, or caching results in dropped requests under load.

Treating the service as always available. External services go down. Without circuit breakers, fallbacks, or graceful degradation, a third-party outage becomes your outage.

Coupling your architecture to a single provider's API. Building directly against provider-specific interfaces makes migration painful. Wrap external services in thin adapter layers.

Install this skill directly: skilldb add css-styling-services-skills

Get CLI access →