Stylelint - CSS Linter You Must Know As A Frontend

Let me show you Stylelint, a tool for anyone working with CSS or SCSS, making sure the code doesn't go off the rails. It identifies errors, and rule violations, suggests fixes, and sometimes solves issues for you.

tl;drGitHub

What kind of issues? For example, if your project has a policy against using px units, you can configure Stylelint to flag any instances where px units are used, providing immediate feedback to developers that these need to be changed. This instant alert helps maintain consistency and uphold standards within your project.

Stylelint protects against coding issues, saves development time, and improves the quality of your project. It is precious in team environments or larger projects where a consistent coding style is key, however, it is not so crucial if you don't write a lot of CSS code, or for the simplest projects.


How to install Stylelint?

At first, I suggest sticking to the official docs and using NPM for installation 😅 This method ensures a smooth setup, avoiding the issues sometimes encountered with other package managers like I experienced with Yarn.

npm init stylelint

The installation command not only sets up Stylelint but also includes recommended rules, providing a strong foundation that you can customize for your project's needs. It also creates a configuration file named .stylelintrc.json. To keep your configuration files consistent, such as with .prettierrc, you might consider renaming it to .stylelintrc.

{
  "extends": ["stylelint-config-standard"]
}

If you're working with SCSS, integrating SCSS-specific rules into your configuration is easy. Install them with the command below and tell the Stylelint to use them.

npm install stylelint-config-standard-scss --save-dev
{
  "extends": ["stylelint-config-standard-scss"]
}

How to use Stylelint?

Once Stylelint is installed, you're ready to put it to work. With the command-line interface, you can lint all SCSS files within the specific directory e.g. resources.

yarn stylelint resources/**/*.scss

resources/styles/styles.scss
   2:16  ✖  Unexpected quotes around "Montserrat"           font-family-name-quotes
  11:16  ✖  Unexpected quotes around "Montserrat"           font-family-name-quotes
  20:16  ✖  Unexpected quotes around "Montserrat"           font-family-name-quotes
  35:16  ✖  Unexpected quotes around "Montserrat"           font-family-name-quotes
  35:16  ✖  Unexpected missing generic font family          font-family-no-missing-generic-family-keyword
  47:3   ✖  Expected "0 0 1.375rem 0" to be "0 0 1.375rem"  shorthand-property-no-redundant-values

✖ 6 problems (6 errors, 0 warnings)
  5 errors potentially fixable with the "--fix" option.

If Stylelint identifies issues that can be automatically fixed, appending the --fix flag to your command will address these issues, simplifying your workflow. Any remaining issues must be manually handled, which is a standard part of the process.

yarn stylelint resources/**/*.scss --fix

resources/styles/styles.scss
  35:16  ✖  Unexpected missing generic font family  font-family-no-missing-generic-family-keyword

✖ 1 problem (1 error, 0 warnings)

error Command failed with exit code 2.

Tip: Dropping Stylelint tasks into your package.json is a great way to make your setup more efficient, keeping your configs and dependencies in one place. Just place the lining and formatting commands after the Prettier's ones (they have been described here).

{
  "scripts": {
    "build": "vite build",
    "dev": "vite",
    "lint": "prettier resources --check; stylelint resources/**/*.scss",
    "format": "prettier resources --write; stylelint resources/**/*.scss --fix"
  },
}

How to ignore code in Stylelint?

The process with Stylelint is similar to other linters and formatters. You can use specific comment formats to exclude certain blocks from validation, specific lines, or even disable a specific rule for a section or line.

/* stylelint-disable */
a {}
/* stylelint-enable */

#id { /* stylelint-disable-line */
  color: pink !important; /* stylelint-disable-line declaration-no-important */
}

Additionally, you can create a .stylelintignore file to exclude entire directories or specific file formats from being linted. Alternatively, you can achieve the same effect by specifying files to ignore in the ignoreFiles key of the Stylelint configuration file.

