Enter your search

Identify unused CSS [Improved]

By
Subtitle

Unused CSS Cleaner Upper

Thanks to Damian over at http://level0.ch/ for bug fixes and feature additions. The original script was written quickly and was intended for simple usage, but he has kindly taken the time to extend the functionality of the script and provide the world with an even better utility!

Improvements include:
– output prefixed with “.” respectively “#” to distinguish classes and id’s
– support for multiple html / css pages (as in larger projects) added, use a comma-separated list as “page” parameter
– added an optional parameter “visual” which will make the script print the evaluated css and html to the browser window.

I’ve fixed a few bugs with his new code and am continually expanding this script to include more functionality, so check back for more up to date versions!

CLICK HERE to reveal the rest of the code


<?php
/********************************************************************
* GoSquared ltd.                                    |css_checker.php *
* Authors: Main code by Geoff http://www.gosquared.com               *
* Extended by Damian http://level0.ch/                               *
* Adapted to OOP by Geoff                                            *
* Date: 10/07                                                        *
* Version: 1.2.0                                                     *
*--------------------------------------------------------------------*
* THIS SCRIPT IS OPEN SOURCE AND MAY BE USED BY ANYONE. SUBSEQUENTLY,*
* THE AUTHORS ACCEPT NO RESPONSIBILITY FOR ITS USAGE NOR GURANTEE ITS*
* RELIABILITY. NONE OF THE AUTHORS STATED ABOVE CAN BE HELD RESPONSI-*
* BLE FOR PROBLEMS RESULTING FROM THE USAGE OF THIS SCRIPT           *
*********************************************************************/

class css_scanner{
    public $helptext = "<p>
        <h3>Identify unused CSS</h3>
        Main code: <a href="http://www.gosquared.com/liquidicity/archives/203">http://www.gosquared.com/liquidicity/archives/203</a> by Geoff<br />
        Bug fix & more: <a href="http://level0.ch/fileserv/csschecker.php.html">http://level0.ch/fileserv/csschecker.php.html</a> by Damian<br />
        Further development, bug fixes and additions by Geoff<br />
        <b>Usage:</b><br />
        <ul>
          <li>http://www.myserver.com/csschecker.php?page=index.html</li>
          <li>http://www.myserver.com/csschecker.php?page=http://www.another-server.net/index.html</li>
          <li>http://www.myserver.com/csschecker.php?page=index.html,about.html,download.html</li>
          <li>http://www.myserver.com/csschecker.php?page=index.html&visual=inline</li>
          <li>http://www.myserver.com/csschecker.php?page=index.html&visual=iframe</li>
        </ul><br />
        CSS Scanner will look for and scan any embedded or external CSS files in your HTML code.
          </p>";
    public $page_content = '';
    public $unused = array();
    public $multi_page;
    public $page;
    public $page_content_visual;

    function __construct($page){
        //$multi_css = explode(',', $css);
        if(empty($page)){
            echo "No page specified to scan" . $this->helptext;
            exit;
        }

        $this->multi_page = explode(',', $page);
        //$css_content = '';

        if(count($this->multi_page) > 1){
            $i = 0;
            $this->page_content = array();
            foreach ($this->multi_page as $page) {
                $this->page_content[$i] = file_get_contents($page);
                $i++;
            }
        }
        else{
            //$css_content .= file_get_contents($css);
            $this->page = $page;
            $this->page_content = file_get_contents($page);
        }

        if(is_array($this->page_content)){
            $i=0;
            foreach($this->page_content as $page_content){
                $this->page = $this->multi_page[$i];
                $this->page_content_visual = $page_content;
                $this->unused = $this->scan($page_content);
                $this->print_report();
                $i++;
            }
        }
        else{
            $this->page_content_visual = $this->page_content;
            $this->unused = $this->scan($this->page_content);
            $this->print_report();
        }
    }

