Skip to content

Releases: parcel-bundler/lightningcss

v1.18.0

04 Jan 16:58
Compare
Choose a tag to compare

This release adds support for custom transform visitors written in JavaScript, which lets you extend Lightning CSS with support for custom CSS syntax extensions, perform build time transforms, and more. It also adds support for nested @container and @layer rules, implements vendor prefixing for @supports, adds support for compiling from stdin via the CLI, and reduces compile times for the Rust crate by adding feature flags.

Custom transforms

The Lightning CSS visitor API enables you to implement custom non-standard extensions to CSS, making your code easier to author while shipping standard CSS to the browser. You can implement extensions such as custom shorthand properties or additional at-rules (e.g. mixins), build time transforms (e.g. convert units, inline constants, etc.), CSS rule analysis, and much more.

The API is designed to call into JavaScript as little as possible. You provide functions for specific types of values you're interested in such as Length, Url, or specific properties or rules. Lightning CSS fully parses all CSS rules and properties (with individual type definitions!), and only calls your plugin when it visits a value type you need to transform. This granularity improves performance, and also makes it much easier to build plugins since you don't need to worry about parsing values or selectors yourself. You can return a new value from a visitor function, or even remove or replace a value with multiple values in some cases. Check out the docs for more details!

Custom transforms have a build time cost: it can be around 2x slower to compile with a JS visitor than without. That being said, it is around 6x faster than equivalent postcss plugins in my testing. While standard CSS features should continue to be implemented in Rust as part of Lightning CSS core, the plugin API can help you migrate from other tools while supporting non-standard syntax extensions you might use. We look forward to hearing your feedback!

Playground updates

The Lightning CSS playground has also been updated to support visitors, which makes it easy to play around right in your browser. It also has a new editor experience powered by Code Mirror including syntax highlighting and inline errors. Check out an example with a custom visitor to see what it can do.

New docs

The Lightning CSS website has also been updated to include documentation for all of the features, including transpilation, CSS modules, bundling, and minification.

Features

  • JavaScript visitor API for custom transforms – #363
  • Add visitor support to WASM build via napi-wasm – #373
  • Parse @container and @layer block rules nested within style rules – 615893c
  • Add projectRoot option and use relative paths for CSS module hashes – 33febb4
  • Implement vendor prefixing for @supports787f46f
  • CLI support for piping – #380
  • Introduce "bundler" feature flag – #358
  • Put all of serde behind feature flag – #360
  • Introduce "visitor" feature flag – #367
  • Add sourcemap feature – #372
  • Remove derive-move – #377

Fixes

  • Fix important declarations within nested at rules – 6a7d19e
  • Remove parentheses from supports condition AST – 87ca705

v1.17.1

30 Nov 17:15
Compare
Choose a tag to compare

Fixed a regression where zero lengths were serialized without a unit in custom properties, which could break calc() usages. 0afccf9

v1.17.0

29 Nov 17:17
Compare
Choose a tag to compare

This release includes support for the new nesting syntax, a new Rust visitor API to make building custom transforms easier, support for page margin at rules, and several other improvements and fixes.

New nesting syntax

The CSS nesting support has been updated to relax some of the rules around where the & selector is required, following the latest spec changes. The & selector is now automatically inserted with a descendant combinator when not already present, unless it starts with an element selector. The @nest rule is deprecated, and will print a warning.

.foo {
  color: red;

  .bar {
    color: blue;
  }
}

compiles to:

.foo {
  color: red;
}

.foo .bar {
  color: blue;
}

Playground

Visitor API

The Rust API now includes a Visitor API, allowing you to much more easily traverse the style sheet and implement custom transforms. You can visit rules, properties, and many common value types such as lengths, urls, custom functions, etc.

For example, this visitor converts all pixel values to rems.

struct MyVisitor;
impl<'i> Visitor<'i> for MyVisitor {
  const TYPES: VisitTypes = visit_types!(LENGTHS);

  fn visit_length(&mut self, length: &mut LengthValue) {
    match length {
      LengthValue::Px(px) => *length = LengthValue::Rem(*px / 16.0),
      _ => {}
    }
  }
}

stylesheet.visit(&mut MyVisitor);

You must declare what types of values you want to visit with bitflags via the visit_types macro. This enables us to completely skip visiting entire branches of the AST when they don't contain any relevant values, statically, at compile time, which improves performance. For example, if you declare you only want to visit urls, we don't need to visit any properties that don't contain URLs somewhere in their type (recursively). Check out the documentation for more details.

