CSS Constants and Compression PHP Class
Published Tuesday, January 15, 2008 in CSS, PHP
I've mentioned my take on CSS-constants before but I haven't come around to actually creating the back-end needed, until now.
Download CSSCompressor and demo-files
The way I see CSS-constants differs a bit from what I've seen over the internet before, which is basically just about storing property-values in variables. That's all good and very basic to implement using any server-side language. What I wanted, tho, was a replacement for classes (CSS-classes that is), so this is how I see constants:
You define a constant the exact same way you style an element, only you replace the selector with a constant name instead.
Let's say we want to create a box that will be used by several different modules on the site. The normal approach would be to create a .box-class and apply that class to every element that should have that styling. That, however, requires you to give every element a class-attribute with the value 'box'. Exactly what I wanted to avoid in the first place.
Using my idea of constants you can skip all your classes and do it like this instead:
$box {
background: #fff;
border: 1px solid #333;
padding: 10px;
margin: 0 0 10px;
}
$box h2 {
background: #369;
margin: -10px -10px 10px;
padding: 10px;
color: #fff;
}
You can put that code anywhere in your .css-file, or you can keep all your constants in a separate file. It doesn't matter.
To use a constant, you simply go:
#recent-articles = $box;
#sub-content > div = $box;
What will happen now is that the parser replaces all constant definitions with the selectors you've selected to receive that constant's styling. Phew. Got that? Anyway, it doesn't matter.
Another nice use for this is the classic self-clear class.
Define it as a constant instead and you wont have to give every element that's going to self-clear a .self-clear class:
$self-clear {
_height: 1%;
*display: inline-block;
_display: block;
}
$self-clear:after {
content: ".";
display: block;
height: 0;
visibility: hidden;
clear: both;
}
And then:
#navigation ul = $self-clear;
#random-images ul = $self-clear;
#wrapper = $self-clear;
The reason I'm against classes is that they are often style-related (as in the self-clear case (and box for that matter)) and giving multiple elements the same class-names means that you will always have to style those elements identically. What if you don't want #recent-comments and #recent-articles to look the same in one design, but in the other?
Enough trying to convince you it's a top-notch idea :), get it here:
Download CSSCompressor and demo-files
Note that I am (like I often mention) no real back-end coder and the regular expressions can probably be improved on greatly so please feel free to do so in the comments.
The CSSCompressor Class is released under a GNU General Public License v3. I know nothing about licenses so just picked one. I hope it allows you to do what you wish except make money off it that I never see :)






Comments
17 comments so far, why don't you post one too?
Wednesday, January 16, 2008 | View all comments by Tobias
Is this free for use? It's very interesting and haven't the php nowledge to do this my self.
Keep it up!
Wednesday, January 16, 2008 | View all comments by Andreas
Absolutely, use it as much as you like. I should probably release it under some license tho...
If you, like me, have a style-switcher and all your styles are in something like /css/A_STYLE/ you can use this MOD_REWRITE rule to merge and compress all the files in a style-dir:
Obviously you'll have to check if $_GET['dir'] is set and, if so, use that in the constructor of the CSSCompressor.
And then link in the style with <link href="/css/A_STYLE/all.css" /> (don't leave out the mandatory attributes like I did for simplicity now =)
Also remember not to have a real all.css in any of your style-directories.
Wednesday, January 16, 2008 | View all comments by Tobias
I don't now why, but I can't get it to work. Can you describe a little closer on how the codes work toghether?
Wednesday, January 16, 2008 | View all comments by Andreas
Well all you need to do is, instead of including you normal css-file(s), include the file containing the code in the second PHP code-block in the article (the one that echo:es the packed code).
Place those two files wherever you want (CSSCompressor.php and the one containing the instantiation of a CSSCompressor class) and then specify your CSS-directory in the CSSCompressor constructor (new CSSCompressor('my-css-dir/')).
That's it.
You can use the mod_rewrite above if you still want it to look like you're including a pure CSS-file, and also have the ability to use a style-switcher.
You could also put the instantiation of the CSSCompressor class in the same file as the declaration of the same class. This way you'll only need one file.
If you want to do it all in one file, place the code from the second PHP code-block below the code in the first PHP code-block and then visit CSSCompressor.php and see what happens. If you get nothing then the directory probably doesn't exist or the path to it is wrong. Can be a good thing to always include $SERVER['DOCUMENTROOT'] when opening files instead of relying on relative paths.
Wednesday, January 16, 2008 | View all comments by Tobias
It just won't work. This is my structur
In styles.php I've got the code for creating the class(your second php code) and in styles.css I have the css code.
The error message I get when testing this is: Warning: preg_replace() [function.preg-replace]: Compilation failed: nothing to repeat at offset 7 in E:\Program\wamp\www\oneCSS_frame-work\css_compressor.php on line 110
Wednesday, January 16, 2008 | View all comments by Andreas
Hm.. that's odd. Haven't got a clue why that happens I'm afraid. Works fine for me (just tested it again).
The error seems to occur in the compress-method's preg_replace-call. That's the preg_replace that strips out comments. Should definitely work??
Is your CSS-file empty or something?
Wednesday, January 16, 2008 | View all comments by Tobias
Nope, and I gets the same message when it's empty(styles.css).
Couldn't you ".rar down" a working example? I will get back when I now what I did wrong...
Thursday, January 17, 2008 | View all comments by Ante
Working example up.
Thursday, January 17, 2008 | View all comments by Tobias
Now it's working :D thx. Is it ok to use this in my css framework(releasing it for public soon)? Of course you will get credits, but you should came up with some sort of licens....
Thursday, January 17, 2008 | View all comments by Andreas
Sure go ahead, I'm just glad if people use it.
I "released" it now under a GNU General Public License (v3) knowing nothing about it basically but just so it's done.
Friday, January 18, 2008 | View all comments by Tobias
One thing tho, if you define constants and don't use them, the compressor will still write them. As you can understand these will not be attached to any element, wich results in a error.
Friday, January 18, 2008 | View all comments by Andreas
Yea I know. I noticed that myself but the fix was rather complex so I couldn't be bothered.
No browser (I've tried) chokes on the invalid CSS so shouldn't cause rendering-issues. If you really don't want invalid CSS, don't define constants you don't use :)
Friday, January 18, 2008 | View all comments by Tobias
Oh ok, one other thing. How can I change so that the css declarations will not be name ordered, cause as it is now;
body { font: 12px Arial; } hml, body { font-family: inherit; font-size: 100%; }
My "body" will be overwritten...
Friday, January 18, 2008 | View all comments by Tobias
nope, that doesn't happend, just some wierd shit was going on at the moment.
Everything runs perfectly now, thx for the CSSCompressor and your kindly support...
Friday, January 18, 2008 | View all comments by Andreas
Sure, np.
The constant-parser will simply replace your constant definitions ($constant {, $constant h2 { etc) with the selectors you've applied the constant to (#selector = $constant).
This means that the styling of the #selector will not take place where the constant declaration is (#selector = $constant) but where the constant definition is.
Shouldn't really matter though. Just plan the specificity of your selectors beforehand and it shouldn't be a problem to override constant-stylings should you want to.
Sunday, February 24, 2008 | View all comments by Jrock
Download link no work? i'd like see how this works
Sunday, February 24, 2008 | View all comments by Jrock
nevermind.. you can delete these 2 posts.