Stylelint instructions

In this blog post, I explain how we can set up and use stylelint in our web projects.


What is stylelint

Stylelint is a powerful modern linter with which we can avoid mistakes in our styles and enforce uniform conventions in our styles.

To begin

First, we will install the stylelint package as follows:

yarn add --save-dev stylelint

Then, we create a .stylelintrc configuration file in the root directory of our project with the following content:

{
    "extends": "stylelint-config-standard",
    "rules": {
        "indentation": 2,
        "string-quotes": "single",
        "no-duplicate-selectors": true,
    }
}

Here I explain the rules set above to you, with examples:

indentation: We use 2 spaces as an indentation

@media print {
  a {
    background-position: top left, top right;
  }
}

string quotes: All strings are enclosed in single quotation marks

// The following example is considered a violation:
a { content: "x"; }

// The following example is not considered a violation:
a { content: 'x'; }

no-duplicate-selectors: Do not allow duplicate selectors in a stylesheet

// The following example is considered a violation:
.foo,
.bar,
.foo {}

// The following example is not considered a violation:
.foo {}

@media (min-width: 10px) {
  .foo {}
}

The whole thing is only part of the rules that we can use with stylelint. Stylelint comes with over 170 rules by default. If we want to get to know more rules, then we can look at the homepage of [Stylelint] (https://stylelint.io/user-guide/rules/list).

In the script section in our package.json we add the following:

"stylelint": "stylelint \"./src/**/*.css\"",

The path can change depending on the project.

Now we can start stylelint for the first time with

yarn stylelint

Stylelint with styled components

We can also use stylelint in projects that use styled components, such as React projects.

What do we need for this:

  • stylelint-processor-styled-components
  • stylelint-config-styled-components, configuration to deactivate stylelint rules that collide with the styled-components
  • Our favorite stylelint configuration! (for example stylelint-config-recommended)
yarn add stylelint stylelint-processor-styled-components stylelint-config-styled-components stylelint-config-recommended

We are now using the following .stylelintrc configuration file in our project.

{
  "processors": ["stylelint-processor-styled-components"],
  "extends": [
    "stylelint-config-recommended",
    "stylelint-config-styled-components"
  ]
}

In the script section in our package.json we add the following:

"stylelint": "stylelint \"./src/**/*.ts{,x}\"",

What exactly are the packages doing now?

stylelint-processor-styled-components:

This processor is required to extract styles from our styled components. The processor also works with files of the type Flow and TypeScript! (We'll assume TypeScript is used if your files end in .ts or .tsx.)

stylelint-config-styled-components:

When using Stylelint processor-style components, some stylelint rules throw up errors that you cannot prevent. Like 'no-empty-source' or 'no-missing-end-of-source-newline'.

This shareable configuration automatically disables rules that cause unsolvable conflicts. In addition to these rules, properties and values ​​prefixed by the manufacturer will trigger an error, since styled-components automatically generates manufacturer prefixes for your CSS. We have to note that we can override these rules in our Stylelint configuration at any time if we want to change them.

stylelint-config-recommended:

The recommended shareable configuration for stylelint. All possible error rules are activated in stylelint. We can find a list of activated rules here.

We use it as is or we can use it as the basis for our own configuration.

Stylelint in SASS / SCSS projects

I personally use SCSS stylesheets in my private projects. There is also a good Stylelint extension called stylelint-config-sass-guidelines for this. It is based on the following [Styleguide] (https://sass-guidelin.es/).

We installed the whole as follows:

yarn add stylelint-config-sass-guidelines

And in our .stylelintrc we add the line stylelint-config-sass-guidelines as follows.

{
  "processors": [...],
  "extends": [
    ...

    /// Will be added here
    "stylelint-config-sass-guidelines"
  ]
}

What exactly does the extension do? I'll explain that to you now.

key principles

  • A style guide is all about consistency.
  • Sass should be kept as simple as possible. We avoid building complex systems unless necessary.
  • We remember that sometimes KISS (Keep It Simple, Stupid) is better than DRY (Don’t Repeat Yourself)

Syntax & Formatting

  • An indent consists of two (2) spaces: no tabs
  • Lines should be shorter than 80 characters as much as possible. We can split them into multiple lines if necessary.

strings

  • It is highly recommended to declare the @charset directive above the stylesheet.
  • Unless used as an CSS identifier, strings should be enclosed in single quotation marks. URLs should also be enclosed in quotation marks.

numbers

  • Sass does not differentiate between numbers, whole numbers and floating point numbers, so trailing zeros (0) should be omitted. However, leading zeros (0) improve readability and should be added.
  • A length of zero (0) should have no unit.
  • The manipulation of units should be viewed as arithmetic operations rather than string operations.
  • For better readability, top-level calculations should be enclosed in parentheses. Also, complex math operations can be broken down into smaller parts.
  • Magic numbers significantly impair the maintainability of the code and should be avoided at all times. If in doubt, explain the value in question in detail.

Colors

  • Whenever possible, colors should be expressed in HSL, then in RGB and then in hexadecimal form (in lowercase and shortened). Color keywords should be avoided.
  • It is best to use the mix (..) function instead of darken (..) and lighten (..).

lists

  • Lists should be separated by commas unless they are used as a direct association.
  • Including parentheses should also be taken into account to improve readability.
  • Inline lists should not have a trailing comma. Multiline lists should have one.

Maps

  • Maps containing more than one pair are written on several lines.
  • To improve maintainability, the last pair of a map should have a trailing comma.

sorting of declarations

  • The system used to sort the declarations (alphabetical, by type, etc.), it does not matter as long as it is consistent.

Selector nesting

  • We avoid nesting selectors when they are not needed (which is the case usually).
  • Use selector nesting for pseudo-classes and pseudo-elements.
  • Media queries can also be nested in their corresponding selector.

Rules of naming

  • It is best to adhere to CSS naming conventions which (except for some errors) are lowercase and separated by hyphens.

Comments

  • CSS is a tricky language. Don't hesitate to write very detailed comments on anything that looks suspicious.
  • Use SassDoc comments for variables, functions, mixins, and placeholders

Stylelint extensions

There are still some useful Stylelint extensions that I would like to introduce here.

stylelint-config-rational-order

Is a stylelint configuration that sorts related property declarations by grouping them in the following order:

  1. Positioning
  2. Box model
  3. Typography
  4. Visual
  5. animation
  6. Misc
.declaration-order {
  /* Positioning */
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 10;

  /* Box Model */
  display: block;
  float: right;
  width: 100px;
  height: 100px;
  margin: 10px;
  padding: 10px;

  /* Typography */
  color: #888;
  font: normal 16px Helvetica, sans-serif;
  line-height: 1.3;
  text-align: center;

  /* Visual */
  background-color: #eee;
  border: 1px solid #888;
  border-radius: 4px;
  opacity: 1;

  /* Animation */
  transition: all 1s;

  /* Misc */
  user-select: none;
}

This has the advantage over the alphabetical sorting that the related properties can be recognized at a glance.

So that the whole thing can be used in our stylelint, we will first install as follows.

yarn add stylelint-order stylelint-config-rational-order

And in our .stylelintrc we add the line stylelint-config-rationalorder as follows.

{
  "processors": [...],
  "extends": [
    ...

    /// Will be added here
    "stylelint-config-rational-order"
  ]
}

stylelint-a11y

This stylelint configuration is very useful for creating accessible CSS rules.

First, we install the plugin as follows:

yarn add stylelint-a11y

Our .stylelintrc is extended by the following:

{
  "processors": [...],
  "plugins": ["stylelint-a11y"], // this line is added
  "extends": [
    ...
  ],
  "rules": {
    // These are the new rules we can set.
    "a11y / content-property-no-static-value": true,
    "a11y / font-size-is-readable": true,
    "a11y / line-height-is-vertical-rhythmed": true,
    "a11y / media-prefers-reduced-motion": true,
    "a11y / media-prefers-color-scheme": true,
    "a11 / no-display-none": true,
    "a11y / no-obsolete-attribute": true,
    "a11y / no-obsolete-element": true,
    "a11y / no-spread-text": true,
    "a11y / no-outline-none": true,
    "a11y / no-text-align-justify": true,
    "a11y / selector-pseudo-class-focus": true
  }
}

Now, briefly explain to you what kind of rules these are and what they do.

content-property-no-static-value:

Do not allow CSS-generated content except for Aria label, attribute content, and empty strings.

// The following example is considered a violation:
.foo :: before {
  content: 'Price: $ 50';
}

// The following example is not considered a violation:
.foo {
  content: '';
}

.foo {
  content: attr (aria-label);
}

font-size-is-readable:

Font sizes below 15px (or 11.25pt) are not permitted.

// The following example is considered a violation:
.foo {
  font-size: 10px;
}

// The following example is not considered a violation:
.foo {
  font-size: 15px;
}

.foo {
  font-size: 1em;
}

line-height-is-vertical-rhythmed:

Vertical rhythm is a concept that originated in printing typography. In Vertical Rhythm, we try to keep vertical distances between elements on a page consistent.

// The following example is considered a violation:
.foo {
  line-height: 12px;
}

.foo {
  line-height: 1.3;
}

.foo {
  line-height: 50px;
}

// The following example is not considered a violation:
.foo {
  line-height: 24px;
}

.foo {
  line-height: 1.6;
}

.foo {
  line-height: 48px;
}

media-prefers-reduced-motion:

In Safari 10.1, the media query for reduced movements was introduced. It is a non-vendor prefix declaration that allows developers to "create styles that avoid large areas of motion for users who specify a preference for reduced motion in system preferences."

// The following example is considered a violation:
.foo {
  animation: 1s ease-in;
}

.bar {
  animation name: skew;
}

@media screen and (prefers-reduced-motion) {
  .bar {
    transition: none;
  }
}

// The following example is not considered a violation:
.foo {
  line-height: 24px;
}

.foo {
  line-height: 1.6;
}

.foo {
  line-height: 48px;
}

media-prefers-color-scheme:

The Preferred Color Scheme media feature reflects the user's desire for the page to use a light or dark color theme.

light: indicates that the user has expressed preference for a page with a light theme (dark text on a light background) or no active preference (and should therefore be given the "web default" of a light theme).

dark: indicates that the user has expressed a preference for a page with a dark theme (light text on a dark background).

// The following example is considered a violation:
.foo {
  color: red;
}

@media screen and (prefers-color-scheme: dark) {
  .foo {
    background-color: red;
  }
}

// The following example is not considered a violation:
.foo {
  color: red;
}

@media screen and (prefers-color-scheme: dark) {
  .foo {
    color: white;
  }
}

no-display-none:

Developers typically use display: none to hide content on the page. Unfortunately, this common action can be problematic for screen reader users, especially if the hidden content is intended for them.

// The following example is considered a violation:
.foo {
  display: none;
}

// The following example is not considered a violation:
.foo {
  display: flex;
}

no-obsolete-attribute:

Do not allow obsolete attributes

// The following example is considered a violation:
body [link] {
  background-color: pink;
}

a, img [datasrc] {
  color: pink;
}

img [align], a [name] {
  color: pink;
}

no obsolete element:

Do not allow obsolete selectors.

// The following example is considered a violation:
blink {
  color: pink;
}

no-spread-text:

Text width greater than 45 characters and less than 80 characters required. This increases readability and the eyes do not tire so quickly.

// The following example is considered a violation:
.foo {
  text-transform: lowercase;
  max-width: 40ch;
}

.foo {
  line-height: 1.8;
  max-width: 82ch;
}

// The following example is not considered a violation:
.foo {
  max-width: 65ch;
}

.foo {
  max-width: 82ch;
}

.foo {
  max-width: 100px;
}

no-outline-none:

Removing outline in CSS creates problems for users who navigate the web with a keyboard.

// The following example is considered a violation:
.foo: focus {
  outline: 0;
}

.bar: focus {
  outline: none;
}

.baz: focus {
  outline: none;
  border: transparent;
}

.quux {
  .quuux: focus {
    outline: 0;
  }
}

// The following example is not considered a violation:
.foo {
  outline: 0;
}

$ primary-color: # 333;
.bar: focus {
  outline: 1px solid $ primary-color;
}

.baz: focus {
  outline: 1px solid # 333;
}

.quux: focus {
  outline: 0;
  border: 1px solid # 000;
}

no-text-align-justify

We forbid {text-align: justify; }. If the text is justified, it becomes more difficult to read because of the large gaps in the text blocks that interrupt reading and make the text block uneven.

// The following example is considered a violation:
.foo {
  text-align: justify;
}

// The following example is not considered a violation:
.foo {
  text-align: center;
}

.foo {
  text-align: left;
}

.foo {
  text-align: right;
}

.foo {
  text-align: start;
}

.foo {
  text-align: end;
}

selector-pseudo-class-focus:

Checks the existence of a pseudo class for selectors with: hover.

// The following example is considered a violation:
a:hover {
}


// The following example is not considered a violation:
a:hover,
a:focus {
}

a:focus {
}

a:hover {
}

a:focus {
}

Stylelint in IDE / editors

For many IDEs and editors, there are plugins with which we can execute Stylelint in them.

  • Execute Stylint in PHPStorm: here
  • Run Stylint in Sublime Text 3: here
  • Run Stylelint in vim: with ale or coc
  • Execute Stylelint in VSCode: here