How to Use Dynamic CSS in Your Joomla Extension

Something I have run into frequently during module development is the need to allow multiple instances of that module on a single page. Joomla!, of course, handles 99% of the work involved, but there are a few tricky aspects to making this work. One is the need to eliminate styling conflicts, especially in themed modules. If you only use generic classes and then load multiple theme/color stylesheets, the end result can be unpredictable to say the least.

	# Very simple module output from modules/mod_mymod/mymod.php
$color = $params->get('color', 'gray');
$css_file = $color.'css';

$document = JFactory::getDocument();
$document->addStylesheet('modules/mod_mymod/css/base.css');
$document->addStylesheet('modules/mod_mymod/css/'.$css_file);

echo "<div class='mymod_class'>";
echo "<p class='mymod_sub_class'>Here is some text that will go in this module.</p>";
echo "</div>";

The included stylesheets may contain declarations like:

	/* base.css */
div.mymod_class {
position:relative;
width:100%;
height:300px;
border:1px solid #000000;
}
p.mymod_sub_class {
font-style:italic;
}

/* gray.css */
div.mymod_class {
border-color:#dedede;
color:#7f7f7f;
}
p.mymod_sub_class {
color:#7f7f7f;
}

The above example code will work nicely for a single instance. The problem, however, shows up when you create a copy of the module and choose "red" as the color. When red.css is loaded, it will be identical to gray.css except for the color choices. The stylesheet loaded second (we'll say red) will override the first (gray) and both modules will inherit its styles. So, how do we solve this problem? The answer is with a dynamic stylesheet. We are going to use some simple PHP to differentiate between the module instances.

	# Very simple module output from modules/mod_mymod/mymod.php

# $module contains data about current module -- available automatically
$module_id = $module->id;

$color = $params->get('color', 'gray');
$css_file = $color.'css.php';

$document = JFactory::getDocument();
$document->addStylesheet('modules/mod_mymod/css/base.css.php?id='.$module_id);
$document->addStylesheet('modules/mod_mymod/css/'.$css_file.'?id='.$module_id);

echo "<div id='mymod_id_".$module_id."' class='mymod_class'>";
echo "<p class='mymod_sub_class'>Here is some text that will go in this module.</p>";
echo "</div>";
	/* base.css.php */
<?php
# Explicitly declare the type of content
header("Content-type: text/css");
# Grab module id from the request
$module_id = $_GET['id'];
?>
div#mymod_id_.mymod_class {
position:relative;
width:100%;
height:300px;
border:1px solid #000000;
}
#mymod_id_ p.mymod_sub_class {
font-style:italic;
}

/* gray.css */
div#mymod_id_.mymod_class {
border-color:#dedede;
color:#7f7f7f;
}
#mymod_id_ {
color:#7f7f7f;
}

If you are a little confused don't worry. First of all, we need a way to uniquely identify our module. Our module already has a unique database ID that can be accessed from the $module object. We can use that to generate a unique div ID. The trick is that we have renamed our CSS files to PHP files and passed them our unique ID through the URL.

The css.php files now contain a couple of lines that declare the content type and pull the unique ID from the URL. That value is then used throughout the stylesheet to construct the names of the unique div ID's. Let's say our $module->id is 47. Then, if you view your source code, some of the out put will look like this:

	<link rel="stylesheet" type="text/css" href="/modules/mod_mymod/css/gray.css.php?id=47" />
...
<div id='mymod_id_47' class='mymod_class'>
<p class='mymod_sub_class'>Here is some text that will go in this module.</p>
</div>
...
/* From gray.css.php */
div#mymod_id_47.mymod_class {
border-color:#dedede;
color:#7f7f7f;
}
#mymod_id_47 {
color:#7f7f7f;
}

If you create a second instance of the module, it may have a $module->id of 52. In this case, all the above code will be output again, except all 47's will be replaced with 52. If we choose the red theme for the second module, all the red styles will be specific to #mymod_id_52 just like all the gray styles were specific to #mymod_id_47. You can see that we were able to prevent the styles from conflicting by ensuring that each set of stylesheets applied to only a single instance of a module.

This technique is obviously not limited to Joomla! development. It can be used in many different situations, but I have found it quite helpful in Joomla! module development. This approach will also work for producing dynamic Javascript files, but we will save that for another day. The idea is basically the same. Have fun with this little tip. I hope you've found it helpful.