Hasmin - A Haskell CSS Minifier

Build Status Hackage Hackage-Deps License

Hasmin is a CSS minifier written entirely in Haskell. To use it as a library, see below

Aside from the usual techniques (e.g. whitespace removal, color minification, etc.), the idea was to explore new possibilities, by implementing things other minifiers weren’t doing, or they were, but not taking full advantage of.

Also, the minifier implements some techniques that do nothing for minified sizes, but attempt to improve post-compression sizes (at least when using DEFLATE, i.e. gzip).

For a list of techniques, see Minification Techniques.


To compile, just run stack build.

Minifier Usage

Hasmin expects a path to the CSS file, and outputs the minified result to stdout.

Every technique is enabled by default, except for:

  1. Escaped character conversions (e.g. converting \2714 to , which can be enabled with --convert-escaped-characters)
  2. Dimension minifications (e.g. converting 12px to 9pt, which can be enabled with --dimension-min, or just -d)

These two are disabled mainly because they are—on average, not always—detrimental for DEFLATE compression. When something needs to be disabled, use the appropriate flag. Not every technique can be toggled yet, but a good amount of them allow it.

Note: there is a problem in Windows when using the --convert-escaped-characters flag to enable the conversion of escaped characters. A workaround is changing the code page, which can be done by running chcp 65001 in the terminal (whether cmd, or cygwin).


The preferable way to use Hasmin as a library is to import Hasmin, as exemplified in the module’s documentation. That is currently the only module that is sure to abide by PVP. Most other exposed modules are so because tests need it, and thus definitions there may be changed anytime. In case something internal is needed though, feel free to open an issue about it.

Zopfli Integration

Hasmin uses bindings to Google’s Zopfli library, allowing the possibility to compress the result.

Since the output is a gzip file, it can be used for the web. It tipically produces files 3~8% smaller than zlib, at the cost of being around 80 times slower, so it is only a good idea if you don’t need compression on the fly.

Zopfli is released under the Apache License, Version 2.0.




Added a simple merging of adjacent media queries (@media rules), e.g.:

@media all and (min-width: 24rem) {
  a { font-size: 1.2rem; }
@media all and (min-width: 24rem) {
  b { padding-left: .25rem; padding-right: .25rem; }

Gets merged into into:

@media all and (min-width: 24rem) {
  a { font-size: 1.2rem; }
  b { padding-left: .25rem; padding-right: .25rem; }

  • Relaxed doctest upper bound.

  • Relaxed criterion upper bound.

  • Relaxed optparse-applicative upper bound.


  • Fixed some dimensions minifying incorrectly.
  • Fixed some Eq instances.
  • <An+B> values data type modified to disallow invalid values. This makes the data type safer, also simplifying the Quickcheck Arbitrary instance.
  • Improved test coverage.

  • Added support for @supports rules, and a slight minification for them: it removes adjacent negations, i.e.: @supports not (not …) gets turn into @supports ….
  • Fixed a small bug with :lang() where spaces before the right parenthesis weren’t being removed.
  • Improved test coverage.

Initial release