Some months ago, when the Zend_CodeGenerator_* component got into the stable release of Zend Framework, I spent some time creating a code base for CSS generation by extending the abstract classes delivered with that component. I wanted to implement all features of the CSS 2.1 specification – and it seems to work pretty fine!
Here is a (quite large) PHP code snippet, which demonstrates the “API”. I tried to make as flexible as possible:
$f = new My_CodeGenerator_Css_File(array(
'media' => array(
My_CodeGenerator_Css_File::MEDIA_SCREEN,
My_CodeGenerator_Css_File::MEDIA_PRINT
),
'selectors' => array(
new My_CodeGenerator_Css_Selector(array(
'element' => '*',
'properties' => array(
new My_CodeGenerator_Css_Property(array(
'name' => 'margin',
'value' => new My_CodeGenerator_Css_Value(array(
'value' => 0
))
)),
new My_CodeGenerator_Css_Property(array(
'name' => 'padding',
'value' => new My_CodeGenerator_Css_Value(array(
'value' => 0,
'important' => true
))
))
)
)),
new My_CodeGenerator_Css_Selector(array(
'element' => 'body',
'properties' => array(
new My_CodeGenerator_Css_Property(array(
'name' => 'fontFamily',
'value' => new My_CodeGenerator_Css_Value(array(
'value' => array('Verdana', 'Arial', 'sans-serif'),
'separator' => ','
))
))
)
)),
array(
'element' => 'h1',
'class' => 'meine-h1',
'properties' => array(
array(
'name' => 'color',
'value' => 'red'
)
)
),
array(
'id' => 'content',
'properties' => array(
array(
'name' => 'width',
'value' => array(
'value' => 1024,
'measure' => My_CodeGenerator_Css_Value::MEASURE_PIXEL
)
)
)
),
new My_CodeGenerator_Css_Selector_Multiple(array(
'selectors' => array('h1.foo', 'h2', 'h3'),
'properties' => array(
new My_CodeGenerator_Css_Property(array(
'name' => 'color',
'value' => '#000'
))
)
))
)
));
echo $f;
The output of $f looks like this:
@media screen, print {
* {
margin: 0;
padding: 0 !important;
}
body {
font-family: Verdana,Arial,sans-serif;
}
h1.meine-h1 {
color: red;
}
#content {
width: 1024px;
}
h1.foo, h2, h3 {
color: #000;
}
}
To make it clear: it almost doesn´t matter which kind of data is used to generate the output. It could be strings, arrays or objects of my classes. I´d like to introduce them in short:
- File: a container for n “Selector” objects. It is also possible to pass an array of media types, for example “screen” and “print”, to support both.
- Selector: the CSS selector, which may be almost anything: an HTML element (h1, p, div, …), an ID selector, a class selector, a pseudo-class like “:hover”, an attribute selector like input[type=text] or even a combination of those. It is also possible to combine multiple selectors to one object…:
- Selector_Multiple: a container for n “Selector objects”, which will then be separated by a comma sign. Just as you write them in your CSS files.
- Property: an object which represents one css attribute/property, whatever you call it. So this might be ‘font-family’, ‘width’, ‘float’, … a “Property” object knows the correct CSS naming. If you pass “FontFamiLY” as the name – it will be filtered (yeah, Zend_Filter component) to “font-family”.
- Value: this is the corresponding value to the previously explained “Property” class. A “Value” object always belongs to a “Property” object. Basically, it consists of the passed value itself and an optional predefined measure, which may be “px”, “em”, …
There is one problem: I don´t know which way is the best, to read the generated CSS at a later time to modify it and re-save it again, … maybe a simple hash per selector/line, … Any suggestions?
Actually, I don´t know if this makes any sense to anyone. If it does, please leave a comment. I then still need to figure out a nice UI I think :S Maybe this will be in the ZF some time :)
Hi Timo,
sieht sehr gut aus…hat die Ausbildung ja doch ganz gute Früchte getragen ;)
Mach weiter so und alles Gute.
Robert
Moin,
gib mir maln use-case dafür :)
Gruß,
Chris.
ein schicker editor in form einer kleinen web-applikation für leute, die keine ahnung von CSS haben und dann quasi eine preview-funktion bekommen könnten, von dem, was sie über die eingabemasken verzapfen :)
An sich n super Kommentar, aber kannst du im nachsten Post n bisschen detaillierter schreiben?