# DropCSS **Repository Path**: mirrors/DropCSS ## Basic Information - **Project Name**: DropCSS - **Description**: DropCSS 是一个用来清理无用 CSS 的小工具,它根据 HTML 和 CSS 作为输入并返回那些有用到的 CSS 信息 - **Primary Language**: JavaScript - **License**: MIT - **Default Branch**: master - **Homepage**: https://www.oschina.net/p/dropcss - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2019-03-26 - **Last Updated**: 2025-11-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 🗑 DropCSS An [exceptionally fast](#performance), thorough and tiny ([~10 KB min](https://github.com/leeoniya/dropcss/tree/master/dist/dropcss.iife.min.js)) unused-CSS cleaner _(MIT Licensed)_ --- ### Introduction DropCSS 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 well-formed input is required. 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](https://github.com/leeoniya/dropcss/issues). While the HTML spec allows `html`, `head`, `body` and `tbody` to be implied/omitted, DropCSS makes no such assumptions; selectors will only be retained for tags that can be parsed from provided markup. It's also a good idea to run your CSS through a structural optimizer like [clean-css](https://github.com/jakubpawlowicz/clean-css), [csso](https://github.com/css/csso), [cssnano](https://github.com/cssnano/cssnano) or [crass](https://github.com/mattbasta/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. More on this project's backstory & discussions: v0.1.0 alpha: [/r/javascript](https://old.reddit.com/r/javascript/comments/b3mcu8/dropcss_010_a_minimal_and_thorough_unused_css/), [Hacker News](https://news.ycombinator.com/item?id=19469080) and v1.0.0 release: [/r/javascript](https://old.reddit.com/r/javascript/comments/bb7im2/dropcss_v100_an_exceptionally_fast_thorough_and/). ---

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

--- ### Installation ``` npm install -D dropcss ``` --- ### Usage & API ```js const dropcss = require('dropcss'); let html = `

Hello World!

`; 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 - Supported selectors | Common | Attribute | Positional | Positional (of-type) | Other | |---------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------|----------| | `*` - universal
`` - tag
`#` - id
`.` - class
  - descendant
`>` - child
`+` - adjacent sibling
`~` - general sibling | `[attr]`
`[attr=val]`
`[attr*=val]`
`[attr^=val]`
`[attr$=val]`
`[attr~=val]` | `: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()` | `:not()` | - Retention of all transient pseudo-class and pseudo-element selectors which cannot be deterministically checked from the parsed HTML. - Removal of unused `@font-face` and `@keyframes` blocks. - Removal of unused [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/--*). - Deep resolution of composite CSS variables, e.g: ```css :root { --font-style: italic; --font-weight: bold; --line-height: var(--height)em; --font-family: 'Open Sans'; --font: var(--font-style) var(--font-weight) 1em/var(--line-height) var(--font-family); --height: 1.6; } @font-face { font-family: var(--font-family); src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2"), url("/fonts/OpenSans-Regular-webfont.woff") format("woff"); } body { font: var(--font); } ``` --- ### 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](https://github.com/jakubpawlowicz/clean-css) - contents: Bootstrap's [reboot.css](https://github.com/twbs/bootstrap/blob/master/dist/css/bootstrap-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/deps output size reduction time elapsed unused bytes (test.html coverage)
DropCSS 58.4 KB
6 Files, 2 Folders
6.58 KB 76.15% 21 ms 575 / 8.5%
UnCSS 13.5 MB
2,829 Files, 301 Folders
6.72 KB 75.71% 385 ms 638 / 9.3%
Purgecss 2.69 MB
560 Files, 119 Folders
8.01 KB 71.05% 88 ms 1,806 / 22.0%
PurifyCSS 3.46 MB
792 Files, 207 Folders
15.46 KB 44.34% 173 ms 9,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](https://github.com/FullHuman/purgecss/issues/110). A full **[Stress Test](https://github.com/leeoniya/dropcss/tree/master/test/bench)** is also available. --- ### JavaScript Execution DropCSS does not load external resources or execute `