Hey,
I don’t know how this is with you guys, but for me CSS is always trouble. First I start with a nice split up of files like:
design.css
layout.css
yii.css
fonts.css
I do a lot of inline comments and try to keep things together. But after a while it becomes a mess. For big projects, my CSS files end up from 500 line to even more. Maybe for you this is no problem, but what I like about the MVC is small files up to 100 lines max. Most of the time only 20 lines or less. It keep things clear for me. Also because every model and controller and views has there own directory and files.
So why not do this for CSS I thought after a new mess up disaster.
So now I got in my themes directory:
css
–design
----top.css
----content.css
----top_menu.css
----main_menu.css
----side_menu.css
----footer.css
–layout
----general.css
----content.css
----tables.css
----footer.css
----sidebar.css
–modules
----blog
------admin
--------admin.css
------blogger
--------admin.css
----user
------admin
--------admin.css
------user
--------profile.css
–yii
----cdetailview.css
----cgridview.css
----clinkpager.css
etc. etc.
This is just an example. But the bottom line is I’ve got a lot of very small CSS files now. When I have to look for something, I now exactly where to look and don’t have to scroll trough hundred of CSS lines.
But of course you don’t want to include them one by one. So I added a little Component that combines and minifies all these files into one CSS file:
protected/components/CssMin.php
class CssMin extends CApplicationComponent
{
public $minAllFilename = 'all.min.css';
public $path;
// Create minimized css file from all css files in given directory.
public function minimize()
{
$buffer = "";
$dir = new RecursiveDirectoryIterator($this->path);
$ite = new RecursiveIteratorIterator($dir);
$files = new RegexIterator($ite,'/^.+\.css$/i',RegexIterator::GET_MATCH);
foreach($files as $file)
{
if(basename($file[0]) != $this->minAllFilename)
{
$buffer .= file_get_contents($file[0]);
}
}
// Minimize.
$buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);
// Remove space after colons
$buffer = str_replace(': ', ':', $buffer);
// Remove whitespace
$buffer = str_replace(array("\r\n", "\r", "\n", "\t", ' ', ' ', ' '), '', $buffer);
// Write minimized css file.
$outputFile = $this->path.$this->minAllFilename;
$fwrite = fopen($outputFile,"w");
fwrite($fwrite, $buffer);
fclose($fwrite);
return true;
}
}
The performance seems to be no issue. I expected it to consume a lot of time, but it’s just a few milliseconds. But it would be stupid to do this for every request in production environment, so in my main layout view I’ve got:
if(DEV_MODE)
{
Yii::app()->cssmin->path = Yii::app()->theme->basePath.'/css/';
Yii::app()->cssmin->minimize();
}
Yii::app()->clientScript->registerCssFile(Yii::app()->baseUrl.'/css/reset.css');
Yii::app()->clientScript->registerCssFile(Yii::app()->theme->baseUrl.'/css/'.Yii::app()->cssmin->minAllFilename);
You can see that I include the reset.css file from my main css directory and that it’s not in the css directory of my theme. Because you have to call the reset.css first else it would mess up things. Of course I can also modify my CssMin class to grab certain files first and put the reset.css also into the theme css directory.
For me this works. Never have to search trough lines and lines of CSS saves me a lot of stress . What do you think about this? Is it a good approach, could I improve some things?
Thanks for reading.