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:
- Be consistent with markup and class names—the goal is to standardize the markup.
- Avoid special casing as much as possible.
- 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: |
| Use cases & notes |
General Guidelines
Specific Implementation Guidelines
|
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": Title (H3), OL list, no attributes: |
| 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 $type classes |
| API/Function | Two special cases:
theme_node_add_list |
| 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.
- Menus output via theme_links - primarily the menus coming from the drupalorg_crosssite.module.
- Standard Drupal menus
- Book module menus - primarily handbook navigation blocks
- 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. |
| 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:
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 |
| 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". |
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 --> 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. |