Last updated February 22, 2013. Created by xjm on December 5, 2012.
Edited by JohnAlbin, nicxvan. Log in to edit this page.
- Status
- Draft. Drupal core (HEAD) should adhere to the latest conventions revision.
- Links
-
CSS coding standards issues
Drupal core "markup" component issuesOriginating groups.drupal.org discussionInitial proposal by Nick Lewis
Table of Contents
- Planning CSS
- Use Appropriate File Conventions
- Remove Assumptions
- Reduce Selector Specificity
- Don't Use IDs in Selectors
- Don't be afraid to change markup
- Start with Stark and cross browser test
- Write Valid CSS
- Comments
- Right-To-Left
Planning CSS
Use Appropriate File Conventions
CSS should be moved to separate files, using the following name spacing conventions based on their purpose:
- module.base.css
- Should hold structural and behavior related styling. CSS should be coded against the Stark theme. The absolute bare minimum CSS required for the module to function should go here. If there is no CSS required, this file should be omitted.
- module.theme.css
- Should hold generic design-related styles that could be used with Stark and other themes. It's where all design assumptions like backgrounds, borders, colors, fonts, margins, padding, etc, would go.
- module.admin.css
- Should hold styles that are only applicable to administrative pages.
To see an example of this in practice, look at Drupal's system module.
Remove Assumptions
Styles that make too many assumptions, introduce superfluous margins, padding and add things like font settings are not necessary and don't belong in core module CSS files. In cases where core themes depend on these properties, they should be moved to the CSS stylesheet of the respective theme.
Reduce Selector Specificity
CSS code that resides in modules should be written in a way that's easily overridden in the theme layer. To improve the Themer Experience and make core CSS more efficient, CSS selectors should be made as general and short as possible. For example:
- Use
.style {}overdiv.style {}where possible. - Use
.module .style {}overdiv.module div.somenestedelement .stylewhere possible.
Don't Use IDs in Selectors
Use of ID's in core CSS selectors requires more specificity in the theme layer, making it harder and more annoying to deal with. It makes achieving consistency in complex design implementations much harder than it needs to be. We need to stop making life hard for theme developers.
Don't be afraid to change markup
Don't be afraid to change markup: There's lots of overlap between using proper and semantic markup and doing CSS right. If you come across a case where CSS is being applied where using a more semantic elements would solve the problem, then change the markup in your patch to make it right. For more information, see the Drupal 8 Markup Gate rules.
Start with Stark and cross browser test
Start with Stark and cross-browser test.
- "Design" markup and CSS for the Stark theme.
- If applicable, adapt the styles to match the core themes afterward.
- Finally, test the changes in all supported browsers and ensure no regressions are introduced.
Write Valid CSS
All CSS code should be valid CSS, preferably to CSS 2.1. CSS 3.0 is acceptable too, provided the usage can be justified and the principles of graceful degradation / progressive enhancement are followed.
Concise terminology used in these standards:
selector {
property: value;
}Selectors
Selectors should
- be on a single line
- have a space after the previous selector
- end in an opening brace
- be closed with a closing brace on a separate line without indentation
.book-navigation .page-next {
}
.book-navigation .page-previous {
}
.book-admin-form {
}A blank line should be placed between each group, section, or block of multiple selectors of logically related styles.
Multiple Selectors
Multiple selectors should each be on a single line, with no space after each comma:
#forum td.posts,
#forum td.topics,
#forum td.replies,
#forum td.pager {Properties
All properties should be on the following line after the opening brace. Each property should:
- be on its own line
- be indented with two spaces, i.e., no tabs
- have a single space after the property name and before the property value
- end in a semi-colon
#forum .description {
color: #efefef;
font-size: 0.9em;
margin: 0.5em;
}Alphabetizing Properties
Multiple properties should be listed in alphabetical order.
NOT OK:
body {
font-weight: normal;
background: #000;
font-family: helvetica, sans-serif;
color: #FFF;
}OK:
body {
background: #000;
color: #fff;
font-family: helvetica, sans-serif;
font-weight: normal;
}Colors (especially hex values) are preferred to be in lowercase.
Properties with multiple values
Where properties can have multiple values, each value should be separated with a space.
font-family: helvetica, sans-serif;CSS3 Properties, Vendor prefixes, progressive enhancement
- Order all properties alphabetically.
- Group vendor-specific with their respective standard CSS3 properties.
- Order vendor-specific properties alphabetically.
- Declare vendor-specific properties before standard properties.
- Declare potentially unsupported values after known to be supported values (progressive enhancement). (see CSS spec)
The special case of filter: should be grouped with ms-filter: and ordered before it (as in above example).
Vendor specific extensions may cause browser inconsistencies when declaring CSS3 before the standard has reached recommended status (a.k.a. finalized). Do not take for granted that a -vendor-xyz-property is and works the same as the final xyz-property.
It is recommended to avoid features of proprietary vendor extensions that are not supported by CSS3 standards.
.progressive-enhancement {
background: #000 none;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#E5000000,endColorstr=#E5000000);
background-color: rgba(0, 0, 0, 0.9);
}
.progressive-prefixes {
background-color: #003471;
background-image: -webkit-gradient(linear, left top, left bottom, from(#003471), to(#448CCB));
background-image: -webkit-linear-gradient(top, #003471, #448CCB);
background-image: -moz-linear-gradient(top, #003471, #448CCB);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#00003471,endColorstr=#00448CCB);
background-image: -ms-linear-gradient(top, #003471, #448CCB);
background-image: -o-linear-gradient(top, #003471, #448CCB);
background-image: linear-gradient(to bottom, #003471, #448CCB);
}
.vendor-prefixes {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
-moz-box-shadow: 0 3px 20px #000;
filter: progid:DXImageTransform.Microsoft.Shadow(color=#000000, direction='180', strength='10');
-ms-filter: "progid:DXImageTransform.Microsoft.Shadow(color=#000000, direction='180', strength='10')";
-webkit-box-shadow: 0 3px 20px #000;
box-shadow: 0 3px 20px #000;
}Comments
In general, all comments should follow Drupal's common Doxygen formatting conventions to stay consistent with the rest of Drupal's code base. In areas, where those common conventions cannot be applied, we resort to the CSSDoc syntax (draft).
In line with PHP coding standards, block level documentation should be used as follows, to describe a section of code below the comment.
/**
* Documentation here.
*/Further details on the common comment syntax may be found in the Doxygen formatting conventions.
Shorter inline comments may be added after a property, preceded with a space:
background-position: 0.2em 0.2em; /* LTR */
padding-left: 2em; /* LTR */Right-To-Left
Drupal supports conditional loading of CSS files with specific override rules for right-to-left languages. For a module, the override rule should be defined in a file named <module>-rtl.css (e.g., node-rtl.css). For a theme, the override rule should be defined in a file named style-rtl.css. The rule that is overridden should be commented in the default CSS rule.
From node-rtl.css:
#node-admin-buttons {
clear: left;
float: right;
margin-left: 0;
margin-right: 0.5em;
}Rules in node.css which will be overridden if the rtl.css file is loaded:
#node-admin-buttons {
clear: right; /* LTR */
float: left; /* LTR */
margin-left: 0.5em; /* LTR */
}See also: http://drupal.org/node/132442#language-rtl
As a rule of thumb, add a /* LTR */ comment in your style:
- when you use the keywords, 'left' or 'right' in a property, e.g.
float: left; - where you use unequal margin, padding or borders on the sides of a box, e.g.,
margin-left: 1em;
margin-right: 2em; - where you specify the direction of the language, e.g.
direction: ltr;