CSS Guidelines

Naming

We use BEM (Block Element Modifier) as a method for naming CSS classes.

A BEM class name includes up to three parts.

  1. Block: The outermost parent element of the component is defined as the block.

  2. Element: Inside of the component may be one or more children called elements.

  3. Modifier: Either a block or element may have a variation signified by a modifier.

If all three are used in a class name it would look something like this:

[block]__[element]--[modifier]

There is no such thing as block__element__element

<header>
    <nav>
        <ul>
            <li>
                <a>Some link</a>
            </li>
        </ul>
    </nav>
</header>

The code block above could for example be converted into following with BEM-style.

<header class="container">

    <nav class="navigation">

        <ul class="navigation__menu">
            <li class="navigation__item">
                <a class="navigation__link">Some link</a>
            </li>

        </ul>

    </nav>

</header>

And the following would be a good fit for SASS-code.

.container {  }

.navigation {

    &__menu {  }

    &__item {  }

    &__link {  }
}

Syntax and formatting

  • Four (4) space indentation, no tabs

See Tooling

CSS Ruleset

.selector {
    property: value;
}

Standard rules for writing CSS, SASS or similar language

  • each selector on its own new line;

  • a space before the opening brace ({);

  • the opening brace ({) on the same line as the last selector;

  • a space after the colon (:);

  • each declaration on its own new line;

  • each declaration indented by four (4) spaces;

  • a trailing semi-colon (;) at the end of all declarations;

  • the closing brace on its own new line;

  • long comma-separated property valuesβ€”such as collections of gradients or shadowsβ€”arranged across multiple new lines, making sure all values are indented at the same level as the first.

  • include a space after each comma in comma-separated values;

  • use double colons (::) for pseudo elements (eg. before, after, first-line) ;

  • a zero (0) length should not have a unit;

Good

.selector-1, 
.selector-2 {
        background-color: #fff; 
        background-image: linear-gradient(#fff, #000), 
                           linear-gradient(#000, #fff);
        box-shadow: 1px 1px 1px $dw-color-primary, 
                    2px 1px 2px 1px $dw-color-draft inset;
        color: rgba(0, 0, 0, 0.8);
        display: block;
        padding: 2px;
}

Not good

.selector-1, .selector-2
{
        background-color: #fff; background-image: linear-gradient(#fff, #000), linear-gradient(#000, #fff);
        box-shadow: 1px 1px 1px $dw-color-primary, 2px 1px 2px 1px $dw-color-draft inset;
color: rgba( 0,0,0,0.8 );
    display: block;
        padding: 2px }
}

Declaration sorting

Properties should be grouped and ordered consistently. General properties should be sorted alphabetically at the top of a block, and more specific properties should be grouped below.

Example:

.selector {
        color: #000;        
        display: block;
        font-family: var(--dw-font-family-base);
        font-size: 20px;

        width: 200px;
        height: 200px;

        position: absolute;
        top: 20px;
        left: 20px;
}

SASS specifics

  • New line between inherit selectors

  • Properties for selector at top followed by pseudo-class and then modifier

Example:

.selector {
        color: $dw-color-primary;
        display: block;    

        &:hover {
            β€” 
        }

        &--modifier {
            β€” 
        }
}

Naming convention in HTML

If we are building more complex or very specific components we can scope them with top components and use more generic names inside the top component to make it more readable and maintainable.

When building large or complex components it is recommended to scope generic child components inside a parent component, to avoid overly long class names.

<div class=”writer-plugin-name”>

    <div class=”login-component”>

        <div class=”login-component__header>
            <h2 class=”login-component__title”>
                ...
            </h2>
        </div>

        <div class=”login-component__content>
            ...
        </div>

        <div class=”login-component__footer”>
            ...
        </div>

    </div>
</div>

This makes it possible to structure the SASS file like this, which avoids leaks from any generic classes to the outside scope.

.writer-plugin-name {
    .login-component {
        &__header { }

        &__title { }

        &__content { }

        ...
    }
}

Multi-word names

All string in classes are delimited with a hyphen (-), like so:

Good

.page-header { }

.page-footer { }

.sub-content { }

Not good

.pageHeader { }

.pagefooter { }

.sub_content { }

State and sizes

State hooks

Certain styles are state based, for example

  • A navigation link may be in an active state

  • An accordion section may be in an expanded state

  • A drop down menu may be in a visible state

  • A third party widget may be in a state where it has finished loading

To keep things consistent and to reduce the cognitive load of having to come up with names for state hooks we should try to stick with a set list of common state hook names, for example:

  • is-active

  • has-loaded

  • is-loading

  • is-visible

  • is-disabled

  • is-expanded

  • is-collapsed

Sizes

The main naming convention for sizes:

  • tiny

  • small

  • large

  • huge

And occasionally for something really small or really big we use:

  • micro

  • mega

Example

.navigation {

        &--tiny { 
            padding: $padding-tiny;
        }

        &--small {
            padding: $padding-small;
        }

        ...
}

Things to avoid

The following code examples should only be used if necessary and would be best to avoid in most cases.

.module > .module-title { }

nav ul li { }

Using this syntax will make it hard to override any rules inside it. A better way is to use good class names with modifiers to override rules.

Tooling

Editorconfig

We use an EditorConfig file which enforces our indenting rules. The contents of the .editorconfig file should look something like this for scss and css files.

[*.{scss,css}]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true

More resources

Recommended reading:

Another very good resource and guiding for formatting and naming in CSS and SASS