Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

dropcss

Package Overview
Dependencies
Maintainers
1
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dropcss

An exceptionally fast, thorough and tiny unused-CSS cleaner

  • 1.0.0
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
1.5K
decreased by-12.42%
Maintainers
1
Weekly downloads
 
Created
Source

🗑 DropCSS

An exceptionally fast, thorough and tiny unused-CSS cleaner (MIT Licensed)


Introduction

DropCSS is an exceptionally fast, thorough and tiny (~8 KB min) unused-CSS cleaner; it takes your HTML and CSS as input and returns only the used CSS as output. Its custom HTML and CSS parsers are highly optimized for the 99% use case and thus avoid the overhead of handling malformed markup or stylesheets, so you must provide well-formed input. There is minimal handling for complex escaping rules, so there will always exist cases of valid input that cannot be processed by DropCSS; for these infrequent cases, please start a discussion, use a previous, larger and slower 0.3.x version that uses heavier but more compliant parsers, or use an alternative CSS cleaner.

As a bonus, DropCSS will also remove unused any @keyframes and @font-face blocks, despite it being somewhat out of scope for this lib (being a purely intra-CSS optimization). Speaking of which, it's a good idea to run your CSS through a structural optimizer like clean-css, csso, cssnano or crass to re-group selectors, merge redundant rules, etc. It probably makes sense to do this after DropCSS, which can leave redundant blocks, e.g. .foo, .bar { color: red; }; .bar { width: 50%; } -> .bar { color: red; }; .bar { width: 50%; } if .foo is absent from your markup.

A bit more on this project's backstory & discussions in /r/javascript and on Hacker News.


Live Demo: https://codepen.io/leeoniya/pen/LvbRyq


Installation

npm install -D dropcss

Usage & API

const dropcss = require('dropcss');

let html = `
    <html>
        <head></head>
        <body>
            <p>Hello World!</p>
        </body>
    </html>
`;

let css = `
    .card {
      padding: 8px;
    }

    p:hover a:first-child {
      color: red;
    }
`;

const whitelist = /#foo|\.bar/;

let dropped = new Set();

let cleaned = dropcss({
    html,
    css,
    shouldDrop: (sel) => {
        if (whitelist.test(sel))
            return false;
        else {
            dropped.add(sel);
            return true;
        }
    },
});

console.log(cleaned.css);

console.log(dropped);

The shouldDrop hook is called for every CSS selector that could not be matched in the html. Return false to retain the selector or true to drop it.


Features

  • Retention of all transient pseudo-class and pseudo-element selectors which cannot be deterministically checked from the parsed HTML.
  • Supported selectors
    • * - universal
    • <tag> - tag
    • # - id
    • . - class
    • - descendant
    • > - child
    • + - adjacent sibling
    • ~ - general sibling
    • [attr] - attribute
    • [attr=val]
    • [attr*=val]
    • [attr^=val]
    • [attr$=val]
    • :not()
    • :first-child
    • :last-child
    • :only-child
    • :nth-child()
    • :nth-last-child()
    • :first-of-type
    • :last-of-type
    • :only-of-type
    • :nth-of-type()
    • :nth-last-of-type()

Performance

Input

test.html

  • 18.8 KB minified
  • 502 dom nodes via document.querySelectorAll("*").length

styles.min.css

  • 27.67 KB combined, optimized and minified via clean-css
  • contents: Bootstrap's reboot.css, an in-house flexbox grid, global layout, navbars, colors & page-specific styles. (the grid accounts for ~85% of this starting weight, lots of media queries & repetition)
Output
lib size w/depsoutput sizereductiontime elapsedunused bytes (test.html coverage)
DropCSS 52.6 KB
6 files, 1 Folders
6.58 KB76.15%20ms575 / 8.5%
UnCSS 13.7 MB
2,831 Files, 301 Folders
6.72 KB75.71%409ms638 / 9.3%
Purgecss 2.53 MB
513 Files, 110 Folders
8.01 KB71.05%79ms1,806 / 22.0%
PurifyCSS 3.45 MB
791 Files, 207 Folders
15.46 KB44.34%179ms9,440 / 59.6%

Notes

  • About 400 "unused bytes" are due to an explicit/shared whitelist, not an inability of the tools to detect/remove that CSS.
  • About 175 "unused bytes" are due to vendor-prefixed (-moz, -ms) properties & selectors that are inactive in Chrome, which is used for testing coverage.
  • Purgecss does not support attribute or complex selectors: Issue #110.

A full Stress Test is also available.


TODO

  • Moar tests. DropCSS is currently developed against gigantic blobs of diverse, real-world CSS and HTML. These inputs & outputs are also used for perf testing and regression detection. While not all output was verified by hand (this would be infeasible for giganitic mis-matched HTML/CSS inputs), it was loosely verified against what other cleaners remove and what they leave behind. Writing tests is additonally challenging because the way selectors are drop-tested is optimized to fast-path many cases; a complex-looking test like .foo > ul + p:not([foo*=bar]):hover will actually short circuit early if .foo, ul or p are missing from the dom, and will never continue to structural/context or negation assertions. Tests must be carefully written to ensure they hit all the desired paths; it's easy to waste a lot of time writing useless tests that add no value. Unfortunately, even 100% cumulative code coverage of the test suite would only serve as a starting point. Good tests would be a diverse set of real-world inputs and manually verified outputs.

Caveats

  • Not tested against or designd to handle malformed HTML or CSS
  • Excessive escaping or reserved characters in your HTML or CSS can break DropCSS's parsers
  • There is no processing or execution of <script> tags; your HTML must be fully formed (or SSR'd). You should generate and append any additional HTML that you'd want to be considered by DropCSS. If you need JS execution, consider using the larger, slower but still good output, UnCSS. Alternatively, Puppeteer can now output coverage reports, and there might be tools that utilize this coverage data to clean your CSS, too. DropCSS aims to be minimal, simple and effective.

Acknowledgements

  • Felix Böhm's nth-check - it's not much code, but getting An+B expression testing exactly right is frustrating. I got part-way there before discovering this tiny solution.
  • Vadim Kiryukhin's vkbeautify - the benchmark and test code uses this tiny formatter to make it easier to spot differences in output diffs.

FAQs

Package last updated on 08 Apr 2019

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc