Open discussion on Drupal's themeing capabilities and templating engines.
[Editor's note: In the 8 years since this was written, all but a few of the links have rotted. To preserve the original sense of what is/isn't meant to be linked, these dead links have been changed to "example.com" rather than completely removed.]
I am in the process of designing a new approach to the themeing system currently employed by Drupal. But first I feel I might need to explain a bit about the approach I am leaning towards. If you are interested in Drupal themeing, I would greatly appreciate if you read the entire post, as I would like as much input about what I am planning, as to better try to help Drupal designers. This is a rather in depth post, but contains some insights into the new system I am currently developing.
I feel that most of what we consider a 'Drupal theme' at this stage, is too complex, and too rigid a framework for most web designers attempting to work with our platform. I propose we rethink the theme system as it currently stands to be a more generic templating system. Specifically , most of cruft in themes can be attributed to completely separate configuration settings and capabilities for each. This leaves us with a set of themes which are incompatible and different from each other, and if a designer wants a feature only another theme supports .. he is left with the choice of porting the feature to his current theme (not that easy for non programmers), or rebuilding his work on the new theme. The designer might even be faced with judgment calls regarding which set of features he would rather have.
I have been involved in Drupal themeing for quite some time, and one of my first in depth Drupal mini-projects was the phptal based theme chameleon (not to be mistaken for the new lightweight theme in Drupal core, Dries liked the name and used it for the new style based theme). As such , I have been thinking about the nature of Drupal themes for more than a year now. I have seen the system grow remarkably more robust in the lately, but there is still a lot of work that needs to be done to make it truly world class and very importantly .. designer friendly. Phptal was incredibly powerful, but had some performance issues (actually..because of it's architecture, it's likely to be a much better option come PHP5). Also.. due to the general nature of Drupal at the stage (it was printing , instead of returning, all theme() functions) it proved to be unpractical at the time.
The second part of the story takes place about *ponders* three months ago when I was contracted to do some modifications to marvin_2k (namely turning it into a hybrid layout. ie: tables for basic layout css for the rest). The theme was recently modified to use an incredibly simple pure php template library, which can be seen on cvs.drupal.org.
Also recently, the Drupal default theme xtemplate, had been given a secondary template, namely Pushbutton that could be used if desired(this template is great btw, kudos to megagrunt) , and the theme itself allows you to switch between templates. I personally feel that we are now more than one level too deep into the hierarchy .. in menu terms .. 'admin->configuration->themes->xtemplate'.
Nevertheless , my initial modification of marvin_2k led me to copy most of the template switching / setting code from xtemplate verbosely (This code is publicly available in the form of the PHPTemplate theme for Drupal 4.4.0) This made me uneasy about the fact that I was being forced to do this due to the structure of the code. In an attempt to try and minimize the duplication of effort, i spent an evening working on a new theme I called 'templates'.
The nature of my 'templates' work is as follows. A single theme, that is able to load any type of template, provided it has support for it. I accomplished this by separating all the cruft (ie: configuration screen, basic formatting of data (ie: the format of the date/username) and features like the avatar support new in 4.4.0) into the templates.theme , and then loading another 'glue library' for whichever template engine of my choosing. The extension of the template file you are attempting to load would act as the template engine glue library you would use. So, you would name your phptal template main.phptal , and that would force engines/phptal.inc to be loaded and used to process the actual displaying of the contents of the theme.
I actually progressed to the point of having xtemplate and the marvin_2k pure php templates natively supported, and a large amount of the work for smarty and phptal templates up and running before I realized the fundamental problem with the approach was that templates were still a few levels too deep, and the entire thing didnt make sense from a usability point of view. I then proceeded to make a pure PHPTemplate theme, (which is a branch of the original marvin_2k , but especially now is virtually indistinguishable apart from the mark up generated. The new version I will discuss in a moment will be out shortly, I am still implementing a lot of my intended functionality.). Since then I have been radically re-architecting the theme itself, to be as friendly to the user and designer as possible.
But once again, I ran into the familiar problem I had found before. Any templating system implemented in the form of a theme is just several layers too deep, and isn't allowed by the rigid nature of the theme api to fully shine through.
My proposition then is to build a generic template engine layer , and do most of the stuff that a .theme is currently handling, directly within the api. By creating a method for Drupal to generically load templates, we give access to a lot of designers who might only have experience with a certain api.
Personally I would like to target at least the following engines :
- Pure phptemplates
- Arguably the fastest and most robust method of doing templates. Sadly it is considered bad practice to force designers to use at least a little bit of php to accomplish their work, hence the abundance of template engines. This theme was created in the spirit of this discussion regarding the nature of templating engines. PHP also allows developers to use pull methodology.
- PHPTal
- Other than pure php, PHPTal is the only templating engine I would actively recommend to anyone. It is a php reimplementation of Zope Page Templates, and one of the distinguishing features of this engine, is that is uses the xml namespace mechanism to embed the template attributes directly into the static html document that the designer works on. I found an actual template I was using from during my chameleon development days. That is the actual template fed into the engine, however Drupal was not that theme friendly at the time. I have also converted already running websites to PHPTal+Drupal in about 20 minutes by simply taking the generated html and tagging it. The major drawback however is performance. If any template engine is ever to be called designer friendly however, PHPTal should actually be the only one on the list.(imnsho *g*)
- XTemplate
- The current Drupal template system of choice, and it should be supported for legacy reasons. An isotemplate (ie: single template file) API without conditional/recursive logic in the template.
- Smarty
- An incredibly popular and widely used templating engine, supporting it would be an incredible boon to the many users who prefer it above all others. There is a Smarty capable theme for the 4.2 era which could be used as a base for a glue library. It is an Isotemplate engine which has conditional logic and much more in the template language.
The back-end then would allow you to use all of these engines interchangeably. The idea would be that each of template engines would need to ship with at least one default template, that conforms to all of the features available in all templates. It might even be an idea to deliver exactly the same theme for all engines by default. Lowering the barrier of entry for designers wanting to work with what they feel comfortable with, and making it easy for new engines to be supported by developers.
Now, you may ask .. what about the current themes? Using the phptemplate system, it is easy to adapt any current (non template engine) themes to their own equivalent templates. A tricky part in all this is being able to override other functions (ie: theme("table") etc). There might need to be a supplemental php file within the template directory (completely optional for 99% of cases). We need to carefully consider what functionality we might be losing if we go this way. One benefit is that we have a single set up supported functions for all templates. All templates will be required to have both left and right columns , primary navigation customization, breadcrumbs and more. Luckily the nightmare of pre-4.4.0 themes not being able to switch to left, right or 3-column layouts without modification are behind us , but it still is nowhere near as centralized as it could be.
PHPTemplate
I am giving this a section of it's own , not because it is my baby, but because I am implementing a lot of the functionality now that I would like to be a central part of Drupal, available to all theme designers wherever. I am still not finished with the current development cycle, hence no release of the new theme. Several people have however made some nifty sites in just the last week or two using some demo code i have been selectively sharing for comments. (i have even gotten several patches back *g*)
Template selection
Template selection has been completely rewritten to allow contextual information for each of the templates. To make it as easy as possible to design new templates, instead of using the usual Drupal .template format, with _template hooks and the like. Information is configured via a simple text file. This allows users to copy the default template to a new directory , and make that template their own simply by changing the details in template.txt.
Each template can have a 'screenshot.png' and a 'screenshot_th.png' file which gives a small preview picture. This takes most of the guess work involved out of trying out a bunch of themes. Other Drupal core contributers might not agree with my belief that this is more user-friendly than simply displaying the name and description (as with theme selection).At the moment, one of the fields I have is 'Author', but objections have been raised regarding this. I am of the personal opinion (especially after some recent forum threads) that attributing layouts to designers will make more people eager to design templates for the contrib directory. Currently theme designers are practically invisible.
General template settings
When designing a new template or theme, there are certain things which will very likely be tweaked / modified by the site administrator. I have looked through other themes to see what configuration options they have, and put together a setting screen to avoid anyone having to modify a template unless it is specifically required. This would ideally be separated into a admin/templates/settings screen or the like, as these settings would form the master list of supported features a template would need to conform to.
An example of the configurability I am trying to reach would be the logo. If you do not specify an alternate logo, the theme/phptemplate/templatename/logo.png file is used. I further want to allow users to upload their logo via fileapi. Being able to display custom messages on the front page, and configurable navigation (currently only primary navigation, apart from drupal.org .. i do not know if there are many other practical implementations of it. at least I have always found it superfluous).
I will also try to see the practicality of one of the more often requested template hacks, namely selecting which node types to display the date/posted by information on. Designers should not have to modify the template to allow something as simple as this to happen
Approach to stylesheets
One of the interesting (and not widely known) parts of the Marvin_2k theme, was it's practice of using a 'custom.css' file , if such a file existed. The idea behind this was people should be allowed to create their own overriding css rules, without needing to modify the theme itself, thus making future upgrades a nightmare.
I am building functionality into the templates settings to modify the contents of custom.css if it is writable. This will hopefully allow wholesale customization for anyone who has a Drupal site. If your logo is higher than the space attributed for the header, you can add additional positional css to make it fit, once again .. without modifying the original template, or having to mess with the files in the directory.
The new default template for the theme is designed to be a 'clean slate' for css designers to work on. Even though marvin_2k has some of the best markup generated by any Drupal theme, most of the time spent customizing it is disabling the look and feel of the default theme. This attempts to cut that time down to a minimum, and allows us to document the classes/id's and the like of the default template for template designers.
I hope to approach the stylesheet problem in such a manner as to make stylesheets the most practical solution to almost all of the customization that needs to be done , and ONLY if a change to html generated is absolutely required would they need to make their own template. What , prey tell , is the practicality in this you may ask? Well .. it's simple. Default will be maintained directly with the template engine, and as such will almost never lag behind with any improvements. Creating your own template when it is not completely necessary complicates the upgrade path and makes maintaining the site more work than it could be.
I have actually got a more extensive approach to handling stylesheets in mind for the future, but I do not want this discussion to revolve around that, but I am adamant that one of the basic requirements for a contributed template would be supporting custom styles.
Some people might feel that CSS only design is not the right tool for this job, but the system allows them to create their own templates. In any case CSSZenGarden is a shining example of the power of CSS.
Push/Pull Hybrid
Drupal uses a 'push method' of populating the template. Basically, Drupal (the engine) decides what the theme/template needs to display and the template generally does as expected. Many people have noted that MoveableType uses Pull methodology, where the template contains certain tags that 'pull' the data required from the engine. Because you are using pure php to write your templates, and are not limited to the basic {values} of , for example Xtemplate, you have a lot more freedom as a site designer.
The simplest example would wanting to add a random quote (as generated by the quotes module to the footer of your site. To accomplish this in xtemplate you would need to modify the template by adding a quote block, and {quote} variable. You would then need to modify the xtemplate.theme file to 'push' the quote into the template. The resulting change might leave your xtemplate theme incompatible with other xtemplates (because they lack the quote block)
To accomplish this in PHPTemplate you would simply need to add
<span style="color: #000000"><span style="color: #0000BB"><?php<br></span><span style="color: #007700">print </span><span style="color: #0000BB">quotes_get_quote</span><span style="color: #007700">(); </span><span style="color: #0000BB">?></span></span>
to the required place in your template.
This feature is used in the mobile template for PHPTemplate
Examples
Regrettably I don't feel very comfortable releasing the theme to the public at large yet, but there have been several sites launched on the beta code of the new version
- Oasis Magazine
- The reason I started using Drupal. I finally am able to run the site I want to be running thanks to the new theme. Apart from a modification to the node template (adding the cactus image), it is completely done with modifications to the css of the original marvin_2k. It still has some semblance (the main nav css rollover for instance) , but I feel it has been customized successfully.
- Oasis Magazine - Mobile Edition
- The most pertinent example to why being able to 'Pull' is useful. Mobile is a much simplified template I wrote that cuts down as much unnecessary content as possible, to allow mobile devices to read the content, without having to try to keep up with the real site. The mobile version of Oasis is accomplished by a few lines of code in the oasismag.com.php configuration file. These lines set the template to mobile, and the base_url to mobile.oasismag.com, should the request come from mobile.oasismag.com. Furthermore, I have purposefully not printed the blocks found on the normal Oasis (they are passed to the template, but completely ignored) , and use pull methodology to print only the user login / navigation screens , depending on the user's logged in status. This is a very simple modification to a template that has a very real benefit. I plan to ship mobile by default with PHPTemplate, so more Drupal sites will hopefully be made more accessible for mobile devices.
- Daemon.co.za
- My personal home page, and one of the first sites to use PHPTemplate. Originally based on Xtemplate Tableless circa Drupal 4.2, I decided to port the stylesheets to the default template, and as such exists almost completely in a few css files and a new logo.png. Currently it is a separate template because the default template was in flux when I was doing this.
- Partyfashion.net
- The first public phptemplate site I am aware of. It was created by Ber Kessels a few days ago. It features a unique method of 3 column display, I am unsure however whether it is done using css or actual html modification was involved. Best you ask him
- Chiquechick.com
- A site based mostly on 'default' , that was customized in a few minutes (according to Ber, about 20 or so) to use a custom logo image, and adjusting the stylesheet to take that into account. This is an example of the site that could be configured without leaving your web browser, directly from the template configuration screen's ability to modify custom.css.
- Default template- screenshot
- A small screenshot of the default look and feel. It isn't finished yet (almost though) , but I hope that it will be used as the basis for many sites. Like I said , it's as clean as It is , to make it a canvas for the designer.
- Bluemarine and Pushbuton template screenshots
- In order to benchmark/compare xtemplate to phptemplate, I took 30 or so minutes to convert the default templates to the new theme. This should give us a better idea of the actual performance of the theme, plus .. it might allow people who have developed XTemplate based themes to switch if they so desire
Believe it or not, the examples are simply the first results of using php as a templating engine, One of the major problems at the moment is that phptemplate doesn't do isotemplates, and there are a few file_exists() checks and other things that need to be optimized a way
There are several actions I am expecting from this post (if it doesn't get completely ignored that is), firstly.. Dries or Unconed are going to complain about some inane spelling or grammatical error .. or even better .. Drupal not being Capitalized... somewhere. I've learned to live with that.
Secondly, I expect quite a few people to have the reaction of 'i can make themes fine'. I can understand the view of those people, since I have gotten the hang of Drupal themeing over the last 18 months myself. I am however not your typical designer who wants to use Drupal but lacks the knowledge to make it work. What I want to do is lower the bar , to allow designers to come to grips with the capabilities of Drupal easier. The Install system is only one part of this, but it's an important start.
Lastly , I expect that people who would benefit from such a system would welcome, and have meaningful input into what I am proposing here. If you have an opinion, or there is something you feel would add to this proposal, please reply. Everyone's voice will be heard at the very least.
The implementation details at this point aren't the most important, I am however confident I could get it all up and running .. but a change this vast is going to need more than just my spare cycles and eyeballs. Especially considering the amount of time I will be spending on finishing the install system in the next few weeks. I can already understand however that the configuration and and actual running of the template system will need to be separated, and the configuration only be loaded when strictly required. It should be possible to improve memory usage and execution speed doing this. Also, Dries doesn't want to make things too complex, which is exactly right. Anything that gets proposed needs to be discussed and designed in such a way as to allow for the system to be as simple as possible, but no simpler. It is a design concern, I do assure you.
Sincere apologies for the severe length of this manifesto. There simply wasn't much I could leave out while still painting the whole picture, and the phptemplate section (as i said) is to demonstrate some of the concepts I would like integrated. Even if no one ever uses it, and it gets locked out of core. I fully intend PHPTemplate to be the last theme I ever need, but I really hope it will be useful for others.