Drupal-Friendly Markup
As a programmer with absolutely no design skills, and markup skills that haven't quite made it into the web 2.0 era, I always collaborate with others when building a new site from scratch, or when embarking on a redesign or any substantial UI changes. Usually I act as the themer, transforming finished markup into a set of templates.
Getting Drupal friendly markup from the start makes the task of theming much, much easier.
The theme guide is a fantastic reference for those with a basic understanding of PHP. But if your markup partner doesn't program, or if they don't work on Drupal sites full-time, it's overkill.
This document contains the information from the theme guide that I think is most relevant for a markup expert who doesn't know PHP and doesn't have in-depth experience with Drupal, along with some practical examples of markup from this site.
Drupal Basics
It's helpful to define some terms, especially those that are relevant for theming.
- Page
- A full page, including persistent theme elements (header/footer), module-specific elements, and content
- Block
- A small block of content that may be reused on multiple pages is a block. Each block has a unique ids. Blocks are assigned to a region on the page, and can be restricted to appear only on certain pages.
- Node
- The main block of content on a page - like a blog post or a forum post - is usually a node. Each nodes has a unique id, which appears in the URL for the page containing that node.
- Content Type
- Each node has a content type. Page is usually used for static content. Story is usually used for blog posts.
- Module
- Modules can provide pages, blocks, and content types to a drupal site. Each module has a unique name.
- Path
- The URL for a particular page. A module usually inserts it's name into the path. For example, the forum module provides a page that lists all forums. The path for that page is /forum.
Templates
A page is built out of a number of template files.
- page.tpl.php is the main template, containing header and footer and includes for all the other template files
- block.tpl.php is a wrapper for block content.
- node.tpl.php is a wrapper for node content.
- comment.tpl.php is a wrapper for comments (replies to nodes).
- box.tpl.php is used as a wrapper for non-block content in a couple of places.
As an example, imagine a page with 3 blocks (header, footer, and navigation), a single node, and 5 comments. In this case, the markup in page.tpl.php will be included once, block.tpl.php 3 times (once for each block), node.tpl.php once, and comment.tpl.php 5 times (once for each comment).
CSS hooks
Drupal's default themes provide a ton of information in the id and class attributes. Module name, content type, node id and block id are usually assigned as ids of divs. The div that contains a node has class="node". The div that contains a block has class="block". The div the contains the content of a node or block has class="content".
Each form in the site has a unique name that is part of the form's id (for example, the user login form is id="form-user-login".
Various sub-parts of the node template (error messages, related links, breadcrumbs, etc.) have class names or ids.
Navigation menus, lists, and tables all have a standard set of classes and ids.
This allows one to customize layout based on all of the above criteria.
It's possible to write code to insert other information into a class or id attribute (username, logged in status, day of the week, whatever) in order to make it easy to change the layout based on whatever you need to.
Template Overrides
The template files can be overridden depending on the path, module, or unique id of the item being themed. The various templates have different options for override.
- page.tpl.php can be overridden by module. page-forum.tpl.php will be used for the forum module instead of page.tpl.php. page-front.tpl.php is used on the front page.
- node.tpl.php can be overridden by module or content type, for example page-story.tpl.php
- block.tpl.php can be overriden by module or by block id, for example block-search.tpl.php or block-1.tpl.php
It's possible to write code to override templates on other criteria.
Examples
These examples are all from this site and the abac theme that it uses. It's also helpful to look at drupal.org, which uses the core bluemarine theme (or something close to it).
Sometimes it's helpful to choose a base theme with your markup partner, so that an agreed upon set of classes and ids can be used by both parties. Sometimes it's enough for them to know the main drupal conventions, and that as long as they are consistent in their use of classes for layout-specific functions, it will be easy for the themer provide those classes in their templates.
Navigation Menu
<br><div class="headMenu"><br><ul class="links primary-links"><li class="first last menu-1-1-2-active"><a href="/blog/3" class="menu-1-1-2-active">Firebus's Blog</a></li><br></ul><br></div><br>
First and lass classes are provided, primary-links is the name of the menu block, the menu item (menu-1-1-2-active) describes the place in the menu system of this link, and its active status.
It would be nice to have active as a separate class!
Search box
<br><div class="search"><br><form action="/search/node" method="post" id="search-theme-form"><br><div><br><div id="search" class="container-inline"><br><div class="form-item"><br><input type="text" maxlength="128" name="search_theme_form_keys" id="edit-search-theme-form-keys" size="15" value="" title="Enter the terms you wish to search for." class="form-text" /><br></div><br><input type="submit" name="op" id="edit-submit" value="Search" class="form-submit" /><br></div><br>
The enclosing div with class="search" names the module.
The form has a unique id.
Form elements have class form-item, and each input element has a class the reflects input type and a unique id. So can style all form elements, all text inputs, or this specific text input, in CSS.
Node and various other bits
<br><div class="breadcrumb"><a href="/">Home</a> › <a href="/blog/3">Firebus's Blog</a></div><br>
Breadcrumbs!
<br><h1 class="with-tabs">Favorite Games</h1><br><ul class="tabs primary"><br><li class="active"><a href="/node/21" class="active">View</a></li><br><li><a href="/node/21/edit">Edit</a></li><br></ul><br>
Node title and tabs list (usually only privileged users have tabs for a node, although logged in users see tabs on user profile edit forms).
<br><div id="node-21" class="node"><br><div class="picture"><a href="/user/3" title="View user profile."><img src="http://twtitw.firebus.com/files/pictures/picture-3.jpg" alt="firebus's picture" title="firebus's picture" /></a></div><br><span class="submitted">Wed, 04/30/2008 - 11:46 — <a href="/user/3" title="View user profile.">firebus</a></span><br>
There's a unique id for this node, as well as a general class. If for some (bad) reason you wanted to style a specific node in CSS you can.
The next div is the user display with a picture, username, profile link, and date of submission.
<br> <div class="content"><br> ...<br> </div><br>
The actual content of the node, pulled from the database.
<br> <div class="clear-block clear"><br> <div class="meta"><br> <div class="terms"><ul class="links inline"><li class="first taxonomy_term_6"><a href="/taxonomy/term/6" rel="tag" title="" class="taxonomy_term_6">Games</a></li><br><li class="last taxonomy_term_3"><a href="/taxonomy/term/3" rel="tag" title="" class="taxonomy_term_3">Self-Reference</a></li><br></ul></div><br> </div><br> <div class="links"><ul class="links inline"><li class="first blog_usernames_blog"><a href="/blog/3" title="Read firebus's latest blog entries." class="blog_usernames_blog">firebus's blog</a></li><br> <li class="last comment_add"><a href="/comment/reply/21#comment-form" title="Share your thoughts and opinions related to this posting." class="comment_add">Add new comment</a></li><br></ul></div><br></div><br>
Links to categories, and links to add comments.
Comments
<br><div id="comments"><h2 class="comments">Comments</h2><a id="comment-207"></a><br><div class="comment odd"><br> <div class="clear-block"><br> <span class="submitted">Sun, 05/11/2008 - 23:36 — Anonymous</span><br> <h3><a href="/node/21#comment-207" class="active">you forgot one.</a></h3><br> <div class="content"><br> ...<br> </div><br> </div><br>
We've also got a general class and a unique id for comments.
There are some layout-specific classes like "clear-block", and we're providing odd and even classes in case you want alternating backgrounds.
<br><div class="links"><ul class="links"><li class="first comment_delete"><a href="/comment/delete/207" class="comment_delete">delete</a></li><br><li class="comment_edit"><a href="/comment/edit/207" class="comment_edit">edit</a></li><br><li class="last comment_reply"><a href="/comment/reply/21/207" class="comment_reply">reply</a></li><br></ul><br></div><br></div><br>
The comment also has some links
<br><div class="indented"><a id="comment-210"></a><br><div class="comment even"><br>
The next comment starts with indentation specified, as it's a reply to the previous comment.