CSS Style Guide - BEM Approach

| Comments

I’m trying to maintain a living CSS style guide which helps as a self guide for me & to get insights from others. Most of the content is picked from Spatie CSS Guidelines & few from Chainable BEM modifiers

Feel free to drop on comments section about what you use and what you feel can be changed here.

Table of Contents

BEM

BEM — Block Element Modifier is a methodology that helps you to create reusable components and code sharing in front-end development. I use a slightly changed modifier naming convention(see below).

1
2
3
4
5
6
7
8
9
10
11
12
.component                            /* Component */
.component__element                   /* Child */
.component__element__element          /* Grandchild. PS. Avoid Grandgrandchild */

.--modifier                           /* Single property modifier, can be chained */

.h-property                           /* Helpers (eg. `h-align-right`, `h-margin-top-s`) */

.js-hook                              /* Script hook, not used for styling */

.items                                /* Use plurals if possible */
.item

.component and .component__element

1
<div class="menu"></div>
  • A reusable component, which can be shared between pages/modules
  • Children are separated with __
  • All lowercase, can contain - in name
  • Avoid more than 3 levels so that your html is not filled with lengther class names
1
2
3
4
5
6
<div class="menu">
    <div class="menu__item">
        <div class="menu__item__icon"></div>
        <div class="menu__item__name"></div>
    </div>
</div>

Be descriptive with component elements. Consider class="team__member" instead of class="team__item"

1
2
3
<div class="team">
    <div class="team__member"></div>
</div>

You can use plurals & singulars for readability. Consider class="member" instead of class="members__member"

1
2
3
<div class="members">
    <div class="member"></div>
</div>

.–modifier

1
<div class="button --rounded --active"></div>
1
2
3
4
5
6
7
8
9
.button {
    &.--rounded {
        ...
    }

    &.--active {
        ...
    }
}
  • A modifier changes only simple properties of a component, or adds a property
  • Modifiers are always tied to a component, don’t work on their own
  • Multiple modifiers are possible. Each modifier is responsible for a property: class="alert --success --rounded --large". If you keep using these modifiers together, consider a variation (see below)
  • Since modifiers have a single responsibility, the order in HTML or CSS shouldn’t matter

.h-property

1
2
3
4
<div class="h-align-right"></div>
<div class="h-visibility-hidden"></div>
<div class="h-text-ellipsis"></div>
<div class="h-margin-top-s"></div>
  • Prefix with h- helps identify easily that’s its a helper class
  • Reusable utility classes throughout the entire project
  • Each helper class is responsible for a well-defined set of properties.
  • It should be clear that these are not components

.js-hook

1
2
3
4
5
<div class="js-map"
     data-map-icon="url.png"
     data-map-lat="4.56"
     data-map-lon="1.23">
</div>
  • Use js-hook to initiate handlers like document.getElementsByClassName("js-hook")
  • Use data-attributes only for data storage or configuration storage
  • Has no effect on styling whatsoever

DOM structure

  • All styling is done by classes (except for HTML that is out of our control)
  • Avoid #id’s for styling
  • Make elements easily reusable, moveable in a project, or between projects
  • Avoid multiple components on 1 DOM-element. Break them up.
1
2
3
4
5
6
7
<!-- Try to avoid, news padding or margin could break the grid-->
<div class="grid__col news"></div>

<!-- More flexible, readable & moveable -->
<div class="grid__col">
    <article class="news"></article>
</div>

Tags are interchangeable since styling is done by class.

1
2
3
4
<!-- All the same -->
<div class="article"></div>
<section class="article"></div>
<article class="article"></div>

Class Visual Grouping

1
<div class="js-hook component__element --modifier helper"></div>

Visual class grouping can be done with … | …

1
<div class="js-news-click | news__item --blue --small --active | h-padding-top-s h-align-right"></div>

Code Style

Use stylelint to lint stylesheets. Configuration is done at custom .stylelintrc which extends stylelint-config-standard.

1
2
3
4
5
6
7
8
9
10
{
  "extends": "stylelint-config-standard",
  "ignoreFiles": "resources/assets/css/vendor/*",
  "rules": {
      "indentation": [2],
      "at-rule-empty-line-before": null,
      "number-leading-zero": null,
      "selector-pseudo-element-colon-notation": "single",
    }
}

Installation

1
2
yarn add stylelint
yarn add stylelint-config-standard

Usage

Most projects have a lint script (with the –fix flag) available in their package.json.

