Skip to main content
Bun’s bundler has built-in support for CSS with the following features:
  • Transpiling modern/future features to work on all browsers (including vendor prefixing)
  • Minification
  • CSS Modules
  • Tailwind (through a native bundler plugin)

Transpiling

Transpiling and vendor prefixing are enabled by default, so you can use modern and future CSS features without worrying about browser compatibility. Bun’s CSS parser and bundler is a direct port of LightningCSS, with a bundling approach inspired by esbuild. The transpiler converts modern CSS syntax into backwards-compatible equivalents that work across browsers.
Thanks to the authors of LightningCSS and esbuild for their work.

Browser Compatibility

By default, Bun’s CSS bundler targets the following browsers:
  • ES2020
  • Edge 88+
  • Firefox 78+
  • Chrome 87+
  • Safari 14+

Syntax Lowering

Nesting

With CSS Nesting, you write child styles directly inside their parent blocks instead of repeating parent selectors across your CSS file.
styles.css
Bun’s CSS bundler automatically converts this nested syntax into traditional flat CSS that works in all browsers:
styles.css
You can also nest media queries and other at-rules inside selectors:
styles.css
This compiles to:
styles.css

Color mix

The color-mix() function blends two colors at a given ratio in a chosen color space. Use it to create color variations without calculating the resulting values yourself.
styles.css
Bun’s CSS bundler evaluates these color mixes at build time when all color values are known (not CSS variables), generating static color values that work in all browsers:
styles.css

Relative colors

Relative color syntax modifies individual components of an existing color. Adjust attributes like lightness, saturation, or individual channels without recalculating the entire color.
styles.css
Bun’s CSS bundler computes these relative color modifications at build time (when not using CSS variables) and generates static color values for browser compatibility:
Use it for theme generation, accessible color variants, or color scales derived from a base color instead of hard-coding each value.

LAB colors

Modern CSS supports the perceptually uniform color spaces LAB, LCH, OKLAB, and OKLCH, which can represent colors outside the standard RGB gamut.
styles.css
Bun’s CSS bundler converts these color formats to backwards-compatible alternatives for browsers that don’t support them:
styles.css

Color function

The color() function specifies colors in predefined color spaces beyond traditional RGB, giving you access to wider color gamuts.
styles.css
For browsers that don’t support these color spaces, Bun’s CSS bundler adds RGB fallbacks:
styles.css

HWB colors

The HWB (Hue, Whiteness, Blackness) color model expresses colors based on how much white or black is mixed with a pure hue. This makes tints and shades more direct to create than with RGB or HSL values.
styles.css
Bun’s CSS bundler converts HWB colors to RGB for compatibility with all browsers:
styles.css

Color notation

Modern CSS supports space-separated RGB and HSL values (no commas) and hex colors with an alpha channel.
styles.css
Bun’s CSS bundler converts these formats for older browsers:
styles.css

light-dark() color function

The light-dark() function takes two colors and applies one based on the current color scheme, so styles respect the user’s system preference without media queries.
styles.css
For browsers that don’t support light-dark(), Bun’s CSS bundler converts it to CSS variables with fallbacks:
styles.css

Logical properties

CSS logical properties define layout, spacing, and sizing relative to the document’s writing mode and text direction rather than physical screen directions, so layouts adapt to different writing systems.
styles.css
For browsers that don’t fully support logical properties, Bun’s CSS bundler compiles them to physical properties for each text direction:
styles.css
If the :dir() selector isn’t supported, Bun generates additional fallbacks.

:dir() selector

The :dir() pseudo-class styles elements based on their text direction (RTL or LTR), as determined by the document or explicit direction attributes. Use it to write direction-aware styles without JavaScript.
styles.css
For browsers that don’t support the :dir() selector, Bun’s CSS bundler converts it to the more widely supported :lang() selector with appropriate language mappings:
styles.css
If multiple arguments to :lang() aren’t supported, Bun generates further fallbacks.

:lang() selector

