Drupal.org Markup Guide

Events happening in the community are now at Drupal community events on www.drupal.org.
You are viewing a wiki page. You are welcome to join the group and then edit it. Be bold!

 

 

 

  1. Overview
    1. Purpose
    2. Scope
    3. Getting Help
  2. General Guidelines
    1. Templates
    2. Functions
    3. Structure and Semantics
  3. Drupal Microformats
    1. Headings
    2. Lists
    3. Menus
    4. Links
    5. Read More Links
    6. Buttons
    7. Tables
    8. Layout 101
    9. Layout Overrides
      1. Narrow Box

Overview

Purpose

This is a guide to marking up output in Drupal.org. It covers both theme layer and content layer output, although the major focus will be on theme layer markup and output.

Scope

The guide is not exhaustive. It is a high level overview and you should refer to more specific documentation for each site section or page (if it exists). Where specific documentation does not exist you will need to apply the guidelines and interpret them as best you can.

The main content of this guide is embedded in the Drupal Microformats section. These are simple patterns of XHTML that underlie, in one way or another, the markup used on Drupal.org.

Getting Help

Should you need help or advice in applying the guidelines you can:

  • Post an issue in the Redesign issue queue.
  • Ask in IRC #drupal-redesign.
  • Contact one of the Project Managers directly.(Provide contact information)
  • Attend the next Redesign Sprint.

General Guidelines

Templates

  • Where appropriate use a tpl file, as opposed to hard coding markup into custom functions.
  • Place a tpl override in the theme and use a blank tpl file in your module - this is primarily to ease the review process and have all tpls organized in one place.
  • Add Doxygen comments to each template explaining what it does, available variables and so on.
  • Inline comments should be added inside <?php ;?> rather than <!-- --> HTML comments, we don't want to print comments in the output.
  • Adhere to Drupal coding standards - in particular PHP in HTML, not HTML in PHP.

Functions

  • Use standard Drupal theme functions.
  • Avoid hard coding markup in custom functions.
  • If you need to put markup in a function build a themeable function OR follow the Drupal Microformats guide for marking up your output.
  • Add Doxygen comments to each function explaining what it does, available parameters and so on.

    The over riding points here are:

  1. Be consistent with markup and class names—the goal is to standardize the markup.
  2. Avoid special casing as much as possible.
  3. Document what you have done with comments.

Structure and Semantics

Its important to maintain the correct structure and wherever possible use markup that describes the content - in short this means using properly nested headings and default to POSH wherever you can.

As a simple rule of thumb:

If its a heading, use heading tags - don't skip heading levels and avoid improperly nested headings. Avoid using DIV's for headings and special casing CSS.

It its a list, mark it up as a list, e.g. use theme_item_list.

Avoid over use of DIV and SPAN tags, use more semantic POSH elements instead.

If you are unsure, check the Drupal Microformats section below first.

Do not use markup for presentation on - this is tempting when there are default styles for an element that fits your design requirement.

Validate your markup.


Drupal Microformats

Drupal microformats are small patterns of HTML to represent commonly published things. The basic concept is that most content can be marked up using one or more Drupal Microformats OR provide a starting point. The key-words here are "reusable patterns" and "consistent markup".

Most of the microformats are familiar patterns to Drupal themers—headings, lists, menus and so on. This guide outlines their usage and should serve as a guide to the principles of semantic markup on Drupal.org.

Each format includes HTML elements and the CSS class names (non-exhaustive) you can use to modify the presentation and other information to help you implement the format.

The concept is simple - we want consistent markup, so if you are wondering how you should mark something up then look here first. If you don't find what you need chances are you'll at least find a pattern to get you started.


Headings

The heading element is used to wrap what can be logically defined or identified as a title or heading. Drupal does a pretty good job of adding headings - whats important here is that we do not remove headings and that we properly identify output that should be a heading.

Sometimes it can be difficult to know when to use a heading and when to use something else - you will find more specific details about this in each section, in particular Lists and Menus. Additionally you will need to review the section specific guide for your section or page which may contain more detailed instructions for headings.

Heading may be removed from visual display, but they should not be removed from the source code. Removing headings breaks the semantics of the document and reduces the accessibility of Drupal.org. Instead headings can be hidden using the Drupal 7 class .element-invisible, which I propose be added to the theme.

Format Name
Heading Levels
Format Type
Heading
Markup Guide
<h1 id="page-title">Heading</h1>
<h2>Heading</h2>
<h3 class="chapter">Heading</h3>
Classes/id's
.h1, .h2, .h4, .h4, .h5, .h6 - see typography.css, these classes modify the look of the heading level.

