Okay, so it seems that I was after either not existing or very hard to find, so I wrote a script that solves my specific problem. I insert it here in the hope that someone will someday find it useful.
<?php $css = file_get_contents('test.css'); //Strip comments and whitespace. Tabs to spaces $css = preg_replace("/\s{2,}/e", ' ', $css); $css = preg_replace("/\/\*.*?\*\//", '', $css); $css = str_replace("\t", " ", $css); $css = str_replace(": ", ":", $css); $css = str_replace(" }", "}", $css); $css = str_replace("{", "{", $css); $css = str_replace(";}", "}", $css); //Break each rule out onto a new line $css = preg_replace("/}\s*/", "}\r\n", $css); //Break @ rules out onto new lines $css = preg_replace('/(@.*?;\s*)/', '\0'."\r\n", $css); //Parse CSS Rules $parsed = array(); $css = explode("\r\n", $css); foreach($css as $line => $rule){ if (preg_match('/(.*?)\{(.*?)\}/i', $rule, $regs)) { $clean_selectors = preg_replace('/\s*,\s*/', ',', $regs[1]); $clean_selectors = preg_replace('/,\s*$|\s$/', '', $clean_selectors); $parsed[$line]['selectors'] = explode(',', $clean_selectors); $parsed[$line]['properties'] = explode(';', $regs[2]); } elseif(trim($rule) != '') { $parsed[$line] = $rule; } } //Group CSS by property $groups = array(); foreach($parsed as $line => $css){ if(is_array($css)){ foreach($css['properties'] as $pline => $property){ if(isset($groups[$property])){ $groups[$property] = array_merge($groups[$property], $css['selectors']); } else { $groups[$property] = $css['selectors']; } } } else { $groups[$line] = $css; } } //Output CSS sorted by property foreach($groups as $property => $selectors){ if(is_array($selectors)){ asort($selectors); echo implode(",\r\n", $selectors)." {\r\n\t".trim($property).";\r\n}\r\n\r\n"; } else { echo $selectors."\r\n\r\n"; } } ?>
Now a few folders.
No, this is not the most beautiful code in the world, it was done quickly to solve one specific problem that I once encountered, and it adapted very much to the CSS that I had to work with. However, it should be general enough to work with most of the CSS that you throw at it.
This is the nature of CSS, which is sometimes the order in which a rule appears, which is important for rendering the final document. It is likely that if you just run all of your CSS through this script, your page will not display as you expect. I just use this script to group page-specific CSS in a web application, I don't have layout control. Since each rule applies to a specific element on a specific page, I do not expect a huge amount of tricks when I group in this way - it just makes CSS more convenient.
source share