stylelint resources/assets/css/**/**.css --fix -r

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/* Comment */
.component {                      /* Indent 2 spaces, space before bracket */
    @at-rule ;                    /*  @at-rules first */

    a-property: value;            /* Props sorted */
    b-property: value;
    c-property: .45em;            /* No leading zero's */

    &:hover {                     /* Pseudo class */

    }

    &:before,                     /* Pseudo-elements */
    &:after {                     /* Each on a line */

    }

    &.--modifier {

    }

    &.--modifier2 {

    }

    /* Try to avoid */
    @apply ;                     /* Use only for variations */

    &__subclass {                /* Unreadable and not searchable */

    }

    h1 {                         /* Avoid unless you have no control over the HTML inside the `.component` */

    }

}
                                 /* Line between classes */
.component__element {            /* Separate class for readability, searchability instead of `&__element`*/

}

Folder/File structure

5 folders and a main app.css file:

1
2
3
4
5
6
7
|-- base       : basic html elements
|-- components : single components
|-- helpers    : helper classes
|-- pages      : page related styles
|-- settings   : variables
|-- vendor     : custom files from 3rd party components like select2, jqueryui etc.
|-- app.css    : main file

app.css

Import in proper order to take care of variable declaration & specificity

1
2
3
4
5
6
@import "settings/**/*";
@import "base/**/*";
@import "components/**/*";
@import "pages/**/*";
@import "helpers/**/*";
@import "vendor/**/*";

Base Folder

Contains resets and sensible defaults for basic html elements.

1
2
3
4
5
6
7
|-- normalize.css
|-- html.css
|-- a.css
|-- p.css
|-- heading.css (h1, h2, h3)
|-- list.css (ul, ol, dl)
|-- 

Components Folder

Stand-alone reusable components with their modifiers.

1
2
3
4
|-- modal.css
|-- buttons.css
|-- table.css
|-- 

Helper Folder

Stand-alone helper classes for small layout fixes.

1
2
3
4
5
|-- align.css
|-- margin.css
|-- padding.css
|-- text.css
|-- 

Pages Folder

Page related styles (not reusable but needed for pages)

1
2
3
|-- about.css
|-- dashboard.css
|-- 

Settings Folder

Settings for colors, typography, etc. You can start small with one settings.css and split them up in different files if your variables grow.

1
2
3
4
5
|-- color.css
|-- fonts.css
|-- grid.css
|-- typography.css
|-- 

Vendor Folders

Imported and customized CSS from 3rd party components (you don’t want to lint this).

1
2
3
|-- jquery-ui.css
|-- select2.css
|-- 

This guide is inspired from various sources, thanks to those who shared their views which help me build this self guide.

Tools I Use

| Comments

“We become what we behold. We shape our tools, and thereafter our tools shape us.”
― Marshall McLuhan

Tools are very important for all professions, this article covers the main tools I use for my everyday work (I work as a frontend developer & user experience designer, so if you are in the same profession you may find this useful)

I will try to keep this post updated. (Last Updated: 18-Aug-2017)

Terminal

  • iTerm2 - my default terminal. I love those spilt pane in iterm2, try hitting Command (⌘) + d to split vertically & Command (⌘) + Shift + d split horizontally
  • oh-my-zsh - gives super power to my shell. Many useful Plugins & Themes.
  • z - remembers your frequently used directory and helps quickly cd into it, check the wiki for more details.

Code Editor / IDE

  • Visual Studio Code - recently became a fan of this open source editor from Microsoft. Love those git integrations and fast performance of the editor.
  • Atom - second favorite and minimal editor.
  • Sublime Text - super fast, Some of my favorite plugins

Browsers

Browser Extensions

  • Tab Suspender - chrome sucks a lot of memory and slows your machine, Use this extension which will kill unused open tabs and increase your RAM space
  • Tab Switcher - fast switch between open tabs. a) Press Command (⌘) + Shift + k use up & down arrow to navigate b) Click return to focus on the tab.

Will add a separate blog post about all of my extensions

Design

  • Sketch - pretty sleak and ease to use app for designing mobile, web apps.
  • Photoshop - all time favorite tool for designing mobile/web apps, graphics, branding, etc.,
  • Omnigraffile - for Functionality map preparation, User Interface Wireframing.

Check my design profile on Dribble, Behance

Productivity

  • Alfred - powerful mac spotlight alternative
  • Evernote - for quick notes taking
  • Skitch - for annotation on screenshots
  • LICEcap - quick record your screen and generate it as GIF
  • Quicktime - for screen casting, audio recording
  • Moom - quickly make any window full screen, snape to grip, move, etc.,
  • Fanstical2 - calander app with great user experience and nice look & feel

Others

  • Rocket - emoji autosuggestion on any app like slack.
  • Muzzle - automatically silence notifications while screensharing (PS. Read those funny notification messages on muzzle website)

Thanks for reading, let me know in the comments about what you use!