#page-title - for the main page title.

Other classes:
.element-invisible (hides content, do not use display:none).

Use cases & notes
General Guidelines
  • Use headings for anything that looks or "feels" like a heading (or is in fact an actual heading).
  • Use headings to identify sections of content, i.e. headings in the main content area, node teasers, comments, blocks, navigation, lists, menus etc.
  • Use only one H1 heading per document, and use it for the document’s main heading.
  • If a document needs a heading before the main heading in the source order, for instance to identify navigation, start with an H2 heading.
  • Do not skip heading levels going downwards, i.e. do not go from H1 to H3, but going from H4 to H2 is fine (here H2 starts a new section).
  • Every menu and list should have a heading (hidden with .element-invisible where appropriate).

Specific Implementation Guidelines

  • Page title is always H1
  • Node teaser titles, Blocks, Menus and Links use H2 (Links heading should be contextually aware, see the Links section below).
  • Comments, Item lists use H3


Lists

Unordered and ordered Lists should be used to markup conceptually related content items - such as a group of links, bulleted items, a list of user names and so on. Lists should almost always have a heading. The only time a list does not need a heading is when its context is clearly evident from the content that precedes it.

Format Name
Item List
Format Type
List
Markup Guide
<div class="item-list">
  <[type]>
    <h3>Title</h3>
    <li>Item</li>
    <li><a href="">Item</a></li>
  <[type]>
</div>

[type] - UL, OL

Classes
UL .flat - Applies to the UL/OL element; removes bullets and indentation.
LI .first, .last - added to lists generated via theme_item_list.
API/Function
theme_item_list

Examples:

No title, UL list, class="flat":
theme('item_list', $items, NULL, 'ul', $attributes = array('class' => 'flat'));

Title (H3), OL list, no attributes:
theme('item_list', $items, t('List Heading'), 'ol');

Use cases & notes
Generated lists use theme_item_list.

Use the $title parameter as opposed to custom headings. This defaults to H3 and most times will be appropriate.

theme_item_list headings are not contextually aware (they don't know what the heading level above them is). We have to live with this.

Hard coded lists may use H2, H3, H4 etc depending on the heading structure and nesting, however this is likely to be a rare case where the heading level needs to be changed from H3 since lists are usually part of an article section or in a block which should have an H2 heading.

Hard coded lists should not omit or add markup unless it is required (for example when adding a .link-button as a list item).


Definition lists are less obvious and are often marked up incorrectly using tables or headings and paragraphs. Document lists should be used when there are "terms" with "descriptions". The node/add page is good example of the correct usage of a definition list. Drupals search results pages are another.
Format Name
Definition List
Format Type
List
Markup Guide
<dl class="[classes]">
  <dt>Definition Term</dt>
  <dd>Definition</dd>
</dl>

[classes] are optional.

Classes
Definition lists are rarely used, each list is special cased.

.definition - applies to the <dl> element; for the Documentation DL.
.search-results - applies to the <dl> element; search results pages.

Search $type classes
Each search type adds a unique search type class to the <dl> element.
.apachesolr_search-results - Apache Solr search results.
.user_search-results - User search results.
.drupalorg-results - IRC Nicks search results.

API/Function Two special cases:

theme_node_add_list
theme_search_results (never used, its empty, the HTML is in the tpl files).

Use cases & notes
Use a Definition List wherever you have lists of information that have:
 a) A unique Term.
 b) An associated definition.

If you find yourself using heading elements and paragraphs for lists of terms and definitions consider replacing it with a Document List.

Most Definition Lists should have a heading, such as H2.


Menus

There are potentially four types of menus that might appear in Drupal.org.

  1. Menus output via theme_links - primarily the menus coming from the drupalorg_crosssite.module.
  2. Standard Drupal menus
  3. Book module menus - primarily handbook navigation blocks
  4. Local tasks

In the following guides on Menus you will not see any wrapper DIV's (such as block code). There are no assumptions made about how a menu will  be added to Drupal.org, only the actual menu markup is presented here. Please see your section specific guides for more details.

Format Name
Menu Links (Menus output via theme_links)
Format Type
Menu
Markup Guide
<ul>
  <li class="[anchor-text-class] [classes]"><a class="[link-type] [classes]" href="">Anchor Text</a></li>
</ul>
Classes
li.[classes] - .first, .last, .active
a.[classes] - .active.
[anchor-text-class] - convert to lowercase, concatenate words with hyphens.
[link-type] - such as .nav-tab.

Note that there is no .links class on the UL.

