Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

csso

css67mMIT5.0.5TypeScript support: definitely-typed

CSS minifier with structural optimisations

css, compress, minifier, minify, optimise, optimisation, csstree

readme

NPM version Build Status Coverage Status NPM Downloads Twitter

CSSO (CSS Optimizer) is a CSS minifier. It performs three sort of transformations: cleaning (removing redundants), compression (replacement for the shorter forms) and restructuring (merge of declarations, rules and so on). As a result an output CSS becomes much smaller in size.

Install

npm install csso

Usage

import { minify } from 'csso';
// CommonJS is also supported
// const { minify } = require('csso');

const minifiedCss = minify('.test { color: #ff0000; }').css;

console.log(minifiedCss);
// .test{color:red}

Bundles are also available for use in a browser:

  • dist/csso.js – minified IIFE with csso as global

    <script src="node_modules/csso/dist/csso.js"></script>
    <script>
    csso.minify('.example { color: green }');
    </script>
  • dist/csso.esm.js – minified ES module

    <script type="module">
    import { minify } from 'node_modules/csso/dist/csso.esm.js'
    
    minify('.example { color: green }');
    </script>

One of CDN services like unpkg or jsDelivr can be used. By default (for short path) a ESM version is exposing. For IIFE version a full path to a bundle should be specified:

<!-- ESM -->
<script type="module">
  import * as csstree from 'https://cdn.jsdelivr.net/npm/csso';
  import * as csstree from 'https://unpkg.com/csso';
</script>

<!-- IIFE with an export to global -->
<script src="https://cdn.jsdelivr.net/npm/csso/dist/csso.js"></script>
<script src="https://unpkg.com/csso/dist/csso.js"></script>

CSSO is based on CSSTree to parse CSS into AST, AST traversal and to generate AST back to CSS. All CSSTree API is available behind syntax field extended with compress() method. You may minify CSS step by step:

import { syntax } from 'csso';

const ast = syntax.parse('.test { color: #ff0000; }');
const compressedAst = syntax.compress(ast).ast;
const minifiedCss = syntax.generate(compressedAst);

console.log(minifiedCss);
// .test{color:red}

Also syntax can be imported using csso/syntax entry point:

import { parse, compress, generate } from 'csso/syntax';

const ast = parse('.test { color: #ff0000; }');
const compressedAst = compress(ast).ast;
const minifiedCss = generate(compressedAst);

console.log(minifiedCss);
// .test{color:red}

Warning: CSSO doesn't guarantee API behind a syntax field as well as AST format. Both might be changed with changes in CSSTree. If you rely heavily on syntax API, a better option might be to use CSSTree directly.

API

minify(source[, options])

Minify source CSS passed as String.

const result = csso.minify('.test { color: #ff0000; }', {
    restructure: false,   // don't change CSS structure, i.e. don't merge declarations, rulesets etc
    debug: true           // show additional debug information:
                          // true or number from 1 to 3 (greater number - more details)
});

console.log(result.css);
// > .test{color:red}

Returns an object with properties:

Options:

  • sourceMap

    Type: Boolean
    Default: false

    Generate a source map when true.

  • filename

    Type: String
    Default: '<unknown>'

    Filename of input CSS, uses for source map generation.

  • debug

    Type: Boolean
    Default: false

    Output debug information to stderr.

  • beforeCompress

    Type: function(ast, options) or Array<function(ast, options)> or null
    Default: null

    Called right after parse is run.

  • afterCompress

    Type: function(compressResult, options) or Array<function(compressResult, options)> or null
    Default: null

    Called right after syntax.compress() is run.

  • Other options are the same as for syntax.compress() function.

minifyBlock(source[, options])

The same as minify() but for list of declarations. Usually it's a style attribute value.

const result = csso.minifyBlock('color: rgba(255, 0, 0, 1); color: #ff0000');

console.log(result.css);
// > color:red

syntax.compress(ast[, options])

Does the main task – compress an AST. This is CSSO's extension in CSSTree syntax API.

