CSS bundler transpiling enabled by default
Bun's CSS bundler has transpiling and vendor prefixing enabled by default. The CSS parser and bundler is a direct port of LightningCSS with a bundling approach inspired by esbuild. It converts modern CSS syntax into backwards-compatible equivalents that work across browsers.
Default browser compatibility targets
Bun's CSS bundler targets the following browsers by default: ES2020, Edge 88+, Firefox 78+, Chrome 87+, and Safari 14+.
CSS nesting syntax transpilation
Bun's CSS bundler automatically converts nested CSS syntax (child styles directly inside parent blocks) into traditional flat CSS. For example, nested selectors like `.card .title` are flattened. Nested media queries and at-rules inside selectors are also converted by moving them outside and reapplying the parent selector.
Color-mix() function evaluation
Bun's CSS bundler evaluates color-mix() functions at build time when all color values are known (not CSS variables), generating static color values that work in all browsers. The color-mix() function blends two colors at a given ratio in a chosen color space.
Relative colors transpilation
Bun's CSS bundler computes relative color modifications at build time when not using CSS variables, generating static color values for browser compatibility. Relative color syntax modifies individual components of an existing color using functions like `lch(from purple calc(l + 15%) c h)`.
LAB color format transpilation
Bun's CSS bundler converts LAB, LCH, OKLAB, and OKLCH color formats to backwards-compatible alternatives. It generates RGB fallbacks (closest approximation), P3 fallbacks for browsers with wider gamut support, and preserves the original value for browsers that support it.
Color function with display spaces
Bun's CSS bundler adds RGB fallbacks for the color() function when specifying colors in predefined color spaces like display-p3 or a98-rgb. It outputs the RGB fallback first for maximum compatibility, then keeps the original for browsers that support the color space.
HWB color model transpilation
Bun's CSS bundler converts HWB (Hue, Whiteness, Blackness) colors to RGB for compatibility with all browsers. HWB expresses colors based on how much white or black is mixed with a pure hue.
Modern color notation transpilation
Bun's CSS bundler converts modern CSS color notation (space-separated RGB/HSL with no commas, hex colors with alpha channel) to formats compatible with older browsers. Space-separated RGB notation like `rgb(50 100 200)` is converted to comma format. Hex with alpha like `#00aaff80` is converted to rgba when needed.
light-dark() function transpilation
For browsers that don't support light-dark(), Bun's CSS bundler converts it to CSS variables with fallbacks. It generates --buncss-light and --buncss-dark variables and uses @media (prefers-color-scheme: dark) to toggle them based on system preference.
Logical properties transpilation
Bun's CSS bundler compiles logical properties (margin-inline-start, padding-block, border-start-start-radius, inline-size, block-size) to physical properties for each text direction. For browsers that don't support :dir(), it generates additional fallbacks using :dir(ltr) and :dir(rtl) selectors.
:dir() selector transpilation
For browsers that don't support the :dir() selector, Bun's CSS bundler converts it to the :lang() selector with appropriate language mappings. LTR languages include en, fr, de, es, it, pt, nl. RTL languages include ar, he, fa, ur. If multiple arguments to :lang() aren't supported, Bun generates further fallbacks.
:lang() selector with multiple arguments
The :lang() pseudo-class can group multiple language codes in a single selector, for example `:lang(zh, ja, ko)`. For browsers that don't support multiple arguments, Bun's CSS bundler converts this to :is() selector form: `:is(:lang(zh), :lang(ja), :lang(ko))`.
:is() selector transpilation and vendor prefixes
For browsers that don't support :is(), Bun's CSS bundler provides fallbacks using vendor-prefixed alternatives: -webkit-any() and -moz-any(). It outputs the vendor-prefixed versions first, then the original :is() for modern browsers. The vendor-prefixed versions have limitations with complex selectors, and Bun only uses them when they work correctly.
:not() selector enhancement transpilation
For browsers that don't support multiple arguments in :not(), Bun's CSS bundler converts `:not(.primary, .secondary)` to `:not(:is(.primary, .secondary))`. If :is() isn't supported, it generates vendor-prefixed fallbacks like `:not(:-webkit-any(.primary, .secondary))` and `:not(:-moz-any(.primary, .secondary))`.
Math functions evaluation in CSS
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). Bun's CSS bundler evaluates these expressions at build time when all values are known constants (not variables).
Media query range syntax transpilation
Bun's CSS bundler converts modern media query range syntax using comparison operators to traditional media query syntax. For example, `@media (width >= 768px)` becomes `@media (min-width: 768px)`. Ranges like `@media (768px <= width <= 1199px)` become `@media (min-width: 768px) and (max-width: 1199px)`.
CSS shorthand expansion
Bun's CSS bundler converts shorthand properties to their longhand equivalents for older browsers. Examples: place-items expands to align-items and justify-items; place-content expands to align-content and justify-content; place-self expands to align-self and justify-self; two-value overflow splits into overflow-x and overflow-y; text-decoration shorthand splits into text-decoration-line, text-decoration-style, text-decoration-color, text-decoration-thickness; display: inline flex becomes display: inline-flex.
Double position gradients transpilation
For browsers that don't support double position gradient syntax (e.g., `green 30%, red 30%`), Bun's CSS bundler converts it to the traditional format by duplicating color stops. Double position syntax creates hard color stops (sharp transitions) instead of smooth fades. The modern syntax `#4caf50 0% 25%` is converted to two stops: `#4caf50 0%, #4caf50 25%`.
system-ui font family expansion
For browsers that don't support system-ui, Bun's CSS bundler expands it to a cross-platform font stack: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Noto Sans', Ubuntu, Cantarell, 'Helvetica Neue'. This includes system fonts for macOS/iOS, Windows, Android, and Linux, plus fallbacks for older browsers.
CSS Modules detection
Bun's bundler detects CSS module files automatically by the `.module.css` extension with no configuration required. CSS modules scope all class names and animations to the file, helping avoid class name collisions since CSS declarations are globally scoped by default.
CSS Modules import behavior
Importing a CSS module gives an object that maps each class name to its unique identifier. For example, importing styles from 'styles.module.css' with a `.button` class returns `{ button: 'button_123' }`. Each file gets unique identifiers, so class names don't collide across modules.
CSS Modules composition rules
Two rules apply when using the `composes` property in CSS modules: (1) A `composes` property must come before any regular CSS properties or declarations, and (2) You can only use `composes` on a simple selector with a single class name. Invalid examples: `#button { composes: background; }` (not a class selector) and `.button, .button-secondary { composes: background; }` (not a simple selector).
CSS Modules composition from separate files
CSS modules can compose from separate CSS module files using the syntax: `.button { composes: background from './background.module.css'; color: red; }`. When composing classes from separate files, ensure they do not contain the same properties, as the CSS module spec says composing with conflicting properties is undefined behavior and the output may differ and be unreliable.
CSS Modules composition behavior
CSS modules composition reuses style rules across multiple classes. Using `composes: background;` where `.background { background-color: blue; }` is defined has the same effect as writing the property directly in the composing class. The composed styles are applied in addition to the composing class's own properties.