Releases: parcel-bundler/lightningcss
v1.18.0
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 @supports – 787f46f
- 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
v1.17.1
v1.17.0
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;
}
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
@page
– 80a982a - 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
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
andborder-bottom-left
in shorthands – @LeoniePhiline in #308 - Fix auto prefixing for browser versions greater than the latest – @mischnic in #326
CLI features
- Add
--browserslist
option to load browsers list config by @LeoniePhiline in #324
v1.16.0
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"
toanimation: "none" none
– @yisibl in #295 - If the browser doesn't support
#rrggbbaa
color syntax, outputtransparent
instead ofrgba(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
v1.15.0
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 foranalyzeDependencies
, which preserves the@import
rules with placeholder URLs similar tourl()
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
v1.14.0
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
v1.13.1
v1.13.0
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
- Preserve unknown at rules as raw tokens
- Store unsupported functional pseudo classes and elements as raw tokens
- Experimental C bindings
- Support parsing tech() function in
@font-face
- Parse and prefix box-decoration-break property