Drupal Markup Style Guide

You are viewing a wiki page. You are welcome to join the group and then edit it. Be bold!

Discuss the Drupal Markup Style Guide

This guide is intended to tell all Drupal developers how to:

  • Create good HTML/markup
  • Create good base templates for themers to stylize
  • Create good CSS classes

This guide is not intended to tell Drupal developers how their applications should look -- that would be a design guide or an interface guide. This guide is only intended to explain the considerations how to create HTML, templates and CSS that are easy for a themer to deal with.
This guide will serve as a basis for creating patches to Drupal 7 that will standardize the HTML and CSS classes.


As a general rule: don't use the id attribute.

Unless you are absolutely 100% sure that your template file or theme function will only be called once per user-request, then your ID might cause the markup not to validate (the value must be unique to every other DOM element's id in the whole DOM tree).

That means, don't use the id attribute on templates of nodes and users and even common forms like search and login forms. Even if you include the object ID in the id attribute. You, as a developer, can not guarantee that particular node, form or user will only be on the page once. Remember that views and panels can pull lots of stuff into blocks and pages.

If you need an ID for javascript, consider refactoring the javascript to use a class. If that is not an option then run the id through a static incrementer so that it gets an indexing integer appended to it; #your-id-0, your-id-1, #your-id-2, etc. See how the zen theme does this with zen_id_safe(). (This function should really go into core for d7 -- search and/or open a ticket please someone. Please see also http://drupal.org/node/111719)


Remember that id of the id="" attribute stands for identifier, while class in the class="" attribute stands for classifiers. So CSS classes are just taxonomy terms for DOM elements!

Rules of thumb for module developers:

  • every div must have at least one identifying class.
  • most divs should have three;
    1. what object it contains, e.g. node/user/message/tree
    2. what variation/permutation/state of that object/markup it contains e.g. full/teaser/node-typ/apple-tree/collapsed
    3. a unique identifier, where appropriate; e.g. node-123/tree-456
  • The module-name should be a class on the root DOM element of each theme_*() function: class "tagadelic" on the div containing the tagadelic block, but not necessarily its descendants, which can be targeted using ascending elements' class/es.
    Use classes on containers, not on elements. /elv
  • use more classes if they provide a further classification that other classes have not covered, and are not inherited by ancestral DOM elements. (I wonder if this is necessary, when is a class not inherited? /elv)
  • the name of the theme token, vis, theme('foo') would be wrapped in a div of class "foo". (<- where? is a class on the body element enough? Is this really needed as website usually use only one theme?)
  • strings always make better identifiers than integers. (seems redundant with the "most divs should have three" rule)
  • it's better to have too many classes than not enough, as long as they have unique meaning not already defined or implied by other classes in the element or on of it's ascendants
  • elements that aren't divs usually follow the same rules as above -- with the exception of extremely explicit elements like <strong>, <em>, <p> etc. If they are used correctly then they normally wouldn't need any/many classes.
  • to indicate variation/state, use the class on the outermost element. ie: on a list of link use "active" on the <li>, not on the <a> (This is now the case in Drupal 6 core menus). (redundant with rule 3?)
  • if you can't think of a class for the div, then you probably shouldn't have a div for it. (However divs are usually useful to themers (better too many than not enough), so first try harder to think of a meaningful class.)

Examples: A div wrapping a teaser might have class="node teaser blog-node node-123". The apple tree in the example might have class="tree apple-tree ready-for-picking tree-456"

Check out the html5 spec for motivation as to what classes might be useful:

  • W3C working draft
  • IBM's article sums it up better than reading the draft could. Just looking at the example's will give you a good enough idea of what it's all about.
  • This view on the Working Draft might be useful.


Spans vs. Divs

Spans and Divs have default properties that you should bear in mind:

  • A span works in-line.
  • A div works as a block element.

In other words, spans can be used to affect styling of content without taking it out of its place in the flow (e.g., for targeting a phrase or piece of jargon within a sentence). On the other hand, divs operate as block elements by default, and thus are best used to define page content that should be handled as a block somehow distinct from its surrounding content (e.g., the node and block divs that are generated in core Drupal).

Use the regular mark-up before using a div or span

When you can avoid it, don't add a div or span to an element already defined in the mark-up. Instead, simply add a class or id, as appropriate (see above), to the existing element. For example:

<div class="foo-title"><h2>example</h2></div>

<h2 class="foo-title">example</h2>

<div class="foo-box"><p>example</p></div>

<p class="foo-box">example</p> [in this case if it's all in one paragraph]

<span class="foo-link"><a href="foo">example</a></span>

<a href="foo" class="foo-link">example</a>

If you're in doubt, put it in a div (and give it classes).

Don't leave content adrift on the page with no mark-up at all. Every chunk of html whether in a tpl file or a theme function should have a root DOM element. For module developers this is a div 95% of the time. In page.tpl.php it's the <html> element. (or <body>?)

<div class="stuff stuff-summary stuff-ID your-module-name ">
summary of your stuff here -->

Each chunk of cohesive html gets its own containing element.

<div class="stuff stuff-summary stuff-ID your-module-name ">
div class="stuff-name">This is some stuff</div>
div class="stuff-summary">
div class="stuff-description">Here is the stuff that I need to plant, grow and pick my apple tree</div>
ul class="stuff-items">
li>apple seeds</li>

Wrap dynamic values in sentences in inline element (span, strong, a).

<p>Posted by <a href="/user/123">Johnny Appleseed</a> on <span class="date yesterday">1 October 2007</span></p>

Leave out presentation formatting

In the interest of maintaining the separation of logic and presentation, and moving all formatting control to the theming layer, avoid using presentation mark-up like <b> and <i>. Not only are these deprecated tags, they force formatting that may not be appropriate in all contexts. Better to use <strong>, <em> or even <span> to provide handles to themers for distinct stylings.

Page structure

  • The site-title should use an <h1 id="site-name"> tag. No other element on the page should use that tag.
  • The page-title should use an <h1 class="title" id="page-title"> tag. No other element on the page should use that tag.
  • Sub-headings within the page's content body should use an <h2> tag.
  • Block titles should use an <h2> tag.


Before publishing your theme to Drupal.org validate your site:


Tables shall not be used for structure, only for tabular data output.

(Add more here)

See comments in Discussion about the Drupal Markup Style Guide