{
  "extends": [
    "stylelint-config-standard-scss",
    "stylelint-config-clean-order"
  ],
  "ignoreFiles": [
    "node_modules",
    "dist/**/*"
  ]
}

How to configure Stylelint?

Stylelint provides several configurable options, but the most I need is adjusting rules to my needs. Let's say that I want to allow empty CSS files, which are forbidden in the standard config. I need to add a rules key to the .stylelintrc and disable no-empty-source.

{
  "extends": [
    "stylelint-config-standard-scss",
    "stylelint-config-clean-order"
  ],
  "rules": {
    "no-empty-source": null
  }
}

There are much more possibilities too! Let's say that you want to enforce a specific order of CSS properties to enhance code readability. It’s generally easier to read the code when properties follow a logical sequence like here.

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

  /* Display & Box Model */
  width: 100px;
  height: 100px;
  padding: 10px;
  border: 10px solid #333;
  margin: 10px;
}

Thanks to Stylelint's extensive plugin ecosystem you can easily handle this. Start by installing the stylelint-order plugin, then choose and install one of the available ordering standards too and set its usage in the .stylelintrc configuration file.

npm install stylelint-order stylelint-config-clean-order --save-dev
{
  "extends": [
    "stylelint-config-standard-scss",
    "stylelint-config-clean-order"
  ]
}

Once the plugin is installed and your configuration is updated, running Stylelint will highlight any discrepancies from your defined property order, among other issues.

yarn stylelint resources/**/*.scss

resources/styles/styles.scss
   2:16  ✖  Unexpected quotes around "Montserrat"                            font-family-name-quotes
   4:3   ⚠  Expected "font-weight" to come before "font-style"               order/properties-order
  11:16  ✖  Unexpected quotes around "Montserrat"                            font-family-name-quotes
  13:3   ⚠  Expected "font-weight" to come before "font-style"               order/properties-order
  20:16  ✖  Unexpected quotes around "Montserrat"                            font-family-name-quotes
  22:3   ⚠  Expected "font-weight" to come before "font-style"               order/properties-order
  35:3   ⚠  Expected an empty line before property "font-family"             order/properties-order
  35:16  ✖  Unexpected quotes around "Montserrat"                            font-family-name-quotes
  35:16  ✖  Unexpected missing generic font family                           font-family-no-missing-generic-family-keyword
  (...)

✖ 19 problems (6 errors, 13 warnings)
  5 errors potentially fixable with the "--fix" option.

This is your chance to customize Stylelint to fit your team's vibe, mixing and matching all the rules until you've got your ideal setup.


How to integrate Stylelint with VS Code?

Stylelint offers an integration plugin for VS Code, and setting it up is pretty easy. Simply install the plugin, and it should work seamlessly. If you work with SCSS, you'll need to adjust the extension settings to include SCSS in the file types to check too. This is also applicable to other file types like Vue if you want to check SCSS within those files.

Once installed, the plugin allows you to see problems in your code as you write. You can also fix these issues directly in VS Code by using the cmd+shift+p shortcut, typing fix and choosing Stylelint to fix the file. You can also modify the settings and enable file formatting every time you save a file. It happens in the background.

Image


How to integrate Stylelint with Prettier?

Until version 15, Stylelint managed stylistic rules, which Prettier also handled. This overlap meant that whichever tool was used last could overwrite changes made by the other. However, with the release of version 16, Stylelint discontinued support for stylistic rules and recommends Prettier for these tasks. Now, Stylelint concentrates mostly on architectural concerns and lets Prettier handle stylistic rules.

Why I'm worried about self-awareness?

It sounds fine, but I have some doubts. Please check out the following code which breaks different rules like incorrect quotes in line 2 handled by Stylelint and incorrect indentation in the line 2,3 handled by Prettier.

@font-face {
    font-family: 'Montserrat';
    font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('../fonts/Montserrat-Light.woff2') format('woff2'),
  url('../fonts/Montserrat-Light.woff') format('woff');
}

