CSS Guidelines

  1. Format
  2. Naming Conventions
  3. Commenting (NOT FINISHED)
  4. Sass specific
  5. Tooling (TODO)
  6. Further reading

1. Format

The chosen code format must ensure that code is: easy to read; easy to clearly comment; minimizes the chance of accidentally introducing errors; and results in useful diffs and blames.

.selector-1,
.selector-2,
.selector-3[type="text"] {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  display: block;
  font-family: helvetica, arial, sans-serif;
  color: #333;
  background: #fff;
  background: linear-gradient(#fff, rgba(0, 0, 0, 0.8));
}

.selector-a,
.selector-b {
  padding: 10px;
}

.selector-1 { width: 10%; }
.selector-2 { width: 20%; }
.selector-3 { width: 30%; }

.selector {
    background-image:
        linear-gradient(#fff, #ccc),
        linear-gradient(#f3c, #4ec);
    box-shadow:
        1px 1px 1px #000,
        2px 2px 1px 1px #ccc inset;
}

Declaration order

If declarations are to be consistently ordered, it should be in accordance with a single, simple principle.

.selector {
  /* Positioning */
  position: absolute;
  z-index: 10;
  top: 0;
  right: 0;

  /* Display & Box Model */
  display: inline-block;
  overflow: hidden;
  box-sizing: border-box;
  width: 100px;
  height: 100px;
  padding: 10px;
  border: 10px solid #333;
  margin: 10px;

  /* Color */
  background: #000;
  color: #fff

  /* Text */
  font-family: sans-serif;
  font-size: 16px;
  line-height: 1.4;
  text-align: right;

  /* Other */
  cursor: pointer;
}

2.Naming conventions

Components

The CSS responsible for component-specific styling.

Syntax: <ComponentName>[-descendentName][--modifierName]

We use a BEM-like naming convention., meaning Block, Element, Modifier, is a front-end methodology coined by developers working at Yandex. Whilst BEM is a complete methodology, here we are only concerned with its naming convention. Further, the naming convention here only is BEM-like; the principles are exactly the same, but the actual syntax differs slightly.

BEM splits components’ classes into three groups:

This has several benefits when reading and writing HTML and CSS:

ComponentName

The component’s name must be written in UpperCamelCase.

.MyComponent { /* … */ }
<article class="MyComponent"></article>

ComponentName–modifierName

A component modifier is a class that modifies the presentation of the base component in some form (e.g., for a certain configuration of the component). Modifier names must be written in camelCase and be separated from the component name by two hyphens. The class should be included in the HTML in addition to the base component class.

/* Core button */
.Button { /* … */ }
/* Default button style */
.Button--default { /* … */ }
<button class="Button Button--default" type="button"></button>

ComponentName-descendentName

A component descendent is a class that is attached to a descendent node of a component. It’s responsible for applying presentation directly to the descendent on behalf of a particular component. Descendent names must be written in camelCase.

<article class="Tweet">
  <header class="Tweet-header">
    <img class="Tweet-avatar" src="" alt=""></header>
  <div class="Tweet-bodyText"></div>
</article>

ComponentName.is-stateOfComponent

Use is-stateName or has-stateName to reflect changes to a component’s state. Normally used for javascript interactions. The state name must be camelCase. Never style these classes directly; they should always be used as an adjoining class.

This means that the same state names can be used in multiple contexts, but every component must define its own styles for the state (as they are scoped to the component).

.Tweet { /* … */ }
.Tweet.is-expanded { /* … */ }
<article class="Tweet is-expanded"></article>
<input class="Input has-error"></article>

Utilities

Low-level structural and positional traits. Utilities can be applied directly to any element within a component.

Syntax: <property>-<value>-[sm|md|lg]

property-value-size

Utilities must use a camelCase name. What follows is an example of how various utilities can be used to create a simple structure within a component.

<div class="clearfix">
  <a class="float-left" href="">
    <img class="display-block" src="" alt="">
  </a>
  <p class="fromSmallSize-textAlign-center fromMediumSize-textAlign-left"></p>
</div>

Responsive utilities

Certain utilities have responsive variants using the patterns: from<breakpoint>-<property>-<value>. For examle: fromMedium-textAlign-center.

Visibility utilities

Syntax: fromSmallSize-hidden or upToLargeSize-hidden.

Visibility classes let you show or hide elements based on screen size or device orientation. You can use visibility classes to control which elements users see depending on their browsing environment.

JS Hacks

Data-* attributes are used to bind the HTML to a JS Component. For example:

<div data-toggler>
</div>

3. Commenting

We need to create classes self explanatory, to not be necessary to explain the code. But at times the code is not enough.

Sass comments

We use Sass comments //, instead of CSS /* */. These comments will never be visible in the compiled CSS.

// This is my comment
.selector {}

If you want to display comments in the compiled CSS, you have to use CSS comments, type C.


/**
 * Images.
 */

img {
  max-width: 100%;
  height: auto;
  font-style: italic;
}

When do we use comments?:

At the beginning of a file:


//
// Button Component
// this is the description, if needed
//

At the beginning of a section:


.Component {
  ...
}

// Variations
//
// Variation
.Component--variation {
  ...
}

When you have to explain some line of CSS, when needed:

.selector {
  // why z-index is used?
  z-index: 3;
}

CSS Comments

CSS comments follows the Idiomatic CSS style guide :

/* ==========================================================================
   Section comment block
   ========================================================================== */

/* Sub-section comment block
   ========================================================================== */

/**
 * Short description using Doxygen-style comment format
 *
 * The first sentence of the long description starts here and continues on this
 * line for a while finally concluding here at the end of this paragraph.
 *
 * The long description is ideal for more detailed explanations and
 * documentation. It can include example HTML, URLs, or any other information
 * that is deemed necessary or useful.
 *
 * @tag This is a tag named 'tag'
 *
 * TODO: This is a todo statement that describes an atomic task to be completed
 *   at a later date. It wraps after 80 characters and following lines are
 *   indented by 2 spaces.
 */

/* Basic comment */

4. Sass specific

.selector-1 {
  @extend .other-rule;
  @include clearfix();
  @include box-sizing(border-box);

  &:hover {
    color:red
  }


}

Variables

Only create variables when it makes sense to do so. Do not initiate new variables for the heck of it, it won’t help. A new variable should be created only when all of the following criteria are met:

!default Flag

When building a library, a framework, a grid system or any piece of Sass that is intended to be distributed and used by external developers, all configuration variables should be defined with the !default flag so they can be overwritten.

$baseline: 1em !default;

Thanks to this, a developer can define their own $baseline variable before importing your library without seeing their value redefined.

// Developers own variable
$baseline: 2em;

// Your library declaring `$baseline`
@import 'your-library';

// $baseline == 2em;

Multiple Variables Or Maps

There are advantages of using maps rather than multiple distinct variables. The main one is the ability to loop over a map, which is not possible with distinct variables.

Another pro of using a map is the ability to create a little getter function to provide a friendlier API. For instance, consider the following Sass code:

$z-indexes: (
  'modal': 5000,
  'dropdown': 4000,
  'default': 1,
  'below': -1,
);

@function z($layer) {
  @return map-get($z-indexes, $layer);
}

5. Tooling (TODO)

Tools to help frontend development: linters (eslint, scsslint), .editorconf, documentation (sassdoc.doc)

6. Further reading