Want to get Lullabot article, videocast, and podcast announcements delivered right to your in-box?
Let us know your email address (we won't share it) and we'll let you know when anything exciting happens.
Dynamic CSS Files in Drupal
Dave Cohen's comment on Nick Lewis' recent post got me to thinking about the power of serving a dynamic CSS file. To quote:
I don't know why themes don't use PHP to define styles. I've started to define a style.php instead of a style.css. This way, I define all the colors near the top of the file, and use PHP to refer to the variables later.
You have to put this in style.php:
header("Content-type: text/css");
And this in your template.php (if using phptemplate engine):
theme_add_style(dirname(__FILE__).'/style.php');
That's a great trick. Using some variations on this trick, one could create a Drupal module/theme combo that would allow less technical administrators to modify style information through a form in the admin menu. Administrators could have a form where they could enter hex color codes for things like body background, links, hovering over links, block titles; font size for h1, h2, h3, etc.; alignment, border color and width -- all of these would be great for creating a quick, customized site without too much technical knowhow.
A more technical, but more flexible solution is to just allow users to edit the CSS in a textarea (a la Movable Type's template system). However, although I don't want to limit creativity, I still like the idea of a multiple choice and/or guided theme customization process.
Both of these methods have the advantage of being able to view changes immediately and therefore administrators can experiment with different settings easily. Stick in some pop-up color pickers, some image uploading, font-family pickers, and the ability to position things on the page and we'll really have something to offer non-developers who want to tap into the wealth of features offered by Drupal without feeling like they're getting a "canned" site.
Comments on this post will automatically be closed three months from the original post date.



RSS Feed



Comments
Yes, yes, but... then again... well...
I toyed around with the concept this summer. It works, however, it adds a new layer of organization (and therefore, another layer that require's my stupid head's attention -- which is in short supply believe me!) to the stylesheet. In theory, I guess your supposed to know what you are doing -- however, as I attempted to organize colors, I began to realize that the php css method becomes constricting in a way, and before I knew it I had 12 different colors strewn about the stylesheet that my brain couldn't possibily remember. Moreover, I would end up liking one color in one place, but not all the other places that I assigned the color variable -- then I'd add a new color to the variables, but completely change the color scheme.
Did I mention I sometimes get neurotic when I play with CSS?
Of course, I was just playing around, and am ADHD by nature. I wouldn't be in the slightest bit suprised if someone managed to figure out an organization of variables in a stylesheet that both made styling easier, and provided room for all those little tiny edits we always end up putting in our style sheets. I'm just pointing this out as a word of warning -- something to keep in mind as you go down the path -- for it is a path that must be explored.
regarding organization of colors
Here's a snippet from one of my stylesheets:
// primary '1'$c[1]['lest'] = '#ffc';
$c[1]['ler'] = '#fc6';
$c[1]['l'] = '#f30';
$c[1]['dest'] = '#900';
$c[1]['der'] = '#c30';
$c[1]['d'] = '#f30';
Explanation:
The array syntax may be a bit cumbersome, but the idea is I'm defining one of the color schemes (each theme could potentially have many of them).
The abbreviations 'lest', 'ler', and 'l' stand for lightest, lighter and light. 'dest' is darkest and so on.
That's what I'm experimenting with as a way to keep the colors straight in my head as I define styles later on. So when defining a style for a particular element I'll set the background to a dark color, and the foreground to a light one, or vice-versa. I create a similar array for shades of grey.
That's a scheme I'm experimenting with. Just wanted to share it.
coming soon
adrianR is working on this. he will talk about it at drupalcon in his themeing talk.
also, we had this feature in a great contrib module drupal 4.3 - http://cvs.drupal.org/viewcvs/drupal/contributions/modules/style/
don't get too dynamic
Hey that looked familiar!
I just wanted to warn against getting too dynamic. Remember that browsers tend to cache stylesheets. So when you make fancy updatable ones, warn users they will have to refresh caches to see changes.
Glad to see this idea catching on, even if if others thought of it long before I mentioned it.
This can be adjusted
You can custom set how long you want files to be cached by using header("Expires: ..."). And also, I think, but am not sure, that most browsers detect the php ending and do not cache the file.
You can put something like
You can put something like this to renew it every so often.
The below example would expires every 10 mins.
header("Expires: ".gmdate("D, d M Y H:i:s", (time()+600)) . " GMT");
a few reasons why this might not be done
1) CSS is easy to grok. A person looking at CSS will be able to change some basics very easily. No UI can beat that power
2) CSS is extremely powerfull. You simply can never ever capture that power in a UI (that is probably the reason that there are no desktop WYSIWYG CSS editors too)
3) PHP adds extra overhead. I use dynamically generated javascript in quicktags. But it requires drupal to load completely once for the page and once for the JS. This is a lot of overhead
4) how often does on *really* change the CSS? For me it is "often", but it is always done in a batch, not now some margins, tomorrow some lines. Even with the client sitting next to me, I can show the changes immediately by working over (s)ftp. And otherwise the Firefox webdeveloper plugin helps there.
I personally doubt that online style editing is as much needed. what we really need is good default themes/styles and much cleaner default code in Drupal. A simple effective theme takes only hours to develop, when you ave such a solid base.
A UI is not going to change this. The theme that can be altered with that UI has to be good in the first place. and when its good, its just as easy to simply edit a CSS file and change a few lines in there.
A way to implement an idea I've had
This seems a like a very reasonable way to serve CSS via Drupal. I was thinking of using private file transfers or one of the file transfer modules, but this seem conceptually simpler.
As to a cool use case I idea I had:
I've always thought it would be cool to use Eric Meyer's color blender in a dynamic setting.
For example, say I have 8 blocks in a column. I could blend between a foreground color (say orange) and a background color (say white) with 9 midpoints. Each sequential block gets a ".colorN" class, where colorN corresponds to the Nth blended color. Voila! My blocks blend into the background as they descend the page.
Of course a much less fun way of doing this would be to create a style sheet with a bunch of classes like .orange1of2, .oranage2of2, .orange4of8 etc. But this sounds lot less fun and I would have to update it whenever I pushed the limits of my blocks. ;-)
As to caching: what about creating a unique ID as the name for each newly generated style sheet? For example, an MD5 hash of the current time. Create a menu item (say 'themes/dynamicstyles') that takes an argument (the name of the style sheet). Store the ID in a styles_cache table with the session, and mark it dirty when the styles need to change. Create a new hashed-titled style sheet when the dirty bit is set and added it to the theme.
Of course, the devil's in the details.
-M
I have some code for this
Along with a very powerful javascript colour picker that steven wrote for us.
There was one modification i needed to make to core, and that was weighting stylesheets, as the overriding stylesheet needs to take over from the other stylesheet.
I also used phptemplate and just made a phptemplate_style(), which automatically makes style.tpl.php loaded when found.
Some things you should consider though :
Derivitive colours :
for simplicity, you don't want to let the user select all the colours. The simplest one that should be available by default is all colours selected should have lighter, lightest and darker , darkest monochromatic colours automatically generated for them.
Complimentary colours :
Be able to autmatically select different colour schemes based on mathematic formulas. This is the best way to get default colour schemes which work well (based on the colour wheel)
Image composition :
unless your theme is _incredibly_ simple, you will need some images. and those images need to keep track of the changes of the colours. So that the background can blend back in.
I spent a lot of time working with imagemagick, and putting together 'image composition recipes' , ie: changing the background fade colour of the header image of pushbutton when you change the background colour. I finally found a library for image magick written as a php library, but i couldn't get it working on OSX without recompiling php..
There are more interesting things for this , like
1) sourcing stock photos.
Be able to use flickr as a source of photos, by using a colorpickr database (http://www.krazydad.com/colrpickr/index.php?group=stock)
He did that by downloading all the images, and resizing them to
1px x 1px and saving the colour value to a database. We could do the same, and each time the module gets updated add a bunch of photos.
If you've seen flickr's avatar selecter, you could use that for cropping your photos too.
2) get colour schemes from images
upload a logo image, and it picks out the colours for your site itself.
3) live preview
this is all incredibly simple to make happen with a live preview, as you are changing the colours, the page changes right in front of you.
Another thing i wanted to see finished first is my revamp of drupal's layout / theme configuration system. To allow for flexibly switching between multiple styles, ESPECIALLY allowing each user to have a style selector for their own blog / site.
I designed this all with my site oasismag.com in mind. I want to have all the users on the site have their own domain / subdomain (mysite.oasisjournals.com) and have their own look and feel on there, but still use my markup and my style structure. IE: no horrible myspace like sites.
Love the idea
I've actually thought of this idea, but never actually implemented it. It would be great for colored themes in drupal, where the colors could be options in the theme options, but I don't think adding options to a theme can actually be done, as far as I know.
Dynamic CSS and browser detection
One benefit of using dynamic css is the ability to detect browsers and deliver customized style information without using css hacks or javascript detection that may be turned off. By getting the http headers, you can find the browser from the user-agent. It not only detects browser type (all of them, not just IE or Firefox), but version as well (helpful when detecting IE7 vs. IE6).
I add this at the top of my css doc:
<?php
header('Content-type: text/css');
$browser = array (
"MSIE", // parent
"OPERA",
"MOZILLA", // parent
"NETSCAPE",
"FIREFOX",
"SAFARI"
);
$info[browser] = "OTHER";
foreach ($browser as $parent) {
$s = strpos(strtoupper($_SERVER['HTTP_USER_AGENT']), $parent);
$f = $s + strlen($parent);
$version = substr($_SERVER['HTTP_USER_AGENT'], $f, 5);
$version = preg_replace('/[^0-9,.]/','',$version);
if (strpos(strtoupper($_SERVER['HTTP_USER_AGENT']), $parent)) {
$info[browser] = $parent;
$info[version] = $version;
}
}
?>
And add a conditional statement where you need to deliver different information to different browsers.
----------------------------
div#test {
width : 100px;
height : 100px;
<?phpif (($info[browser] == "MSIE") && ($info[version] == 7)) {
echo 'background : #F00;';
} else if (($info[browser] == "MSIE") && ($info[version] < 7)) {
echo 'background : #0F0;';
} else if ($info[browser] == "FIREFOX") {
echo 'background : #00F;';
} else {
echo 'background : #CCC;';
}
?>
}
------------------
Then you can use one stylesheet doc instead of one for each browser that displays css differently.
Here's an example: http://www.digitalbonsai.com/phpstyle.php
Dynamic CSS and browser detection
Something I've been using PHP based stylesheets is with browser detection. By reading the http headers you can determine both the browser and version being used, and it doesn't rely on Javascript that may be turned off since it works at the server level, not the client.
I've been using the following code to get the user-agent info:
<?php
header('Content-type: text/css');
$browser = array (
"MSIE", // parent
"OPERA",
"MOZILLA", // parent
"NETSCAPE",
"FIREFOX",
"SAFARI"
);
$info[browser] = "OTHER";
foreach ($browser as $parent) {
$s = strpos(strtoupper($_SERVER['HTTP_USER_AGENT']), $parent);
$f = $s + strlen($parent);
$version = substr($_SERVER['HTTP_USER_AGENT'], $f, 5);
$version = preg_replace('/[^0-9,.]/','',$version);
if (strpos(strtoupper($_SERVER['HTTP_USER_AGENT']), $parent)) {
$info[browser] = $parent;
$info[version] = $version;
}
}
?>
and when I encounter a situation where browsers interpret the style differently, I do the following:
--------
div#test {
width : 100px;
height : 100px;
<?phpif (($info[browser] == "MSIE") && ($info[version] == 7)) {
echo 'background : #F00;';
} else if (($info[browser] == "MSIE") && ($info[version] < 7)) {
echo 'background : #0F0;';
} else if ($info[browser] == "FIREFOX") {
echo 'background : #00F;';
} else {
echo 'background : #CCC;';
}
?>
}
--------
Here's a sample of it at work: http://www.digitalbonsai.com/phpstyle.php
theme_add_style deprecated
I now this post is old but i stumbled across it and noticed so I thought I'd make a note that
<?phptheme_add_style()
?>
<?phpdrupal_add_css()
?>
Just in case anyone is confused as I was when stumbling across this nice little tidbit.
Color Picker
Hi there,
I want to integrate a color picker like the one for Drupal on my site so that customers can choose their color themes for table headers, links ect...
Do you know where I can get a script like that?
it’s work gr8 thanks
it’s work gr8
thanks
CSS aggregation and PHP driven CSS
so how does this method work when you have css aggregation and caching turned on?