NOTE: syntax.compress() performs AST compression by transforming input AST by default (since AST cloning is expensive and needed in rare cases). Use clone option with truthy value in case you want to keep input AST untouched.

Returns an object with properties:

  • ast Object – resulting AST

Options:

  • restructure

    Type: Boolean
    Default: true

    Disable or enable a structure optimisations.

  • forceMediaMerge

    Type: Boolean
    Default: false

    Enables merging of @media rules with the same media query by splitted by other rules. The optimisation is unsafe in general, but should work fine in most cases. Use it on your own risk.

  • clone

    Type: Boolean
    Default: false

    Transform a copy of input AST if true. Useful in case of AST reuse.

  • comments

    Type: String or Boolean
    Default: true

    Specify what comments to leave:

    • 'exclamation' or true – leave all exclamation comments (i.e. /*! .. */)
    • 'first-exclamation' – remove every comment except first one
    • false – remove all comments
  • usage

    Type: Object or null
    Default: null

    Usage data for advanced optimisations (see Usage data for details)

  • logger

    Type: Function or null
    Default: null

    Function to track every step of transformation.

Source maps

To get a source map set true for sourceMap option. Additianaly filename option can be passed to specify source file. When sourceMap option is true, map field of result object will contain a SourceMapGenerator instance. This object can be mixed with another source map or translated to string.

const csso = require('csso');
const css = fs.readFileSync('path/to/my.css', 'utf8');
const result = csso.minify(css, {
  filename: 'path/to/my.css', // will be added to source map as reference to source file
  sourceMap: true             // generate source map
});

console.log(result);
// { css: '...minified...', map: SourceMapGenerator {} }

console.log(result.map.toString());
// '{ .. source map content .. }'

Example of generating source map with respect of source map from input CSS:

import { SourceMapConsumer } from 'source-map';
import * as csso from 'csso';

