"Design 2.0" Coding Standards
The following are list of standards that should be adhered to when coding a "Design 2.0"-compatible website. This is a work in progress.
Naming Conventions
BEM
"Design 2.0" uses a CSS naming convention inspired by BEM. From that link: "It is a smart way of naming your CSS classes to give them more transparency and meaning to other developers. They are far more strict and informative, which makes the BEM naming convention ideal for teams of developers on larger projects that might last a while."
"BEM" stands for "Block Element Modifier." In BEM, everything consists of blocks (which are a design's big, high-level chunks), elements (which are the children of blocks), and modifiers (which modify the appearance or function of elements). It should be relatively easy to divine a core class' purpose, function, location, and ancestry from its name alone. Obviously, this won't always be possible, but those situations should be as few and far between.
Here's a simple example from "Design 2.0"'s forms component.
In "Design 2.0," each form field is contained within a form row, which is further broken down into containers for the field's label and controls. So, in BEM naming, each form row has a class of form-row
while the label and control containers have the form-row__label
and form-row__controls
classes, respectively. The double underscores (__
) indicate that those two elements are direct descendants, or elements, of the form-row
block.
Likewise, the form-row
block can be further identified by the type of form element(s) it contains (e.g., text field, radio buttons, checkboxes). If the form-row
block contains a text field, then the form-row--text
class is also added to the form-row
block. If it contains radio buttons, then the form-row--radio
class is added. The double hyphens (--
) indicate that those classes modify (or in this case, further clarify) the form-row
block's purpose. Here's the finished code for a text input form row:
<!-- BEGIN text field --> <div class="form-row form-row--text" id=""> <div class="form-row__label"> <label for="text">Form Label Goes Here</label> </div> <div class="form-row__controls"> <input type="text" name="text" id="text"> </div> </div> <!-- END text field -->
Note: A BEM class should not necessarily reflect the entire ancestry of an element. So, for example, you shouldn't write classes like form-row__controls__wrapper__radio-buttons
unless it really makes sense in that particular context. A BEM class should be kept to one layer of depth as much as possible.
CSS Recommendations
Comment, Comment, Comment
Good code is thoroughly documented code; you can never have too many comments. That being said, comments should be succinct and precise. As for formatting different comments and creating some sort of hierarchy, "Design 2.0" currently uses a variation of the approach found in Nicolas Gallagher's "Idiomatic CSS" guidelines.
Format Consistently
The following rules are the current recommendation for "Design 2.0"-compatible CSS:
- Never mix spaces and tabs for indentation. Preference is to use tabs with a length of 4 spaces.
- Remove all whitespace at the beginning and end of CSS files.
- Use one discrete selector per line in multi-selector rulesets.
- Include a single space before the opening brace of a ruleset.
- Include one declaration per line in a declaration block.
- Use one level of indentation for each declaration.
- Include a single space after the colon of a declaration.
- Use lowercase and shorthand hex values, e.g.,
#aaa
. - Use single or double quotes consistently. Preference is for double quotes, e.g.,
content: ""
. - Quote attribute values in selectors, e.g.,
input[type="checkbox"]
. - Where allowed, avoid specifying units for zero-values, e.g.,
margin: 0
. - Include a space after each comma in comma-separated property or function values.
- Include a semi-colon at the end of the last declaration in a declaration block.
- Place the closing brace of a ruleset in the same column as the first character of the ruleset.
- Separate each ruleset by a blank line.
- Regular class names should be delimited by hyphens, not underscores. So
form-row
is correct butform_row
is not correct. (An obvious exception here is the BEM naming schemes, where underscores are used for organizational purposes.) - Avoid qualifying your selectors -- e.g., don't put tag names in front of them -- unless absolutely necessary. In other words, write
.header
instead ofdiv.header
. This makes your CSS more portable and not tied to a single tag.
Note: The above rules apply to CSS you write, not to the final CSS that is actually used to render a client's site. The final, rendered CSS may be heavily minified/compressed to improve website performance, which means comments will be removed.
In general practice, write your CSS in a way that it could be reasonably understood by complete strangers today, tomorrow, or a year from now.
Use Classes for Everything
CSS should be applied with classes, not IDs. Since IDs can only be used once on a page, using classes insures that styles remain portable and easily recycled and reused. Also, IDs make specificity scores much higher than classes, which makes it harder to override styles if necessary.
IDs should only be used for JavaScript/jQuery hooks and for navigational purposes (e.g., jump links).
Similarly, inline styles should be avoided as much as possible.
The BEM naming convention (see above) should be used as much as makes sense when writing custom CSS classes.
Keep Your CSS as "Flat" as Possible
With CSS, it is possible to nest CSS selectors, e.g., .header ul
(which would affect all ul
elements that are descendants of the .header
element). However, this is not ideal for several reasons:
- It's not well-scoped. What if there's a
ul
element inside of the.header
element that you don't want to style? - It's unnecessarily specific. This means that it will be harder to override these default styles.
- It's not descriptive. At a glance, that rule tells you nothing about what the style is supposed to do, where it applies, etc.
If this style was for a site's main navigation, then a better selector would be something like .site-nav
. It's more precise and descriptive. Also, simpler selectors are more efficient for browsers to render, thus improving page performance.
Nesting CSS selectors is unavoidable, but it should be done as infrequently and as shallowly as possible.