What is clean-css?
Clean-css is a fast and efficient Node.js library for minifying CSS files.
According to tests it is one of the best available.
Usage
What are the requirements?
Node.js 0.10+ (tested on CentOS, Ubuntu, OS X 10.6+, and Windows 7+) or io.js 3.0+
How to install clean-css?
npm install clean-css
How to use clean-css CLI?
Clean-css accepts the following command line arguments (please make sure
you use <source-file>
as the very last argument to avoid potential issues):
cleancss [options] source-file, [source-file, ...]
-h, --help output usage information
-v, --version output the version number
-b, --keep-line-breaks Keep line breaks
-c, --compatibility [ie7|ie8] Force compatibility mode (see Readme for advanced examples)
-d, --debug Shows debug information (minification time & compression efficiency)
-o, --output [output-file] Use [output-file] as output instead of STDOUT
-r, --root [root-path] Set a root path to which resolve absolute @import rules
-s, --skip-import Disable @import processing
-t, --timeout [seconds] Per connection timeout when fetching remote @imports (defaults to 5 seconds)
--rounding-precision [n] Rounds to `N` decimal places. Defaults to 2. -1 disables rounding
--s0 Remove all special comments, i.e. /*! comment */
--s1 Remove all special comments but the first one
--semantic-merging Enables unsafe mode by assuming BEM-like semantic stylesheets (warning, this may break your styling!)
--skip-advanced Disable advanced optimizations - ruleset reordering & merging
--skip-aggressive-merging Disable properties merging based on their order
--skip-import-from [rules] Disable @import processing for specified rules
--skip-media-merging Disable @media merging
--skip-rebase Disable URLs rebasing
--skip-restructuring Disable restructuring optimizations
--skip-shorthand-compacting Disable shorthand compacting
--source-map Enables building input's source map
--source-map-inline-sources Enables inlining sources inside source maps
Examples:
To minify a public.css file into public-min.css do:
cleancss -o public-min.css public.css
To minify the same public.css into the standard output skip the -o
parameter:
cleancss public.css
More likely you would like to concatenate a couple of files. If you are on a Unix-like system:
cat one.css two.css three.css | cleancss -o merged-and-minified.css
On Windows:
type one.css two.css three.css | cleancss -o merged-and-minified.css
Or even gzip the result at once:
cat one.css two.css three.css | cleancss | gzip -9 -c > merged-minified-and-gzipped.css.gz
How to use clean-css API?
var CleanCSS = require('clean-css');
var source = 'a{font-weight:bold;}';
var minified = new CleanCSS().minify(source).styles;
CleanCSS constructor accepts a hash as a parameter, i.e.,
new CleanCSS(options)
with the following options available:
-
advanced
- set to false to disable advanced optimizations - selector & property merging, reduction, etc. -
aggressiveMerging
- set to false to disable aggressive merging of properties. -
benchmark
- turns on benchmarking mode measuring time spent on cleaning up (runnpm run bench
to see example) -
compatibility
- enables compatibility mode, see below for more examples -
debug
- set to true to get minification statistics understats
property (seetest/custom-test.js
for examples) -
inliner
- a hash of options for@import
inliner, see test/protocol-imports-test.js for examples, or this comment for a proxy use case. -
keepBreaks
- whether to keep line breaks (default is false) -
keepSpecialComments
-*
for keeping all (default),1
for keeping first one only,0
for removing all -
mediaMerging
- whether to merge@media
at-rules (default is true) -
processImport
- whether to process@import
rules -
processImportFrom
- a list of@import
rules, can be['all']
(default),['local']
,['remote']
, or a blacklisted path e.g.['!fonts.googleapis.com']
-
rebase
- set to false to skip URL rebasing -
relativeTo
- path to resolve relative@import
rules and URLs -
restructuring
- set to false to disable restructuring in advanced optimizations -
root
- path to resolve absolute@import
rules and rebase relative URLs -
roundingPrecision
- rounding precision; defaults to2
;-1
disables rounding -
semanticMerging
- set to true to enable semantic merging mode which assumes BEM-like content (default is false as it's highly likely this will break your stylesheets - use with caution!) -
shorthandCompacting
- set to false to skip shorthand compacting (default is true unless sourceMap is set when it's false) -
sourceMap
- exposes source map undersourceMap
property, e.g.new CleanCSS().minify(source).sourceMap
(default is false) If input styles are a product of CSS preprocessor (Less, Sass) an input source map can be passed as a string. -
sourceMapInlineSources
- set to true to inline sources inside a source map'ssourcesContent
field (defaults to false) It is also required to process inlined sources from input source maps. -
target
- path to a folder or an output file to which rebase all URLs
The output of minify
method (or the 2nd argument to passed callback) is a hash containing the following fields:
-
styles
- optimized output CSS as a string -
sourceMap
- output source map (if requested withsourceMap
option) -
errors
- a list of errors raised -
warnings
- a list of warnings raised -
stats
- a hash of statistic information (if requested withdebug
option):-
originalSize
- original content size (after import inlining) -
minifiedSize
- optimized content size -
timeSpent
- time spent on optimizations -
efficiency
- a ratio of output size to input size (e.g. 25% if content was reduced from 100 bytes to 75 bytes)
-
@import
s are processed correctly?
How to make sure remote In order to inline remote @import
statements you need to provide a callback to minify method, e.g.:
var CleanCSS = require('clean-css');
var source = '@import url(http://path/to/remote/styles);';
new CleanCSS().minify(source, function (errors, minified) {
// minified.styles
});
This is due to a fact, that, while local files can be read synchronously, remote resources can only be processed asynchronously.
If you don't provide a callback, then remote @import
s will be left intact.
How to use clean-css with build tools?
- Broccoli: broccoli-clean-css
- Brunch: clean-css-brunch
- Grunt: grunt-contrib-cssmin
- Gulp: gulp-minify-css
- Gulp: using vinyl-map as a wrapper - courtesy of @sogko
- component-builder2: builder-clean-css
- Metalsmith: metalsmith-clean-css
- Lasso: lasso-clean-css
What are the clean-css' dev commands?
First clone the source, then run:
-
npm run bench
for clean-css benchmarks (see test/bench.js for details) -
npm run browserify
to create the browser-ready clean-css version -
npm run check
to check JS sources with JSHint -
npm test
for the test suite
How to contribute to clean-css?
See CONTRIBUTING.md.
Tips & Tricks
How to preserve a comment block?
Use the /*!
notation instead of the standard one /*
:
/*!
Important comments included in minified output.
*/
How to rebase relative image URLs?
Clean-css will handle it automatically for you (since version 1.1) in the following cases:
- When using the CLI:
- Use an output path via
-o
/--output
to rebase URLs as relative to the output file. - Use a root path via
-r
/--root
to rebase URLs as absolute from the given root path. - If you specify both then
-r
/--root
takes precendence.
- Use an output path via
- When using clean-css as a library:
- Use a combination of
relativeTo
andtarget
options for relative rebase (same as 1 in CLI). - Use a combination of
relativeTo
androot
options for absolute rebase (same as 2 in CLI). -
root
takes precendence overtarget
as in CLI.
- Use a combination of
How to generate source maps?
Source maps are supported since version 3.0.
Additionally to mapping original CSS files, clean-css also supports input source maps, so minified styles can be mapped into their Less or Sass sources directly.
Source maps are generated using source-map module from Mozilla.
Using CLI
To generate a source map, use --source-map
switch, e.g.:
cleancss --source-map --output styles.min.css styles.css
Name of the output file is required, so a map file, named by adding .map
suffix to output file name, can be created (styles.min.css.map in this case).
Using API
To generate a source map, use sourceMap: true
option, e.g.:
new CleanCSS({ sourceMap: true, target: pathToOutputDirectory })
.minify(source, function (minified) {
// access minified.sourceMap for SourceMapGenerator object
// see https://github.com/mozilla/source-map/#sourcemapgenerator for more details
// see https://github.com/jakubpawlowicz/clean-css/blob/master/bin/cleancss#L114 on how it's used in clean-css' CLI
});
Using API you can also pass an input source map directly:
new CleanCSS({ sourceMap: inputSourceMapAsString, target: pathToOutputDirectory })
.minify(source, function (minified) {
// access minified.sourceMap to access SourceMapGenerator object
// see https://github.com/mozilla/source-map/#sourcemapgenerator for more details
// see https://github.com/jakubpawlowicz/clean-css/blob/master/bin/cleancss#L114 on how it's used in clean-css' CLI
});
Or even multiple input source maps at once (available since version 3.1):
new CleanCSS({ sourceMap: true, target: pathToOutputDirectory }).minify({
'path/to/source/1': {
styles: '...styles...',
sourceMap: '...source-map...'
},
'path/to/source/2': {
styles: '...styles...',
sourceMap: '...source-map...'
}
}, function (minified) {
// access minified.sourceMap as above
});
How to minify multiple files with API?
Passing an array
new CleanCSS().minify(['path/to/file/one', 'path/to/file/two']);
Passing a hash
new CleanCSS().minify({
'path/to/file/one': {
styles: 'contents of file one'
},
'path/to/file/two': {
styles: 'contents of file two'
}
});
How to set a compatibility mode?
Compatibility settings are controlled by --compatibility
switch (CLI) and compatibility
option (library mode).
In both modes the following values are allowed:
-
'ie7'
- Internet Explorer 7 compatibility mode -
'ie8'
- Internet Explorer 8 compatibility mode -
''
or'*'
(default) - Internet Explorer 9+ compatibility mode
Since clean-css 3 a fine grained control is available over those settings, with the following options available:
-
'[+-]colors.opacity'
- - turn on (+) / off (-)rgba()
/hsla()
declarations removal -
'[+-]properties.backgroundClipMerging'
- turn on / off background-clip merging into shorthand -
'[+-]properties.backgroundOriginMerging'
- turn on / off background-origin merging into shorthand -
'[+-]properties.backgroundSizeMerging'
- turn on / off background-size merging into shorthand -
'[+-]properties.colors'
- turn on / off any color optimizations -
'[+-]properties.ieBangHack'
- turn on / off IE bang hack removal -
'[+-]properties.iePrefixHack'
- turn on / off IE prefix hack removal -
'[+-]properties.ieSuffixHack'
- turn on / off IE suffix hack removal -
'[+-]properties.merging'
- turn on / off property merging based on understandability -
'[+-]properties.spaceAfterClosingBrace'
- turn on / off removing space after closing brace -url() no-repeat
intourl()no-repeat
-
'[+-]properties.urlQuotes'
- turn on / offurl()
quoting -
'[+-]properties.zeroUnits'
- turn on / off units removal after a0
value -
'[+-]selectors.adjacentSpace'
- turn on / off extra space beforenav
element -
'[+-]selectors.ie7Hack'
- turn on / off IE7 selector hack removal (*+html...
) -
'[+-]selectors.special'
- a regular expression with all special, unmergeable selectors (leave it empty unless you know what you are doing) -
'[+-]units.ch'
- turn on / off treatingch
as a proper unit -
'[+-]units.in'
- turn on / off treatingin
as a proper unit -
'[+-]units.pc'
- turn on / off treatingpc
as a proper unit -
'[+-]units.pt'
- turn on / off treatingpt
as a proper unit -
'[+-]units.rem'
- turn on / off treatingrem
as a proper unit -
'[+-]units.vh'
- turn on / off treatingvh
as a proper unit -
'[+-]units.vm'
- turn on / off treatingvm
as a proper unit -
'[+-]units.vmax'
- turn on / off treatingvmax
as a proper unit -
'[+-]units.vmin'
- turn on / off treatingvmin
as a proper unit -
'[+-]units.vm'
- turn on / off treatingvm
as a proper unit
For example, using --compatibility 'ie8,+units.rem'
will ensure IE8 compatibility while enabling rem
units so the following style margin:0px 0rem
can be shortened to margin:0
, while in pure IE8 mode it can't be.
To pass a single off (-) switch in CLI please use the following syntax --compatibility *,-units.rem
.
In library mode you can also pass compatibility
as a hash of options.
What advanced optimizations are applied?
All advanced optimizations are dispatched here, and this is what they do:
-
recursivelyOptimizeBlocks
- does all the following operations on a block (think@media
or@keyframe
at-rules); -
recursivelyOptimizeProperties
- optimizes properties in rulesets and "flat at-rules" (like @font-face) by splitting them into components (e.g.margin
intomargin-(*)
), optimizing, and rebuilding them back. You may want to useshorthandCompacting
option to control whether you want to turn multiple (long-hand) properties into a shorthand ones; -
removeDuplicates
- gets rid of duplicate rulesets with exactly the same set of properties (think of including the same Sass / Less partial twice for no good reason); -
mergeAdjacent
- merges adjacent rulesets with the same selector or rules; -
reduceNonAdjacent
- identifies which properties are overridden in same-selector non-adjacent rulesets, and removes them; -
mergeNonAdjacentBySelector
- identifies same-selector non-adjacent rulesets which can be moved (!) to be merged, requires all intermediate rulesets to not redefine the moved properties, or if redefined to be either more coarse grained (e.g.margin
vsmargin-top
) or have the same value; -
mergeNonAdjacentByBody
- same as the one above but for same-rules non-adjacent rulesets; -
restructure
- tries to reorganize different-selector different-rules rulesets so they take less space, e.g..one{padding:0}.two{margin:0}.one{margin-bottom:3px}
into.two{margin:0}.one{padding:0;margin-bottom:3px}
; -
removeDuplicateMediaQueries
- removes duplicated@media
at-rules; -
mergeMediaQueries
- merges non-adjacent@media
at-rules by same rules asmergeNonAdjacentBy*
above;
Acknowledgments (sorted alphabetically)
- Anthony Barre (@abarre) for improvements to
@import
processing, namely introducing the--skip-import
/processImport
options. - Simon Altschuler (@altschuler) for fixing
@import
processing inside comments. - Isaac (@facelessuser) for pointing out a flaw in clean-css' stateless mode.
- Jan Michael Alonzo (@jmalonzo) for a patch
removing node.js' old
sys
package. - Luke Page (@lukeapage) for suggestions and testing the source maps feature. Plus everyone else involved in #125 for pushing it forward.
- Timur Kristóf (@Venemo) for an outstanding contribution of advanced property optimizer for 2.2 release.
- Vincent Voyer (@vvo) for a patch with better empty element regex and for inspiring us to do many performance improvements in 0.4 release.
- @XhmikosR for suggesting new features (option to remove special comments and strip out URLs quotation) and pointing out numerous improvements (JSHint, media queries).
License
Clean-css is released under the MIT License.