    function scan($page_content){
        $i = 0;
        if(ereg("<style( *[n]*.*)>n*(.n*)*</style>", $page_content)){
            if(preg_match_all("/(@s*imports* (url(("|')?)?(("|')?)|("|'){1}).+("|')?)?)/", $page_content, $ext_stylesheets)){
                foreach($ext_stylesheets[0] as $stylesheet){
                    $css_content[$i] = preg_replace("/(@s*imports*)|(url(?(("|')?))|("|'){1}|)?("|')?;|(s)/", "", $stylesheet);
                    $i++;
                }
                $array = 1;
            }
            $inline_notused = $this->check_file($page_content, $page_content);
        }
        else die("No page styles, sorry!".$this->helptext);

        $unused = array('internal' => array(), 'external' => array());

        if(isset($array) && $array == 1){
            foreach($css_content as $css_file){
                $css = file_get_contents($css_file);
                if(!empty($css)){
                    $not_used = $this->check_file($css, $page_content);
                    array_push($unused['external'], array('css_file' => $css_file, 'external' => $not_used));
                }
            }
        }
        if($inline_notused != false){
            $unused['internal'] = $inline_notused;
        }
        return $unused;
    }

    function print_report(){
        echo "<h1>Report for page: ".$this->page.'</h1>';
        foreach($this->unused['external'] as $unused){
            echo 'CSS entries not used from external CSS file '.$unused['css_file'].':<br />';
            if(count($unused['external']) > 0){
            foreach($unused['external'] as $entry){
                echo $entry.'<br />';
            }
            }else echo 'None, good job!';
            echo '<br /><br />';
        }
        if(count($this->unused['internal'] > 0)){
            echo 'CSS entries not used from internal CSS code block:<br />';
            foreach($this->unused['internal'] as $entry){
                echo $entry.'<br />';
            }
            echo '<br /><br />';
        }
        if(isset($_GET["visual"]) && $_GET['visual'] == 'iframe'){
           echo "<hr><iframe src = "$this->page" width="100%" height="100%"></iframe>";
        }
        elseif(isset($_GET["visual"]) && $_GET['visual'] == 'inline'){
            echo "<hr>",
                $this->page_content_visual;
        }
    }

    function check_file($css, $page_content){
        preg_match_all("/.([a-zA-Z-_][a-zA-Z0-9-_]+)({|[s].*{)/", $css, $css_classes);
        preg_match_all("/#([a-zA-Z-_][a-zA-Z0-9-_]+)({|[s][^;]*{)/", $css, $css_ids );
        preg_match_all("/<[a-zA-z0-9][^>]*classs*=s*["'](.+?)["']/", $page_content, $page_classes);
        preg_match_all("/<[a-zA-z0-9][^>]*ids*=s*["'](.+?)["']/", $page_content, $page_ids);

        $clean_page_classes = array();
        $clean_page_ids = array();
        foreach($page_classes[1] as $s) {
            $classes = explode(" ", $s);
            foreach($classes as $class) {
                array_push($clean_page_classes, $class);
            }
        }
        foreach($page_ids[1] as $s) {
            $ids = explode(" ", $s);
            foreach($ids as $id) {
                array_push($clean_page_ids, $id);
            }
        }

        $not_used = array();
        foreach($css_classes[1] as $css){
            if(!in_array($css, $clean_page_classes) && !in_array('.'.$css, $not_used)){
                array_push($not_used, '.'.$css);
            }
        }
        foreach($css_ids[1] as $css){
            if(!in_array($css, $clean_page_ids) && !in_array('#'.$css, $not_used)){
                array_push($not_used, '#'.$css);
            }
        }
        return (count($not_used) > 0) ? $not_used : false;
    }
}

$scanner = new css_scanner($_GET['page']);
?>

I hope this helps you out!

You might also like: Some People Just Don’t Get Interfaces…, Download ANY file from ANY site using Safari, Love Colour? Love These..

You May Also Like

Group 5 Created with Sketch. Group 11 Created with Sketch. CLOSE ICON Created with Sketch. icon-microphone Group 9 Created with Sketch. CLOSE ICON Created with Sketch. SEARCH ICON Created with Sketch. Group 4 Created with Sketch. Path Created with Sketch. Group 5 Created with Sketch.