You can also implement support for parsing custom at rules (e.g. Tailwind's @apply), by providing a custom AtRuleParser implementation. The parsed rules are stored in the stylesheet using a generic parameter. See the example for more details.

Other fixes and improvements

  • Support for margin at rules within @page80a982a
  • Simplify :is() selector when only a single simple selector is provided as an argument – b870d1f
  • Fix ARM linux GLIBC requirement – 5098cae
  • Fix parenthesization of media queries – 5a12639
  • Bump napi-rs – 9f2e369
  • Expose and add docs for selector module – e31234f

v1.16.1

06 Nov 17:48
Compare
Choose a tag to compare

Bug fixes

  • Parse :nth-col() and :nth-last-col() selectors – @yisibl in #302
  • Use :is for non-leading nesting with multiple compound selectors – 8652701
  • Fix flipped border-bottom-right and border-bottom-left in shorthands – @LeoniePhiline in #308
  • Fix auto prefixing for browser versions greater than the latest – @mischnic in #326

CLI features

v1.16.0

20 Sep 03:19
Compare
Choose a tag to compare

This release adds support for the new relative color syntax, improves support for quoted CSS animation names, and fixes some bugs.

Relative color syntax

Lightning CSS now supports the new relative color syntax in the CSS Color Level 5 spec! This allows you to use math functions like calc() to manipulate the channel values of a source color, and to convert between color spaces. This is not yet shipping in any browsers, but Lightning CSS will do this manipulation at build time when possible, so that it works in any browser today!

Here's a simple example, which uses the lch color space to darken slateblue by 10%. This is done by using the l channel value in a calc() expression, and preserving the c and h channels as is.

.foo {
  color: lch(from slateblue calc(l - 10%) c h);
}

This will output:

.foo {
  color: lch(34.5711% 65.7776 296.794);
}

And, when lch colors are not supported by your browser targets, Lightning CSS already supports outputting fallbacks for older browsers:

.foo {
  color: #4e42b1;
  color: lch(34.5711% 65.7776 296.794);
}

Check it out in the playground!

Note that due to being a build time transform, CSS variables are not supported as source colors since the variable value may change at runtime. We'll have to wait for browser support for that.

Other fixes and improvements

  • Support for parsing the border-spacing property – @yisibl in #294
  • Avoid converting animation: "none" to animation: "none" none@yisibl in #295
  • If the browser doesn't support #rrggbbaa color syntax, output transparent instead of rgba(0, 0, 0, 0)@yisibl in #296
  • Support parsing angles with unitless zero in gradients and transforms – cbd392f
  • Bump parcel_sourcemap dependency to fix parsing source maps without sourcesContent, and improve base64 performance – 061c0c2

v1.15.1

16 Sep 03:42
Compare
Choose a tag to compare

v1.15.0

15 Sep 05:21
Compare
Choose a tag to compare

This release includes several new features and a bunch of bug fixes.

New features

  • Use inline source maps during bundling – bfa8b8c
  • Add new preserveImports option for analyzeDependencies, which preserves the @import rules with placeholder URLs similar to url() dependencies – 676bf1f
  • Add filename option for transformStyleAttribute, used for error messages and dependency locations – 815a183
  • Add version flag to cli – @lucasweng in 3c9db12

Bug fixes

  • Fix types for bundleAsync – adabfc1
  • Fix CLI package – a82381f
  • Fix bundling of @import rules with both layer and import conditions – f66c6d7
  • Fix printing flex shorthand – 84298d2
  • Parenthesize custom media conditions with not – 7c58283
  • Fix handling of strings in animation-name property – 7efeef2

v1.14.0

08 Sep 15:18
b6c24f4
Compare
Choose a tag to compare

We are excited to announce that Parcel CSS is now called Lightning CSS! ⚡ This new name makes it clear that the project can be used outside of Parcel, with other build tools, or even standalone.

We also have a brand new website showcasing some of the features, along with the WASM-based playground at lightningcss.dev. This will expand over time to include more documentation and examples.

Going forward, new releases will be under the lightningcss npm package and Rust crate. The @parcel/css package still exists on npm for backward compatibility, but now re-exports lightningcss. The parcel_css Rust crate is deprecated - please use lightningcss going forward.

New features

This release also includes several new features, including major improvements to the bundler.

Custom JS resolver

The node bindings now include a new bundleAsync function in addition to the existing bundle function. bundleAsync runs the bundler asynchronously in a background thread, and returns a promise that lets you know when it has completed. In addition, bundleAsync supports custom JavaScript-based resolvers, which allow you to customize the resolution behavior for @import specifiers, and provide the contents of files from a source other than the file system.

let {code, map} = await css.bundleAsync({
  filename: 'style.css',
  minify: true,
  resolver: {
    read(filePath) {
      return fs.readFileSync(filePath, 'utf8');
    },
    resolve(specifier, from) {
      return path.resolve(path.dirname(from), specifier);
    }
  }
});

Note that providing a resolver can negatively affect performance, so only do so when you need to customize things.

CSS modules bundling

Dependencies in CSS modules are now also bundled. For example, the composes property allows you to reference another file. These will now be bundled, and the resolved class name will be included in the output JSON as well.

Bug fixes

  • add types for wasm init default export – @deckchairlabs in #269
  • match the spec so that feature-* in @font-face tech() becomes plural – @yisibl in #270
  • CSS-wide keywords and none in @keyframes cannot remove quotes – @yisibl in #267

v1.13.1

02 Sep 15:30
Compare
Choose a tag to compare

Fixes

  • Playground: Fix wrong text color in output panel – @marvinhagemeister in #259
  • Add missing semicolon in Custom Media Queries – @Marabyte in #260
  • Do not omit 1x resolution in image-set()@yisibl in #264
  • Suppress unsupported pseudo class or element warning if vendor prefixed – @pfroud in #266

v1.13.0

22 Aug 01:43
Compare
Choose a tag to compare

This release includes a few new features and bug fixes.

Parcel CSS will now try to preserve unknown @ rules and selectors rather than erroring (a warning will be emitted instead). These rules are not fully parsed and therefore may not be minified as much as possible. This is useful in cases where Parcel CSS has not yet implemented a feature that browsers are experimenting with.

We now also have experimental bindings to use Parcel CSS via C, which will enable it to be used from many languages other than Rust and JavaScript. See here for an example. For now, this will need to be compiled from source. More features will be added in future updates as the need arises (please open a feature request).

Features

Bug fixes