const inputFile = 'path/to/my.css';
const input = fs.readFileSync(inputFile, 'utf8');
const inputMap = input.match(/\/\*# sourceMappingURL=(\S+)\s*\*\/\s*$/);
const output = csso.minify(input, {
  filename: inputFile,
  sourceMap: true
});

// apply input source map to output
if (inputMap) {
  output.map.applySourceMap(
    new SourceMapConsumer(inputMap[1]),
    inputFile
  )
}

// result CSS with source map
console.log(
  output.css +
  '/*# sourceMappingURL=data:application/json;base64,' +
  Buffer.from(output.map.toString()).toString('base64') +
  ' */'
);

Usage data

CSSO can use data about how CSS is used in a markup for better compression. File with this data (JSON) can be set using usage option. Usage data may contain following sections:

  • blacklist – a set of black lists (see Black list filtering)
  • tags – white list of tags
  • ids – white list of ids
  • classes – white list of classes
  • scopes – groups of classes which never used with classes from other groups on the same element

All sections are optional. Value of tags, ids and classes should be an array of a string, value of scopes should be an array of arrays of strings. Other values are ignoring.

White list filtering

tags, ids and classes are using on clean stage to filter selectors that contain something not in the lists. Selectors are filtering only by those kind of simple selector which white list is specified. For example, if only tags list is specified then type selectors are checking, and if all type selectors in selector present in list or selector has no any type selector it isn't filter.

ids and classes are case sensitive, tags – is not.

Input CSS:

* { color: green; }
ul, ol, li { color: blue; }
UL.foo, span.bar { color: red; }

Usage data:

{
    "tags": ["ul", "LI"]
}

Resulting CSS:

*{color:green}ul,li{color:blue}ul.foo{color:red}

Filtering performs for nested selectors too. :not() pseudos content is ignoring since the result of matching is unpredictable. Example for the same usage data as above:

:nth-child(2n of ul, ol) { color: red }
:nth-child(3n + 1 of img) { color: yellow }
:not(div, ol, ul) { color: green }
:has(:matches(ul, ol), ul, ol) { color: blue }

Turns into:

:nth-child(2n of ul){color:red}:not(div,ol,ul){color:green}:has(:matches(ul),ul){color:blue}

Black list filtering

Black list filtering performs the same as white list filtering, but filters things that mentioned in the lists. blacklist can contain the lists tags, ids and classes.

Black list has a higher priority, so when something mentioned in the white list and in the black list then white list occurrence is ignoring. The :not() pseudos content ignoring as well.

* { color: green; }
ul, ol, li { color: blue; }
UL.foo, li.bar { color: red; }

Usage data:

{
    "blacklist": {
        "tags": ["ul"]
    },
    "tags": ["ul", "LI"]
}

Resulting CSS:

*{color:green}li{color:blue}li.bar{color:red}

Scopes

Scopes is designed for CSS scope isolation solutions such as css-modules. Scopes are similar to namespaces and define lists of class names that exclusively used on some markup. This information allows the optimizer to move rules more agressive. Since it assumes selectors from different scopes don't match for the same element. This can improve rule merging.

Suppose we have a file:

.module1-foo { color: red; }
.module1-bar { font-size: 1.5em; background: yellow; }

.module2-baz { color: red; }
.module2-qux { font-size: 1.5em; background: yellow; width: 50px; }

It can be assumed that first two rules are never used with the second two on the same markup. But we can't say that for sure without a markup review. The optimizer doesn't know it either and will perform safe transformations only. The result will be the same as input but with no spaces and some semicolons:

.module1-foo{color:red}.module1-bar{font-size:1.5em;background:#ff0}.module2-baz{color:red}.module2-qux{font-size:1.5em;background:#ff0;width:50px}

With usage data CSSO can produce better output. If follow usage data is provided:

{
    "scopes": [
        ["module1-foo", "module1-bar"],
        ["module2-baz", "module2-qux"]
    ]
}

The result will be (29 bytes extra saving):

.module1-foo,.module2-baz{color:red}.module1-bar,.module2-qux{font-size:1.5em;background:#ff0}.module2-qux{width:50px}

If class name isn't mentioned in the scopes it belongs to default scope. scopes data doesn't affect classes whitelist. If class name mentioned in scopes but missed in classes (both sections are specified) it will be filtered.

Note that class name can't be set for several scopes. Also a selector can't have class names from different scopes. In both cases an exception will thrown.

Currently the optimizer doesn't care about changing order safety for out-of-bounds selectors (i.e. selectors that match to elements without class name, e.g. .scope div or .scope ~ :last-child). It assumes that scoped CSS modules doesn't relay on it's order. It may be fix in future if to be an issue.

changelog

5.0.5 (August 10, 2022)

  • Bumped css-tree to ~2.2.0 (#458)

5.0.4 (July 14, 2022)

  • Fixed usage filtering for from/to selectors in keyframes at-rule (#448)
  • Fixed removing medium in font declarations since it breaks the value since <font-size> is required (#449)

5.0.3 (March 9, 2022)

  • Fixed CommonJS version bundling when browser field is used
  • Added module field

5.0.2 (December 17, 2021)

  • Extended Node.js support to include ^10
  • Fixed main field in package.json to refer to CommonJS module
  • Bumped css-tree to ~2.0.4 (fixed CSS serialization issue in IE11)

5.0.1 (December 14, 2021)

  • Bumped css-tree to ~2.0.3 (various fixes on generate CSS)
  • Added exports:
    • csso/syntax

5.0.0 (December 4, 2021)

  • Added support for CSS Selectors Level 4 and legacy pseudos in specificity calculation, i.e. :has(), :not(<selector-list>), :is(), :matches(), :-moz-any(), :-webkit-any(), :where(), :nth-child(... of <selector-list>) and :nth-last-child(... of <selector-list>)
  • Package
    • Changed supported versions of Node.js to ^12.20.0, ^14.13.0 and >=15.0.0 (extended in 5.0.2 to include ^10)
    • Converted to ES modules. However, CommonJS is supported as well (dual module)
    • Changed bundle set to provide dist/csso.js (an IIFE version with csso as a global name) and dist/csso.esm.js (as ES module). Both are minified
    • Bumped css-tree to 2.0

4.2.0 (November 26, 2020)

  • Trim Custom Property values when possible (#393)
  • Fixed removing unit for zero-length dimentions in min(), max() and clamp() functions (#426)
  • Fixed crash on bad value in TRBL declaration value (#412)

4.1.1 (November 15, 2020)

  • Fixed build setup to exclude full mdn/data that reduced the lib size:
    • dist/csso.js: 794.5Kb -> 255.2Kb
    • dist/csso.min.js: 394.4Kb -> 194.2Kb
    • package size: 237.8 kB -> 156.1 kB
    • package unpacked size: 1.3 MB -> 586.8 kB

4.1.0 (October 27, 2020)

  • Bumped CSSTree to ^1.0.0
  • Fixed wrongly merging of TRBL values when one of them contains var() (#420)
  • Fixed wrongly merging of pseudo class and element with the same name, e.g. :-ms-input-placeholder and ::-ms-input-placeholder (#383, #416)
  • Fixed wrongly merging of overflow fallback (#415)

4.0.3 (March 24, 2020)

  • Prevented percent sign removal in flex/-ms-flex (#410)
  • Fixed restructuring optimisation in some cases (@charlessuh & @chsuh, #358, #411)
  • Bumped dependencies (@AviVahl, #409)

4.0.2 (October 28, 2019)

  • Fixed clean stage to avoid exceptions when source has unparsed or bad parts (#380)
  • Fixed wrong percentage sign removal for zero values (#395)

4.0.1 (October 22, 2019)

  • Bumped CSSTree to 1.0.0-alpha.37 to avoid source map generation inconsistency across Node.js versions

4.0.0 (October 21, 2019)

  • Dropped support for Node.js < 8
  • Refreshed dev dependencies and scripts
  • Bumped CSSTree to 1.0.0-alpha.36 (#399)
  • Changed bundle files: dist/csso.js and dist/csso.min.js instead single dist/csso-browser.js (min version)
  • Expose compress() as syntax.compress()

3.5.1 (June 7, 2018)

  • Bumped CSSTree to 1.0.0-alpha.29 (fixes some issues)

3.5.0 (January 14, 2018)

  • Migrated to CSSTree 1.0.0-alpha.27

3.4.0 (November 3, 2017)

  • Added percent sign removal for zero percentages for some properties that is safe (@RubaXa, #286)
  • Removed unit removal for zero values in -ms-flex due it breaks flex in IE10/11 (#362)
  • Improved performance of selectors comparison (@smelukov, #343)

3.3.1 (October 17, 2017)

  • Fixed merge of position declarations when sticky fallback is using (@gruzzilkin, #356)

3.3.0 (October 12, 2017)

  • Migrated to CSSTree 1.0.0-alpha25
    • Changed AST format (see CSSTree change log for details)
    • Fixed performance issue when generate CSS with source map (quadratic increase in time depending on the size of the CSS)

3.2.0 (September 10, 2017)

  • Fixed named color compression to apply only when an identifier is guaranteed to be a color
  • Added lifting of @keyframes to the beginning of style sheet (chunk), but after @charset and @import rules
  • Added removal of @keyframes, @media and @supports with no prelude
  • Added removal of duplicate @keyframes (#202)
  • Added new option forceMediaMerge to force media rules merging. It's unsafe in general, but works fine in many cases. Use it on your own risk (#350)
  • Bumped CSSTree to 1.0.0-alpha23

3.1.1 (April 25, 2017)

  • Fixed crash on a number processing when it used not in a list (#335)

3.1.0 (April 24, 2017)

  • Implemented optimisation for none keyword in border and outline properties (@zoobestik, #41)
  • Implemented replacing rgba(x, x, x, 0) to transparent
  • Fixed plus sign omitting for numbers following identifier, hex color, number or unicode range, since it can change the meaning of CSS (e.g. calc(1px+2px) has been optimized to calc(1px2px) before, now it stays the same)
  • Improved usage filtering for nested selectors (i.e. for :nth-*(), :has(), :matches and other pseudos)
  • Implemented blacklist filtering in usage (#334, see Black list filtering)
  • Improved white space removing, now white spaces are removing in the beginning and at the ending of sequences, and between stylesheet and block nodes
  • Bumped CSSTree to 1.0.0-alpha19

3.0.1 (March 14, 2017)

  • Fixed declaration merging when declaration contains an !important

3.0.0 (March 13, 2017)

  • Migrated to CSSTree as AST backend and exposed its API behind syntax property
  • Extracted CLI into standalone package css/csso-cli

2.3.1 (January 6, 2017)

  • Added \0 IE hack support (#320)

2.3.0 (October 25, 2016)

  • Added beforeCompress and afterCompress options support (#316)
  • Fixed crash on empty argument in function (#317)

2.2.1 (July 25, 2016)

  • Fixed shorthand optimisation issue when value has a color value or something unknown (#311)
  • Fixed cursor broken fallback (#306)

2.2.0 (June 23, 2016)

  • Implement AST cloning by adding clone() function and clone option for compress() function (#296)
  • Fix parse and translate attribute selector with flags but w/o operator (i.e. [attrName i])
  • Don't merge rules with flagged attribute selectors with others (#291)
  • Take in account functions when merge TRBL-properties (#297, thanks to @ArturAralin)
  • Improve partial merge (#304)
  • Tweak scanner, reduce code deoptimizations and other small improvements

2.1.1 (May 11, 2016)

  • Fix wrong declaration with \9 hack merge (#295)

2.1.0 (May 8, 2016)

  • New option comments to specify what comments to left: exclamation, first-exclamation and none
  • Add offset to CSS parse error details
  • Fix token offset computation

2.0.0 (April 5, 2016)

  • No more gonzales AST format and related code
  • minify() and minifyBlock() is always return an object as result now (i.e. { css: String, map: SourceMapGenerator or null })
  • parse()
    • Returns AST in new format (so called internal)
    • Dynamic scanner implemented
    • New AST format + dynamic scanner = performance boost and less memory consumption
    • No more context argument, context should be specified via options
    • Supported contexts now: stylesheet, atrule, atruleExpression, ruleset, selector, simpleSelector, block, declaration and value
    • Drop needPositions option, positions option should be used instead
    • Drop needInfo option, info object is attaching to nodes when some information is requested by options
    • options should be an object, otherwise it treats as empty object
  • compress()
    • No more AST converting (performance boost and less memory consumption)
    • Drop outputAst option
    • Returns an object as result instead of AST (i.e. { ast: Object })
  • Drop methods: justDoIt(), stringify(), cleanInfo()

1.8.1 (March 30, 2016)

  • Don't remove spaces after function/braces/urls since unsafe (#289)

1.8.0 (March 24, 2016)

  • Usage data support:
    • Filter rulesets by tag names, class names and ids white lists.
    • More aggressive ruleset moving using class name scopes information.
    • New CLI option --usage to pass usage data file.
  • Improve initial ruleset merge
    • Change order of ruleset processing, now it's left to right. Previously unmerged rulesets may prevent lookup and other rulesets merge.
    • Difference in pseudo signature just prevents ruleset merging, but don't stop lookup.
    • Simplify block comparison (performance).
  • New method csso.minifyBlock() for css block compression (e.g. style attribute content).
  • Ruleset merge improvement: at-rules with block (like @media or @supports) now can be skipped during ruleset merge lookup if doesn't contain something prevents it.
  • FIX: Add negation (:not()) to pseudo signature to avoid unsafe merge (old browsers doesn't support it).
  • FIX: Check nested parts of value when compute compatibility. It fixes unsafe property merging.

1.7.1 (March 16, 2016)

  • pass block mode to tokenizer for correct parsing of declarations properties with // hack
  • fix wrongly @import and @charset removal on double exclamation comment

1.7.0 (March 10, 2016)

  • support for CSS Custom Properties (#279)
  • rework RTBL properties merge – better merge for values with special units and don't merge values with CSS-wide keywords (#255)
  • remove redundant universal selectors (#178)
  • take in account !important when check for property overriding (#280)
  • don't merge text-align declarations with some values (#281)
  • add spaces around /deep/ combinator on translate, since it together with universal selector can produce a comment
  • better keyword and property name resolving (tolerant to hacks and so on)
  • integration improvements
    • compression log function could be customized by logger option for compress() and minify()
    • make possible to set initial line and column for parser

1.6.4 (March 1, 2016)

  • npm publish issue (#276)

1.6.3 (February 29, 2016)

  • add file to generated source map since other tools can relay on it in source map transform chain

1.6.2 (February 29, 2016)

  • tweak some parse error messages and their positions
  • fix :not() parsing and selector groups in :not() is supported now (#215)
  • needPosition parser option is deprecated, positions option should be used instead (needPosition is used still if positions option omitted)
  • expose internal AST API as csso.internal.*
  • minify() adds sourcesContent by default when source map is generated
  • bring back support for node.js 0.10 until major release (#275)

1.6.1 (February 28, 2016)

  • fix exception on zero length dimension compress outside declaration (#273)

1.6.0 (February 27, 2016)

  • source maps support
  • parser remake:
    • various parsing issues fixed
    • fix unicode sequence processing in ident (#191)
    • support for flags in attribute selector (#270)
    • position (line and column) of parse error (#109)
    • 4x performance boost, less memory consumption
  • compressor refactoring
    • internal AST is using doubly linked lists (with safe transformation support during iteration) instead of arrays
    • rename restructuring to restructure option for minify()/compress() (restructuring is alias for restructure now, with lower priority)
    • unquote urls when possible (#141, #60)
  • setup code coverage and a number of related fixes
  • add eslint to check unused things

1.5.4 (January 27, 2016)

  • one more fix (in restructRuleset this time) with merge of rulesets when a ruleset with same specificity places between them (#264)
  • disable partial merge of rulesets in @keyframes rulesets (until sure it's correct)

1.5.3 (January 25, 2016)

  • don't override display values with different browser support (#259)
  • fix publish issue (one of modules leak in development state)

1.5.2 (January 24, 2016)

  • don't merge rulesets if between them a ruleset with same specificity (#264)

1.5.1 (January 14, 2016)

  • ensure - is not used as an identifier in attribute selectors (thanks to @mathiasbynens)
  • fix broken justDoIt() function
  • various small fixes

1.5.0 (January 14, 2016)

Parser

  • attach minus to number

Compressor

  • split code base into small modules and related refactoring
  • introduce internal AST format for compressor (gonzalesinternal and internalgonzales convertors, walkers, translator)
  • various optimizations: no snapshots, using caches and indexes
  • sort selectors, merge selectors in alphabet order
  • compute selector's specificity
  • better ruleset restructuring, improve compression of partially equal blocks
  • better ruleset merge – not only closest but also disjoined by other rulesets when safe
  • join @media with same query
  • outputAst – new option to specify output AST format (gonzales by default for backward compatibility)
  • remove quotes surrounding attribute values in attribute selectors when possible (#73)
  • replace from0% and 100%to at @keyframes (#205)
  • prevent partial merge of rulesets at @keyframes (#80, #197)

API

  • walker for gonzales AST was implemented

CLI

  • new option --stat (output stat in stderr)
  • new optional parameter level for --debug option

1.4.4 (December 10, 2015)

  • prevent removal of spaces after braces that before identifier that breaking at-rules expressions (#258)

1.4.3 (December 4, 2015)

  • fix unicode-range parsing that cause to wrong function detection (#250)

1.4.2 (November 9, 2015)

  • allow spaces between progid: and rest part of value for IE's filter property as autoprefixer generates this kind of code (#249)
  • fixes for Windows:
    • correct processing new lines
    • normalize file content in test suite
  • fixes to work in strict mode (#252)
  • init compressor dictionaries for every css block (#248, #251)
  • bump uglify-js version

1.4.1 (October 20, 2015)

  • allow merge for display property (#167, #244)
  • more accurate rect (clip property value) merge
  • fix typo when specifying options in cli (thanks to @Taritsyn)
  • fix safe unit values merge with keyword values (#244)
  • fix wrong descendant combinator removal (#246)
  • build browser version on prepublish (thanks to @silentroach)
  • parser: store whitespaces as single token (performance and reduce memory consumption)
  • rearrange compress tests layout

1.4 (October 16, 2015)

Bringing project back to life. Changed files structure, cleaned up and refactored most of sources.

Common

  • single code base (no more src folder)
  • build browser version with browserify (no more make, and web folder), browser version is available at dist/csso-browser.js
  • main file is lib/index.js now
  • minimal node.js version is 0.12 now
  • restrict file list to publish on npm (no more useless folders and files in package)
  • add jscs to control code style
  • automate gh-pages update
  • util functions reworked
  • translator reworked
  • test suite reworked
  • compressor refactored
  • initial parser refactoring

API

  • new method minify(src, options), options:
    • restructuring – if set to false, disable structure optimisations (true by default)
    • debug - outputs intermediate state of CSS during compression (false by default)
  • deprecate justDoIt() method (use minify instead)
  • rename treeToString() method to stringify()
  • drop printTree() method
  • AST node info
    • column and offset added
    • ln renamed to line
    • fix line counting across multiple files and input with CR LF (#147)

CLI

  • completely reworked, use clap to parse argv
  • add support for input from stdin (#128)
  • drop undocumented and obsoleted options --rule and --parser (suppose nobody use it)
  • drop -off alias for --restructure-off as incorrect (only one letter options should starts with single -)
  • new option --debug that reflecting to options.debug for minify

Parsing and optimizations

  • keep all exclamation comments (#194)
  • add /deep/ combinator support (#209)
  • attribute selector
    • allow colon in attribute name (#237)
    • support for namespaces (#233)
  • color
    • support all css/html colors
    • convert hsla to rgba and hls to rgb
    • convert rgba with 1 as alpha value to rgb (#122)
    • interpolate rgb and rgba percentage values to absolute values
    • replace percentage values in rgba for normalized/interpolated values
    • lowercase hex colors and color names (#169)
    • fix color minification when hex value replaced for color name (#176)
    • fit rgb values to 0..255 range (#181)
  • calc
    • remove spaces for multiple operator in calc
    • don't remove units inside calc (#222)
    • fix wrong white space removal around + and - (#228)
  • don't remove units in flex property as it could change value meaning (#200)
  • don't merge \9 hack values (#231)
  • merge property values only if they have the same functions (#150, #227)
  • don't merge property values with some sort of units (#140, #161)
  • fix !important issue for top-right-bottom-left properties (#189)
  • fix top-right-bottom-left properties merge (#139, #175)
  • support for unicode-range (#148)
  • don't crash on ruleset with no selector (#135)
  • tolerant to class names that starts with digit (#99, #105)
  • fix background compressing (#170)

1.3.12 (October 8, 2015)

  • Case insensitive check for !important (#187)
  • Fix problems with using csso as cli command on Windows (#83, #136, #142 and others)
  • Remove byte order marker (the UTF-8 BOM) from input
  • Don't strip space between funktion-funktion and funktion-vhash (#134)
  • Don't merge TRBL values having \9 (hack for IE8 in bootstrap) (#159, #214, #230, #231 and others)
  • Don't strip units off dimensions of non-length (#226, #229 and others)

1.3.7 (February 11, 2013)

  • Gonzales 1.0.7.

1.3.6 (November 26, 2012)

  • Gonzales 1.0.6.

1.3.5 (October 28, 2012)

1.3.4 (October 10, 2012)

1.3.3 (October 9, 2012)

1.3.2 (October 8, 2012)

1.3.1 (October 8, 2012)

1.3.0 (October 4, 2012)

  • PeCode CSS parser replaced by Gonzales CSS parser