API/Function
theme_links
Use cases & notes
Used extensively by the drupalorg_crosssite.module.
$nav_header, $nav_footer, $page_tools, $nav_masthead, $nav_content all use theme_links.



Standard Drupal menus and Book menus have identical markup so they are listed here together. This is stock standard Drupal output for menus. Most times these will be in a block, however there is at least one instance then they are not. If a book node has child nodes, the parent node will render a book menu with the child items on the parent node - you can view an example on the Accessibility section of the Drupal handbooks - http://drupal.org/node/464472. This menu is not wrapped in a block but rather the book module generates its own wrapper in book-navigation.tpl.php. We will discuss this further in the section on Templates, Layout and Boxes.
Format Name
Menu Menus (Standard Drupal menus)
Menu Book (Book module menus)
Format Type
Menu
Markup Guide
<ul class="menu">
  <li class="[classes]"><a href="">Anchor Text</a></li>
</ul>
Classes
[classes] - .leaf, .first, .last, .collapsed, .expanded, .active-trail
API/Function
menu_tree
menu_tree_output
theme_menu_tree
theme_menu_item
theme_menu_item_link
Use cases & notes
Normally output in a block (see block.tpl.php).



Book navigation links
are the menus links that allow us to navigate between book pages. Book menu blocks and the child item menus on book pages with child nodes are covered in the previous section. Book have a second navigation widget that prints Previous UP Next type links on book nodes.

This is included as a pattern here to show that a list of links does not have to be an unordered list - other structures are valid. Here this is perfectly fine, both structurally and accessibility wise, because this navigation is secondary to the main Book Menu Block that will appear on book nodes.

Format Name
Book navigation Link
Format Type
Menu
Markup Guide
<div class="page-links clearfix">
  <a href="" class="page-previous" title="Go to previous page">
    Anchor Text <span class="element-invisible">(Go to previous page)</span>
  </a>
  <a href="" class="page-up" title="Go to parent page">
    up <span class="element-invisible">(Go to parent page)</span>
  </a>
  <a href="" class="page-next" title="Go to next page">
    Anchor Text <span class="element-invisible">Go to next page</span>
  </a>
</div>
Classes
.page-links - applies to the DIV wrapper (this is in )
.page-previous, page-up, page-next - allow for granular theming of each link.

.element-invisible - to hide the content of the span tags from visual display. These are inserted to aid screen readers users understand where each link will take them.

Template
book-navigation.tpl.php
Use cases & notes
For consistency this template should be over-ridden the theme with the clearfix class replacing the standard clear-block class.



Local tasks are, well, local tasks, really just another version of an Item List/Menu list. The major difference is that they have two distinct levels - Primary and Secondary tabs, but the markup is identical for both except for the classes. bluecheese_menu_local_tasks overrides theme_menu_local_tasks and adds the very useful .parent-active class to the active Primary tab.
Format Name
Menu Local Tasks
Format Type
Menu
Markup Guide
<ul class="tabs [type]">
  <li><a href="">Anchor Text</a></li>
  <li class="[class]"><a href="" class="[class]">Anchor Text</a></li>
</ul>
Classes
[type]     - .primary, .secondary
li [class] - .active, .parent-active
a [class]  - .active
API/Function
bluecheese_menu_local_tasks (bluecheese/template.php)
Use cases & notes
Used only for Primary and Secondary local tasks.


Links

Links apply to any list of links output on nodes and comments, such as traditional $links, $terms and the new $sources variable for forum posts (and other lists as required).

This pattern in included because its the only pattern that I have proposed to have contextual headers.

Format Name
Node Links
Format Type
Links
Markup Guide
1) Standard markup.
<div class="node-[link-type]">
  <h[level]>Title</h[level]>
  <ul>
    <li><a href="" class="" rel=""></a></li>
  </ul>
</div>

2) With title hidden, no rel attribute.
<div class="node-[link-type]">
  <h[level] class="element-invisible">Title</h[level]>
  <ul>
    <li><a href="" class=""></a></li>
  </ul>
</div>

Classes &
Attributes
.node-[link-type] - applies to the DIV wrapper, such as .node-links, .node-terms.

<h[level]> - heading levels should be contextually aware to maintain proper nesting. The contexts are $page and $teaser. This can be implemented using a condition in preprocess_node, e.g. $level = $vars['page'] ? 'h2' : 'h3';

.[attribute class] - applies to the A element, such as .taxonomy_term_[tid]

rel - optional, normally used for terms, applies to the A element, such as rel="tag".

