Code Style Guide bridges the gap between framework and developer
The following document contains ruleset of writing both HTML and CSS code in SmartRecruiters. It's based on best practices and strongly relies on idiomatic CSS and HTML principles published by Nicholas Gallagher.
> Programs are meant to be read by humans
and only incidentally for computers to execute. **Harold Abelson and Gerald Jay Sussman** *Structure and Interpretation of Computer Programs, 1984*
Don't try to name classes to get more semantic code. Semantics is about elements only. Attributes should be sensible for other developers, not machines.
To avoid problems with performance, maintanence and entanglement in general, do not use nested selectors. What is more, it helps to avoid location dependency.
Use OOCSS and prefixed classes for different layers and behaviours in your code.
Use Modernizr to detect implemented features of the browser.
Important There is a grunt task to generate custom Modernizr build.
Width of block elements should depend on grid or parent element's width only. Never use width rule for block elements alone in your styles.
We use BEM methodology as a core of our naming convention to help us keep the whole frontend architecture consistent, strict, and easy to read and maintain.
However, we found much more efficient and easier to name BEM items as follow:
-
Block:
.foo
-
Element:
.foo-bar
-
Modifier:
.foo--baz
Use lower CamelCase if you need to write a class with multiple words.
/* Good */
.fooBar
.fooBar-baz
.fooBar--qux
/* Bad */
.foo-bar
.foo-bar-baz
.foo-bar--qux
.foo_bar
.foo_bar-baz
.foo_bar--qux
To avoid long, hard to read and maintain names of classes, keep only root block name in elements.
<!-- Good -->
<div class="rating">
<div class="rating-hedaer">
<h3 class="rating-title"></h3>
</div>
</div>
<!-- Bad -->
<div class="rating">
<div class="rating-header">
<h3 class="rating-header-title"></h3>
</div>
</div>
- Use four spaces for indentaction
Idiomatic rules
- 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"].
- 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.
Use EditorConfig plugin for your IDE to make sure you are using correct code formating settings.
EditorConfig website:
EditorConfig settings:
# editorconfig.org
root = true
# Common rules
[*]
indent_size = 4
indent_style = space
end_of_line = lf
charset = utf-8
tab_width = 4
trim_trailing_whitespace = true
insert_final_newline = true
# Matches the exact files either package.json or .travis.yml
[{package.json,.travis.yml}]
indent_style = space
indent_size = 2
/* ----------------------------------------------------------------
COMPONENT - Button
@date
@author
* ---------------------------------------------------------------- */
Use one blink line after and two before (if it's not a first line of the stylesheet) primary comment.
/* --------------------------
COMPONTENT Dependencies
* --------------------------- */
Use one blink line after and before (if it's not a first line of the stylesheet) secondary comment.
// Comment
Use one blink line before (if it's not a first line of the stylesheet) inline comment.
Avoid using vendor prefixes directly in selector rules. It will be added automatically during build process.
Keep in mind there is border-box layout model applied to all elements.
-
Use rems where possible. Do not write any fallbacks in pixels in your styles directly. It will be added automatically during build process.
To simplify calculations, use font-size: 62.5% on the root element (html, not body) what makes 1rem equal to 10px. -
Do not use unit with 0 values
/* Good */
padding: 0 10%;
/* Bad */
padding: 0% 10%;
padding: 0px 10%;
- Do not use unit with line-height
/* Good */
line-height: 1.5;
/* Bad */
line-height: 1.5rem;
line-height: 150%;
It's allowed to style IDs in edge cases, but only as a key selector.
/* Good */
#foo {
}
/* Bad */
#foo .bar {
}
#foo a {
}
To avoid problems with overriding helper classes, make their specificity higher by including #root
id added on body element.
Always keep styles related to each "module" in one place. All media queries should be nested inside selector.
/* Good */
.element {
@media (min-width: @breakpoint) {
}
}
/* Bad */
@media (min-width: @breakpoint) {
.element {
}
}
Idiomatic rules:
- Always use lowercase tag and attribute names.
- Write one discrete, block-level element per line.
- Use one additional level of indentation for each nested block-level element.
- Use valueless boolean attributes (e.g. checked rather than checked="checked").
- Always use double quotes to quote attribute values.
- Omit the type attributes from link stylesheet, style and script elements.
- Always include closing tags.
The only valid doctype is HTML5 Document Type Definition.
<!doctype html>
Do not serve different stylesheets for different browsers To target older IE, use conditional comments and specific classes as listed below.
<!--[if lt IE 9]> <html class="no-js oldie"> <![endif]-->
<!--[if IE 9 ]> <html class="no-js ie9"> <![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--> <html class="no-js"> <!--<![endif]-->
Use js-
prefix for JavaScript hooks.
Do not ever style js- classes in your stylesheet.
Use st-
prefix in IDs used for Smart Testing Framework hooks
Remember to use at least these landmark roles in your code:
- banner,
- complementary,
- contentinfo,
- main,
- navigation,
- search
Consider adding skipping links between long blocks of content
Use button element rather than a link with href="#"
as a hook for JavaScript interactions.
<div class="site site--home">
<header class="site-hedaer" role="banner">
<nav class="nav" role="navigation">
<ul class="nav-list"></ul>
</nav>
</header>
<div class="site-container">
<section class="main" role="main">
</section>
</div>
<footer class="site-footer" role="contentinfo">
</footer>
</div>