Menu
«

CSS Style Guide

NOTE!

This style guide is outdated and should be updated to reflect the current state of our projects. It's still a good starting point, but it's not the final word on how we write CSS.


We always use Sass (the scss flavour) in our projects. We generally use TailwindCSS for all new projects.

Class naming & components

Use simple classes with words separated with hypens. Try to avoid creating components. Instead try to style as much as you can with Tailwind classes and only extract components when you have to.

Bad:

.sidebar__link {}

Good:

.sidebar-link {}

Try not to use too many general html-selectors, this will eventually have unwanted side effects:

Bad:

.sidebar {
    a {}
}

Good:

.sidebar {}
.sidebar-link {}

// or 

.sidebar {
    .link {}
}

Nesting

Try to avoid nesting more then 2 levels deep:

Bad:

.component {
    h2 {
        i {}
    }
}

Good:

.component {
    h2 {}
    
    i {}
}

If you need to style stuff with css and you feel the need to nest stuff deep, add a class instead - it's ok!

Indentation

Always use 4 spaces (not tabs) for indentation (make sure your IDE is setup correctly). For PHPStorm, this is done by going to Preferences => Editor => Code Style => SCSS/CSS and there set the options:

This is already configured in our own phpstorm .xml-file.

Code style linting

We use stylelint to lint our stylesheets. Configuration is done a custom .stylelintrc which extends stylelint-config-standard.

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

Installation

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

Projects without Tailwind

For older projects where we don't use Tailwind, we try to follow a BEM-like structure. Everything from this point is only important for older projects without Tailwind.

BEM

.component                      /* Component */   
.component__element             /* Child */
.component__element__element    /* Grandchild */

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

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

.component--variation           /* Standalone variation of a component */
.component__element--variation  /* Standalone variation of an element */

.helper-property                /* Generic helper grouped by type (eg. `align-right`, `margin-top-s`) */

.component, .component__element

<div class="article">
<div class="article">
    <div class="article__item">
        <div class="article__item__publish-date">

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

<div class="team">
    <div class="team__member">

You can use plurals & singulars for readability. Consider class="member" instead of class="members__member". Not everything must be inside of the same component!

<div class="members">
    <div class="member">

.-modifier

Don't use the -modifier for all variations, just single modifier classes like active.

<div class="button -rounded -active">
.button {
    &.-rounded {
    }

    &.-active {
    }
}

.component--variation

A variation should be used together with the base class.

<div class="button button--delete">
.button {
    // Button styles
}
.button--delete {
    
    // Variation styles
    background-color: red; 
    color: white;
    text-transform: uppercase;
}

.helper-property

<div class="align-right">
<div class="visibility-hidden">
<div class="text-ellipsis">
<div class="text-muted">

Nesting

Make sure that you don't nest your components in the SASS code unless you have to.

Best:

.search {
    
}

.search__input {

}

OK in some scenarios:

.search {
    // Need to nest this because of form input base style
    .search__input {
    
    }  
}

Bad:

.search {
    .search__icon {
    
    }
}

Js-hooks / Data-attributes

<div class="…"
     data-trigger-map
     data-map-icon="url.png"
     data-map-lat="4.56"
     data-map-lon="1.23">

DOM structure

<!-- Try to avoid, news padding or margin could break the grid--> 
<div class="grid__col -1/2 news">
    …
</div>    

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