API/Function
theme_links
theme_links does not support insertion of a heading, these need to be added in template.php if theme_links is used. There is no requirement to use this function, but the markup should be emulated.
Use cases & notes
To be used for node:
  • Links.
  • Terms.
  • Sources (forum node type).
  • Versions (book node type).
  • Feature Tags (book node type).
  • Possibly Authors, Languages, and Alerts (book node type).

Titles may hidden using .element-invisible but not omitted.

Deprecates current implementations which uses SPAN elements such as theme_drupalorg_handbook_meta_link and the special casing in Bluecheese for sources, links and terms. For terms the Title is normally the Vocab Name.


Read More Links

Format Name
Read More Links
Format Type
Link
Markup Guide
<[type] class="read-more"><a href="" [attribute]>Anchor Text</a></[type]>

[type] - DIV or SPAN
[attribute] - optional, could be rel="nofollow".

Classes
.read-more - deprecates all other classes such as .all
API/Function
theme_more_link
Use cases & notes
Used on:

1) Node teasers - use type SPAN, attribute is rel="nofollow".
2) Get started (replaces the .all widowed anchors) - use type DIV.
3) Blocks if applicable (generally will conform via theme_more_link), uses type DIV.


Buttons

Link Buttons are the big green buttons as seen on the homepage behind the "Get Started with Drupal" link. Where you need to add a button like this follow this markup pattern.

Format Name
Link Button
Format Type
Button
Markup Guide
<a href="" class="link-button"><span>Anchor Text</span></a>
Classes
a.link-button
a.link-button span
Use cases & notes
This can safely be embedded in an item list or paragraphs tags, a div or any other block level element. Be aware that if the containing element is more than .grid-4 wide the button will break (the sprite will support buttons up to around 320px wide).

Tables

Most tables appear to be output via theme_table.

Format Name
Table
Format Type
Table
Markup Guide
<table>
  <caption></caption>
  <thead>
    <tr>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td></td>
    </tr>
  </tbody>
</table>
Classes
Class are added dymanically via theme_table and a bunch of other functions that genertate tables. There are many and you will need to be familiar with theming Drupal tables.
API/Function
theme_table - from here you can drill down into the API to find all the functions.
Use cases & notes
Tables are used extensively in Drupal, however they should only ever be used to markup tabular data. Tables should not be used to replace document lists or other more appropriate semantic markup.

If you can - add a caption, theme_table supports the addition of captions.

For hard coded tables please use a caption and follow the above markup guide.


Layout 101

These are generic examples of grid columns. You should see page.tpl.php for more examples. Its is shown here as an example of how to implement a grid column should you need to. This is not a guide on how to implement 960gs. You should refer to the 960gs documentation and study the bluecheese layout.css.

Format Name
Grid Columns
Format Type
Layout
Markup Guide
This is a simple example of 960gs grid layout, it uses most the the major tenants of the framework as it is implemented by Bluecheese.

This is a basic 3 column layout.

<div class="container-12"> <!-- container-12 is 960px with margin-left/right auto for centering -->
  <div class="grid-12"> <!-- grid-12 is 940px -->
    <div class="grid-4 alpha"></div> <!-- grid-4 is 300px, .alpha removes margin-right -->
    <div class="grid-4"></div>
    <div class="grid-4 omega"> </div> <!-- .omega removes margin-left -->
  </div>
</div>

All grids float left in LTR mode, and right in RTL mode.

Nested grids must use the .alpha and .omega classes to remove margins or the layout will break.

Remember, the usable horizontal space in 960ps is only 940px.

Note: this is almost the exact layout used in dashboard-page.tpl.php, v 1.3 - Bluecheese theme.


Layout Overrides

Strictly speaking these patterns do not override the 960gs layout, but I couldn't think of a better title.

There will be times when you need extra margin or padding for your content. There are two ways you can go about this:

1) Add padding/margin to your elements, such as headings, paragraphs etc.
2) Use a wrapper DIV and add your padding/margins to that.

You cannot modify the grid. It might be tempting to avoid the additional wrapper and instead adjust the width and margins of the grid. Do not do this, sometime, somewhere this will break the layout and adds special casing to the CSS, which we would like to avoid.

There is one pattern in the Bluecheese theme already that you can reuse to add extra padding and margin - .narrow-box is used on the Get Started page.

Narrow Box

Format Name
Narrow Box
Format Type
Layout override
Markup Guide <div class="grid-4">
  <div class="narrow-box">[content]</div>
</div>
Classes
.narrow-box - adds 18px padding and 18px margin-bottom.
Use cases & notes
Use when you need to create a box with extra padding and margin inside a grid column.

Mainly used on the Get Started page.

Drupal.org Improvements

Group categories

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: