As a team we have decided on the BEM naming convention
We use:
a dash (-
) to join words
a double underscore (__
) to indicate a child element in a component
a double dash (--
) to indicate a modified version of a component
l-
to indentify a layout class
js-
to identity a class that is being used to bind javascript behaviour to
The reason to use such a naming convention is explained clearly in Philip Walton's CSS Architecture
CSS must not use id
or js-*
classes in selectors.
The js-*
class names are reserved for JavaScript-only use.
The example below includes a dedicated JavaScript utility class to which behaviour is bound. It is independent of any specific UI component.
<a class="js-show-profile" data-username="necolas" href="{url}">...</a>The HTML element has a .no-js
class which is replaced with .js
for browsers that js enabled
and pass our criteria for a browser that we want to provide javascript support for. This enables to provide different
styles for javascript and non-javascript experiences. .no-js
can be utilsed to prevent the javascript
version having to override the non-javascript version but does not have to be used.
We use CSS Lint to perform static analysis of our compiled CSS to enforce good practice. CSS Lint comes with predefined rules which can either be errors, warnings or ignored. Errors will fail the build and therefore require fixing. Warnings suggest that there may be an issue with the CSS so developers are expected to check warnings and confirm that they are ok to be used.
This is how we have our configuration file set:
css: errors: - important - known-properties - errors - duplicate-background-images - duplicate-properties - empty-rules - fallback-colors - font-faces - star-property-hack - import - ids - underscore-property-hack - shorthand - text-indent - vendor-prefix - zero-units warnings: - overqualified-elements - display-property-grouping - bar - regex-selectors - selector-max-approaching - font-sizes - floats - outline-none - qualified-headings - unique-headings - universal-selector - unqualified-attributes off: - adjoining-classes - box-sizing - box-model - bulletproof-font-face - compatible-vendor-prefixes - gradientsFor information about each rule check the documentation
This is the folder structure we use for organising our Sass files
├── base ├── components ├── layout ├── lib └── utilitiesAnd a selection of the files found inside these:
├── base │ ├── _default.scss │ ├── _fonts.scss │ ├── _forms.scss │ ├── _links.scss │ ├── _media.scss │ └── _typography.scss ├── components │ ├── _button.scss │ ├── _header.scss │ ├── _icon.scss │ ├── _lists.scss ├── layout │ ├── _common.scss │ └── _pages.scss ├── lib │ ├── _functions.scss │ ├── _grid.scss │ ├── _mixins.scss │ ├── _placeholders.scss │ └── _variables.scss └── utilities └── _utils.scssbase - base rules are the defaults. They are almost exclusively single element selectors but it could include attribute selectors, pseudo-class selectors, child selectors or sibling selectors. Essentially, a base style says that wherever this element is on the page, it should look like this.
components - components are the blocks that make up your page. The modular parts of our design. They should be built in such a way that they can be dropped into any page or layout. Components should define how they look, but not their layout or position
layout - layouts hold one or more components together and are responsible for positioning components.
lib - library of variables, functions, mixing and placeholders. They output no css until used.
utilities - utilities are reusable helper classes
basic.css.scss - This contains the basic styles present in the base folder and should work in all browsers including legacy browsers
enhanced_responsive.css.scss - This contains the enhanced and responsive styles and will only be used by browsers that understand media queries.
enhanced_fixed.css.scss - This contains a fixed width version of the enhanced styles of the website which is served to IE 7/8. It cIE 7/8 fixes are only included in this file.
To make variable names more understandable we use the convention category-some-name
. This is also great
for RubyMine as it can then auto-suggest available variables.
Example:
$color-green-primary $color-green-higlight$color-white
$color-black
$color-grey-primary
$color-green-primary
$color-green-secondary
$color-green-tertiary
$color-green-paler
$color-green-pale
$color-green-light
$color-green-medium
$color-teal-light
$color-teal-dark
$color-blue-light
$color-blue-medium
$color-blue-dark
$color-grey-pale
$color-grey-light
$color-grey-medium
$color-grey-dark
$color-bluegrey-dark
$color-bluegrey-medium
$color-bluegrey-light
$color-pink-medium
$color-pink-dark
$color-red-medium
$color-red-dark
$color-orange-medium
$color-orange-dark
$color-yellow-light
$color-yellow-dark
$color-site-bg
$color-green-primary
$color-text-default
$color-black
$color-text-icon
$color-white
$color-link-nav
$color-green-primary
$color-link-nav-visited
$color-green-secondary
$color-link-external
$color-grey-light
$color-table-heading
$color-white
$color-table-background
$color-green-primary
$color-table-background-alt
color-green-paler
$color-table-border
$color-grey-light
$color-list-bullet
$color-green-secondary
$color-list-yes
$color-green-secondary
$color-list-no
$color-red-dark
$color-button-default
$color-green-light
$color-button-default-border
$color-green-medium
$color-button-default-text
$color-black
$color-button-primary
$color-yellow-light
$color-button-primary-border
$color-yellow-dark
$color-footer-bg
$color-grey-pale
$color-callout-background
$color-green-pale
$color-action-item-heading
$color-white
$color-action-item-heading-bg
$color-grey-medium
$color-action-item-border
$color-bluegrey-light
$color-icon-open
$color-yellow-light