When I run Stylelint checks, it works great and shows all the rules violations with exact references. When I run Prettier to check formatting, I get only the information about files which includes problems without any further references.

yarn stylelint resources/**/*.scss

resources/styles/styles.scss
  2:18  ✖  Unexpected quotes around "Montserrat"                            font-family-name-quotes
  4:3   ⚠  Expected "font-weight" to come before "font-style"               order/properties-order
yarn prettier . --check

Checking formatting...
[warn] .stylelintrc
[warn] resources/styles/styles.scss
[warn] Code style issues found in 2 files. Run Prettier to fix.

I know, Prettier was created to forget about problems. Automatic corrections, especially with features like "format on save," are amazing, and improve the coding experience a lot, but they can also obscure learning opportunities. For developers who thrive on detailed feedback to improve their coding practices, seeing each issue is beneficial.

Also, without CI/CD processes or integrating tools like Husky, developers must remember to format the code before pushing. This reliance on memory is a potential source of the problems. I don't like this and that's why I prefer seeing problems immediately as I write - I can't just say "Oh, I forgot."

So while Prettier is an excellent tool, it truly shines only in the right hands.

Is there any alternative?

It might seem that with Stylelint's decision to remove stylistic rules, you'd be left without those capabilities unless you switch to using Prettier. However, that isn't the case. A community-driven plugin has brought these deprecated rules back.

npm install @stylistic/stylelint-plugin @stylistic/stylelint-config --save-dev
{
  "extends": [
    "@stylistic/stylelint-config",
    "stylelint-config-standard-scss",
    "stylelint-config-clean-order"
  ],
  "ignoreFiles": [
    "node_modules",
    "dist/**/*"
  ],
  "rules": {
    "@stylistic/string-quotes": "single"
  }
}

After installing the additional plugin, stylistic issues such as breaking indentation rules are also displayed in the reports. This visibility ensures that developers can no longer claim they didn't notice these problems.

yarn stylelint resources/**/*.scss

resources/styles/styles.scss
   2:5   ✖  Expected indentation of 2 spaces                                 @stylistic/indentation
   2:18  ✖  Expected double quotes                                           @stylistic/string-quotes
   2:18  ✖  Unexpected quotes around "Montserrat"                            font-family-name-quotes
   3:5   ✖  Expected indentation of 2 spaces                                 @stylistic/indentation
   4:3   ⚠  Expected "font-weight" to come before "font-style"               order/properties-order
   6:6   ✖  Expected newline after ":" with a multi-line declaration         @stylistic/declaration-colon-newline-after
   6:12  ✖  Expected double quotes                                           @stylistic/string-quotes
   6:54  ✖  Expected double quotes                                           @stylistic/string-quotes
   7:3   ✖  Expected indentation of 4 spaces                                 @stylistic/indentation
   7:7   ✖  Expected double quotes                                           @stylistic/string-quotes
   7:48  ✖  Expected double quotes                                           @stylistic/string-quotes

In this approach, I want to tweak the rules slightly, as I prefer using single quotes. Consequently, I need to update the .prettierrc file to exclude CSS files from its checks.

*.lock
*-lock.json
**/*.scss

What approach do I use?

In a previous video about Prettier, I mentioned that I wouldn't use Prettier for managing stylistic rules in CSS code, believing that it was the right approach at the time. However, my perspective has since shifted.

I had concerns about developers losing awareness or forgetting about the formatting process, but It might not be a huge problem when integrating tools like Husky or setting up CI/CD processes, which I plan to implement soon. Therefore, I now use Stylelint to handle CSS architectural concerns and let Prettier take care of the formatting.


Summary

Using Stylelint not only enforces good coding habits and helps you spot problems early, but it also keeps your codebase sharp and consistent. As you customize Stylelint to fit into your workflow, you'll notice improvements not just in your code quality, but also in the efficiency of your development process. So go ahead, dive in, make the necessary adjustments, and watch as the quality of your CSS improves!

Feedback

How satisfied you are after reading this article?