
PurifyCSS – Remove unused CSS - k8t
https://github.com/purifycss/purifycss
======
simonw
I've been looking into this kind of tool for a while, but none of them are
quite right for my purpose. I don't want a tool that spits out just-the-CSS-
that-is-used, I want a tool that shows me blocks of CSS that it thinks are NOT
used - ideally after I've loaded a number of different pages in a browser.

My use-case is for analyzing a large, existing website that has many years of
accumulating CSS, and getting a feel for which blocks of code can be safely
eliminated.

I'm pretty sure what I'm after needs a full-blown DOM to work effectively -
either with something like PhantomJS or even running as a Chrome Extension. So
far I haven't seen anything that fits the bill.

~~~
Zikes
I honestly think this needs to be a part of Chrome Dev Tools's profiler.
Already it's able to record sessions that persist across page loads, and
tracks what CSS selectors are applied and which properties are overridden. I
don't think it's much of a stretch to add a feature like this.

~~~
spanktar
+1 for something along these lines to be available in all vendor's dev tools!

~~~
WhiteNoiz3
Agreed! We need something that collects data from multiple pages as you browse
through and use your site. At the end it gives you a table of all your classes
that didn't match anything (with line number references to your css file).

------
geuis
I created and maintain Helium. [https://github.com/geuis/helium-
css](https://github.com/geuis/helium-css)

The problem with the PurifyCSS approach, like so many before it, is that you
cannot really do this accurately from the server. It has to be done in the
browser.

Helium is a dev tool. It takes a list of sample urls from the developer
because its presumed the engineer will be able to make the best choice as to
pages that represent all the aspects of their site.

It will work in any web page regardless of framework, because ultimately its
all just web pages.

Helium will find the actual style sheets loaded into each page, then at the
end of the scan give you an accurate and realistic report of the css selectors
that were not found anywhere in your site.

There are some minor limitations, such as the inability to test for user-
interactions with pseudo selectors like :active, :focus, :hover, etc.

~~~
jamesdelaneyie
As a designer that would love this tool for the speed and cleanliness factor
it would give, i have a few other Qs:

1\. Does it spit out a css file or multiple css file I can use immediately?
Can i actually amend a local document with it, or do I have to copy paste?

2\. Does it give any critique on poor selector methods? Definitely have a few
foolish ways of doing things that could be improved with a little bit of
"hey...stop that" feedback, in my work

3\. ??? PROFIIT

4\. Can it give me a few stats on the css to benchmark it? You're already
showing me the unused ccs selectors, can you present other data that you could
present to your boss and say hey...look at this, this is why it's worth doing
this stuff

5\. Known browser issues highlighted. "Hey! In IE8...that div ACTUALLY does
this". Also, heres how to fix it. Insta–contextual documentation. As I say
that I realise I'm asking for Clippy back in a way so I shall bow out.
Responsive design? worth thinking about...anyway!

Really interesting project! I'm going it use it this weekend and see how it
goes :)

~~~
geuis
It doesn't modify your css files. That's your job. It gives you a report of
unused selectors. It can't test pseudo selectors requiring human interaction.

------
namuol
Like most CSS tooling, this is a treatment for a symptom of an underlying
disease: the inherently global nature of CSS[1].

Rather than "blob" all your CSS together, and _then_ "de-blob" it, why not
build your CSS dynamically based on what components your app is using?