The :lang() pseudo-class targets elements based on their language. To group rules for related languages, pass multiple language codes to a single :lang().
styles.css
For browsers that don’t support multiple arguments in the :lang() selector, Bun’s CSS bundler converts this syntax to the :is() selector with the same behavior:
styles.css
If needed, Bun can generate additional fallbacks for :is() as well.

:is() selector

The :is() pseudo-class function (formerly :matches()) takes a selector list and matches if any selector in the list matches.
styles.css
For browsers that don’t support :is(), Bun’s CSS bundler provides fallbacks using vendor-prefixed alternatives:
The vendor-prefixed versions have limitations compared to the standardized :is() selector, particularly with complex selectors. Bun only uses the prefixed versions when they work correctly.

:not() selector

The :not() pseudo-class excludes elements that match a selector. The modern version accepts multiple arguments to exclude several patterns with one :not().
styles.css
For browsers that don’t support multiple arguments in :not(), Bun’s CSS bundler converts this syntax to a more compatible form with the same behavior:
styles.css
And if :is() isn’t supported, Bun can generate further fallbacks:
styles.css
The converted selectors keep the specificity and behavior of the original.

Math functions

CSS includes standard math functions (round(), mod(), rem(), abs(), sign()), trigonometric functions (sin(), cos(), tan(), asin(), acos(), atan(), atan2()), and exponential functions (pow(), sqrt(), exp(), log(), hypot()).
styles.css
Bun’s CSS bundler evaluates these expressions at build time when all values are known constants (not variables):
styles.css

Media query ranges

Media query range syntax expresses breakpoints with comparison operators (<, >, <=, >=) instead of the more verbose min- and max- prefixes.
styles.css
Bun’s CSS bundler converts range queries to traditional media query syntax for compatibility with all browsers:
styles.css

Shorthands

CSS has introduced several shorthand properties that combine multiple longhand properties.
styles.css
For browsers that don’t support these shorthands, Bun converts them to their component longhand properties:
styles.css

Double position gradients

Double position gradient syntax specifies the same color at two adjacent positions to create a hard color stop: a sharp transition instead of a smooth fade. Use it for stripes, color bands, and other multi-color designs.
styles.css
For browsers that don’t support this syntax, Bun’s CSS bundler converts it to the traditional format by duplicating color stops:
styles.css

system-ui font

The system-ui generic font family uses the device’s native UI font.
styles.css
For browsers that don’t support system-ui, Bun’s CSS bundler expands it to a cross-platform font stack:
styles.css
The expanded stack includes system fonts for macOS/iOS, Windows, Android, and Linux, plus fallbacks for older browsers.

CSS Modules

Bun’s bundler also supports CSS modules, with the following features:
  • Detecting CSS module files (.module.css) with no configuration
  • Composition (composes property)
  • Importing CSS modules into JSX/TSX
  • Warnings/errors for invalid usages of CSS modules
A CSS module is a CSS file (with the .module.css extension) where all class names and animations are scoped to the file. This helps you avoid class name collisions, as CSS declarations are globally scoped by default. Bun’s bundler transforms locally scoped class names into unique identifiers.

Getting started

Create a CSS file with the .module.css extension:
styles.module.css
other-styles.module.css
You can then import this file, for example into a TSX file:
app.tsx
Importing a CSS module gives you an object that maps each class name to its unique identifier:
app.tsx
This outputs:
app.tsx
The class names are unique to each file, so they don’t collide.

Composition

CSS modules can compose class selectors together to reuse style rules across multiple classes. For example:
styles.module.css
This is the same as writing:
styles.module.css
Two rules apply when using composes:
Composition Rules: - A composes property must come before any regular CSS properties or declarations - You can only use composes on a simple selector with a single class name
styles.module.css

Composing from a separate CSS module file

You can also compose from a separate CSS module file:
background.module.css
styles.module.css
When composing classes from separate files, make sure they do not contain the same properties.The CSS module spec says that composing classes from separate files with conflicting properties is undefined behavior: the output may differ and be unreliable.