Make your CSS so fresh, so clean.
Find a file
2024-07-07 17:29:23 -04:00
.github Create FUNDING.yml 2024-06-07 07:50:53 -04:00
refreshcss Internal restructuring. 2024-07-07 17:12:23 -04:00
tests Internal restructuring. 2024-07-07 17:12:23 -04:00
.all-contributorsrc docs: update .all-contributorsrc 2024-07-04 17:22:04 -04:00
.gitignore __pycache__/ added to .gitignore 2024-06-24 17:49:42 +02:00
CHANGELOG.md Bump to 0.5.0. 2024-07-07 17:19:27 -04:00
conftest.py Initial commit. 2024-06-06 22:58:47 -04:00
justfile Add cli extra to just. 2024-07-07 17:29:23 -04:00
LICENSE Initial commit. 2024-06-06 22:58:47 -04:00
poetry.lock Add mypy back to dev dependencies. 2024-07-06 17:47:36 -04:00
py.typed Initial commit. 2024-06-06 22:58:47 -04:00
pyproject.toml Bump to 0.5.0. 2024-07-07 17:19:27 -04:00
README.md Bump to 0.5.0. 2024-07-07 17:19:27 -04:00

RefreshCSS 🫧

All Contributors

RefreshCSS is a Python library that removes unused classes, ids, and element selectors from CSS.

Make your CSS so fresh, so clean.

🔧 Installation

To use the refreshcss library or use the django-compressor integration

pip install refreshcss

To run refreshcss on the command-line

pip install refreshcss[cli]

Features

  • Pure Python (no extra NodeJS build process needed)
  • Filters out unused classes, ids, elements from CSS based on HTML templates
  • Handles Django/Jinja styles HTML templates
  • Can be used as a filter with django-compressor to minify CSS as part of the compress management command
  • Can be used via command-line interface in CI/CD

⌨️ Command-line interface

Make sure that the cli extra is installed first: pip install refreshcss[cli].

Usage: refreshcss [OPTIONS] CSS HTML...

  Remove classes, ids, and element selectors not used in HTML from CSS.

Options:
  -o, --output FILENAME  Write to file instead of stdout.
  -R, -r, --recursive    Recursively search subdirectories listed.
  --encoding TEXT        Character encoding to use when reading files. If not
                         specified, the encoding will be guessed.
  --version              Show the version and exit.
  --help                 Show this message and exit.

🗜️ Integrate with django-compressor

Add "refreshcss.filters.RefreshCSSFilter" to COMPRESS_FILTERS in the Django settings file.

COMPRESS_FILTERS = {
    "css": [
        "refreshcss.filters.RefreshCSSFilter",
        ...
    ],
    "js": [...],
}

⚙️ Library

from refreshcss import RefreshCSS, PathSite

def clean_css(css_path: Path):
    # Parse the HTML files
    site = PathSite(paths=["templates"], recursive=True)
    site.parse()

    # Get clean CSS based on the parsed HTML
    css_text = css_path.read_text()
    cleaned_css = RefreshCSS(site).clean(css_text)

    return cleaned_css

🤓 How does it work?

  1. Catalogue classes, ids, and elements that are currently being used in found HTML templates
  2. Catalogue classes, ids, elements, and at-rules in a particular CSS stylesheet
  3. Return new CSS stylesheet that only contains rules that are actively being used by the HTML

🧐 Why?

I wanted to have a filter for django-compressor that would purge unused CSS as part of the compress step when deploying for coltrane apps. After dealing with a manual process and attempting to integrate https://purgecss.com and https://github.com/uncss/uncss I thought "this couldn't be that hard to do in Python".

Which is always the thought at the beginning of every side project... 😅

🙋 FAQ

Will this work with SPAs?

Probably not. RefreshCSS only inspects HTML templates, so if CSS classes are being changed client-side then refreshcss will not know about it.

Does this work by crawling a website URL?

Currently no, although that is a possibility in the future. PRs appreciated. 😉

Does this support HTML written in the Django Template Language?

Yes! That was a primary reason I built my own solution. 😅 Jinja might also be possible to support with some small tweaks, although it is currently untested.

Is this what people mean when they say "treeshaking"?

Maybe. 🤷

I found a bug!

Thanks for trying RefreshCSS out! Please make a PR (pull request) with a small test that replicates the bug or, if that is not possible, create a new discussion.

Node

Python

  • treeshake: I unfortunately could not get this to work on my local environment.
  • cssutils: This unfortunately seemed to choke on more modern CSS when I tested on Bulma 1.0.
  • css-optomizer

🙏 Thanks

❤️ Support

This project is supported by GitHub Sponsors and Digital Ocean.

🥳 Contributors

Tobias Bölz
Tobias Bölz

💻 📖 ⚠️