[1] I strongly encourage you to watch this talk:
[https://vimeo.com/116209150](https://vimeo.com/116209150)

~~~
bpicolo
Because it slows down your app by a relevant amount.

Edit: I see we're referring to inline styles instead of requirecss. In that
case, it's because code reusability becomes a pita and you bloat your JS.

~~~
Udo
There's another way besides inlining and requirejs. In cases where you're
doing server-side programming anyway, you can just have the server inject
view-specific <link> elements pointing to individual CSS files as needed -
augmenting the site's core CSS file. The downside is more requests to fetch
those files, but after the first time you can take advantage of the browser's
cache. As long as you keep the number of extra CSS files reasonable, this
method costs almost nothing.

A variant of this is where you compile one CSS file from many view-specific
ones beforehand. The advantage is it'll speed up things on the client side and
the programming overhead is relatively small if you're using something to
generate CSS anyway.

------
frandroid
This looks awesome. If it did a second run to look up where the CSS comes from
in my SASS and remove the SASS instead, that would be magical. :D

~~~
inostia
Couldn't you just add a Grunt task to purify the compiled SASS?

~~~
jonahx
This would miss the point. Sure, it would still lighten the css file
downloaded by the client, but it would do nothing to clean up the source file
developers work with and thus lighten their cognitive burden, which imo is
more important.

------
gpvos
Nice. But from the description, it apparently doesn't work if you construct
class names by string manipulation (like "item_" \+ (selected ? "selected" :
"")). Maybe you shouldn't do that anyway, though.

~~~
white-flame
Even worse, I've sometimes done things like

    
    
      $(...).addClass("bg" + getSomeClassIdentifier(obj))
    

Linking some string hanging off some runtime object to its CSS class usage
quickly runs into halting problem issues.

There are certainly some arguments to keeping class names as opaque magic
strings, but given certain levels of dynamic complexity and the lack of tools
like CSS class inheritance, naming policy is sometimes far cleaner and more
manageable.

Also, there is a minor concern about false positives. If you have a class
called "name" or something generic like that, the odds of that string
appearing in non-CSS usage your source code is fairly high.

------
Existenceblinks
I _think_ it shouldn't be too much code. For my rails project, I wrote a
simple shell script[1] to get all unused css classes and remove it my hand in
final step, to make sure i will not remove css classes that actually used (e.g
pre-define and use in future, overriding of third party css class)

The script basically does:

1\. Use REGEX match all css classes, `cat` into one place

2\. Read the class line by line and search in html,js files to see if this css
is used (even support #addClass from js)

2.1 it also supports several class adding styles e.g. class="abc", class:
"abc", :class=> 'abc' or even "xxx" class in this: class="abc xxx ijk"

2.2 People even do this in js: $modal.append($('<div class="modal-close-
icon"></div>')); and the REGEX can also detect this lol.

[1]
[https://gist.github.com/50kudos/3028fac585eda85aea9a](https://gist.github.com/50kudos/3028fac585eda85aea9a)

You can adapt my REGEX, and custom your directory where those css files are
in.

Simply copy the code and save into your filename.sh, and can run safely
because my script don't write any file of your project.

------
brightball
This setup is ideal IMO. Keep your existing files, like bootstrap, intact in
case you ever DO use them but integrate this into your deploy process to do
compression and minification prior to getting out to your server.

Workflow wise, this is a huge win.

------
joeyspn
Apparently it also has a gulp plugin: [https://github.com/purifycss/gulp-
purifycss](https://github.com/purifycss/gulp-purifycss)

(just in case you were also wondering) =)

------
cblock811
This could be really useful when I do a major refactor later this year.
Thanks.

~~~
mkagenius
Kind of funny. Although maybe true.

------
Brajeshwar
This is nice. Just in case, you might also like to look at the likes of
[https://github.com/giakki/uncss](https://github.com/giakki/uncss)

~~~
k8t
Yes! that is a great library. Unfortunately, that library does not
automatically detect the classes used in JS. So we thought we could give it a
try to make one that would detect classes used in JS by default

------
weinzierl
How do you do this for JavaScript? In Java I used a mixture of static
analysis[1] and code coverage[2] with great success. For JavaScript there seem
to be many (dead) coverage tools but nothing comparable to UCDetector.

[1] [http://www.ucdetector.org/](http://www.ucdetector.org/)

[2]
[http://www.eclemma.org/jacoco/trunk/doc/](http://www.eclemma.org/jacoco/trunk/doc/)

------
peterbe
I use a similar tool on my personal site (www.peterbe.com) It also inlines all
CSS but only does so with the selectors that are actually ever used.

Go to [http://www.peterbe.com/plog/mincss](http://www.peterbe.com/plog/mincss)
and click to view source. 120Kb of bootstrap excess baby!

------
mschuster91
What is the actual performance advantage gained in contrast to a simple
minifier?

Given today's CPU speeds, I think the only thing you can save with this tool
is bandwidth on mobile and even with this, the effort is not always worth the
resulting speed gains as mobile networks get faster and faster.

------
brokentone
The dynamic class allocation here looks really robust and amazing. Huge
concern in similar libraries.

------
JuanSoto
>Able to also detect dynamically-loaded CSS classes in your javascript.

Awesome! I worked with a tool like this that did not have dynamically loaded
classes in mind.

For people not sure on how to use this, I personally use tools like these when
working with a CSS framework.

------
prayerslayer
An alternative to this is symdiff
[http://symdiff.github.io/](http://symdiff.github.io/) (Disclaimer: I'm the
author).

The auto-remove part you would have to code yourself though.

------
kanakiyajay
Wrote a quick tutorial [http://grunt-tasks.com/grunt-purifycss/](http://grunt-
tasks.com/grunt-purifycss/) on how to use it with grunt and grunt-usemin

------
Cengkaruk
Cool. I will try later. I'm using UnCSS[0] with Gulp. What is the different
with UnCSS?

[0] [https://github.com/giakki/uncss](https://github.com/giakki/uncss)

------
Spidy88
Mobile developers dream tool!

------
welder
Would this work with [https://github.com/jaysonsantos/jinja-assets-
compressor](https://github.com/jaysonsantos/jinja-assets-compressor)?

------
dsernst
This is awesome and makes so much sense, great work team.

------
aaggarwal
This is a very handy tool. I have a question, would it be able to take
wildcard and recursive argument for filepath of HTML, JS? Thanks.

------
henryng24
AWESOME!! this is just what i was looking for!!

------
shogun21
When it says it works on single-page apps, does that mean ONLY single page
apps?

~~~
k8t
Thanks for giving a heads up. It works with all apps. We just put the emphasis
on SPAs. Updated readme for this

------
d4ncer
This is amazing.

------
sdtsui
Cool. Nice work!

------
cschep
super awesome.

------
milkworsethan
So basically it's a tool to remove the mess that we've created? Maybe we
shouldn't have done so in the first place.

~~~
psychometry
Do you also scorn at the existence of debugging tools because we should've
written the code correctly the first time?

