Taking CSS Linting to the Next Level with Stylelint

Share this article

Stylelint Demo

As front-end development has matured, the use of tools addressing code quality has grown substantially.

This is perhaps most evident when looking at the JavaScript ecosystem. Using a JavaScript linter is now the expected standard for front-end developers to ensure that their code is well structured and consistent. In fact, in my recent tooling survey, the vast majority of developers stated that they lint their JavaScript.

When it comes to writing CSS, the drive towards using code quality tools has been a little slower, with the majority of developers in that same survey stating that they chose not to use a CSS linter in their workflow.

Stylelint Demo

I want to address this shortfall today, looking at one tool in particular that has raised the bar when it comes to linting stylesheets: stylelint.

It’s worth noting up front that although I reference CSS throughout this article, these references are interchangeable with a preprocessing language such as Sass. Stylelint can evaluate Sass and Less files as well as plain CSS and we’ll look at this in more detail later in the article.

A (Very) Brief History of CSS Linting

When CSS linting was first introduced as a concept, it was fairly polarizing. Shortly after CSS Lint was introduced back in 2011, I remember reading an article by Matt Wilcox called CSS Lint is harmful, which criticized the opinionated nature of some of its rules – a sentiment that was shared by many in the community.

Looking back, CSS Lint was much like the first JavaScript linting tools that were available, such as JSLint – opinionated and not very flexible. However, while tools such as JSHint and ESLint emerged and pushed JavaScript linting forward, alternatives in the CSS linting landscape were non-existent.

That is until stylelint arrived on the scene.

Why Stylelint?

There are a few reasons why I think stylelint is now the best tool available when it comes to linting your CSS.

Firstly, it is completely un-opinionated. That means you can enable as few or as many rules as you like, with a number of its rules giving you options to configure them to your preferences.

Also, it has a huge array of rules available – over 150 in fact, not including language specific rules for preprocessor specific syntax. Spending a little time to look through these is invaluable to building up a set of rules that fits how you write your styles.

It is also very flexible, understanding CSS and CSS-like syntax such as SCSS and Less. So whether you want to lint preprocessor code or vanilla CSS, stylelint has you covered.

Lastly, and perhaps most importantly, its documentation is excellent. Want to see what rules are available? Check out the detailed documentation covering all available rules. How about some advice on how to contribute a new rule that you might like? They have a great developer guide to help you with that too.

What Can Stylelint Do?

The value of adding a linting step when developing in any language is to improve the consistency of the code that you’re writing and to reduce the number of errors in your code.

When applying this to CSS there are a number of issues that stylelint can help you address.

Syntax Errors

Syntax errors are not subjective errors and should be very clear once highlighted.

Consider the following example:

.element {
  color: #EA12AE1;
  disply: block;
}

The above code shows two different syntax errors. The first error is an invalid hex color. The second is a typo when declaring the display property.

These are pretty basic syntax errors that can get picked up by stylelint using rules such as color-no-invalid-hex and property-no-unknown, saving you the headache of having to find the mistake manually.

Formatting and Consistency

In CSS, code style preference can be extremely subjective. Chances are the way that I like to write my CSS isn’t the way that you prefer to write yours. It’s therefore important that a CSS linter can adapt to your preferences rather than trying to force a set of rules on you.

Consider the following styles:

.listing {
  display: block;
}

.listing-item
{
  color:blue;
}

.listing-img{
  width : 100%}

.listing-text { font-size: block; }

.listing-icon {
  background-size: 0,
    0; }

All of the rule sets above contain valid CSS, but they are clearly not consistent with one another in style. Use of spacing in each declaration is different and each block is formatted in a slightly different way.

This example shows just a few possible ways of formatting CSS. But in reality there are hundreds of subtle variations. Over a whole stylesheet (or multiple files), inconsistencies such as these can hinder the readability and maintainability of your code.

This inconsistency becomes more apparent when a project is worked on by multiple developers, as each one might prefer to write their styles in a slightly different way. It’s always beneficial to get together and agree on a set of formatting rules that you will all stick to in such a situation.

Stylelint allows you to customize a set of rules to match the way that you, or your team, prefer to format your styles. Whatever preferences you have, stylelint can check that these rules are being applied consistently across your project.

Reduce Duplication in Styles

Duplication can be a pain to debug, whether it’s the duplication of selectors or properties in a stylesheet.

Take a look at the following CSS:

/* Property duplication */
a {
  display: block;
  color: orange;
  font-size: 1.2rem;
  display: inline; /* duplicate */
}

/* Selector duplication (1)
   Same selector, at different points in stylesheet */
.foo {}
.bar {}
.foo {}

/* Selector duplication (2)
   The same group of selectors, simply ordered differently */
.foo, .bar {}
.bar, .foo {}

Stylelint has several rules that can help spot this kind of duplication in your code, such as the declaration-block-no-duplicate-properties rule that will catch duplicate properties.

It can also be configured to ignore intentional duplication, such as when the same property has been defined to provide a fallback value:

.example {
  font-size: 14px;
  font-size: 1.2rem; /* will override the above if browser supports rem */
}

Best Practice Checks

Best practices in CSS are somewhat subjective, but stylelint give you total flexibility in how you want to check for these “errors”, if at all.

One commonly accepted best practice that falls into this category would be to throw an error when a certain selector nesting depth is exceeded when writing preprocessor code. This is useful to ensure that the specificity level of your styles is kept to a reasonable level and doesn’t get out of hand.

Different developers and different use cases mean that what is deemed to be ‘acceptable’ may change from project to project. For example, you may have a legacy stylesheet in which you want to ensure the nesting depth doesn’t get any worse. The max-nesting-depth rule lets you define your own acceptable nesting depth to check against, meaning that this rule could be useful for any project that uses a preprocessor.

Limit Language Features

The final set of checks that stylelint gives you access to is what they call ‘Limit language features’ in their rule guide. These can be used to enforce your own feature rules when working with your stylesheets.

A common example would be if you use a tool like Autoprefixer to automate adding vendor prefixes to your styles. In this scenario, it would be useful to throw a warning or an error if a vendor prefix has been manually added by a developer, as this will help to keep your code clean of unnecessary prefixes that will get added when the tool is subsequently run over unprefixed styles. Stylelint can take care of this for you with its ‘value-no-vendor-prefix’ rule rule, which does exactly that.

Other examples of rules range from disallowing named colors or specifying the maximum precision of numbers, to being able to blacklist certain properties if you so wish to.

These rules are more opinionated by their very nature, but you can use them however you choose to. This means that your projects’ linting rules are tailored to how you and your team like to write your styles.

Using Stylelint

We’ve covered what stylelint can do, but how easy is it to set up and use?

Like its rule set, stylelint is extremely flexible. There are a number of plugins available that make it easy to integrate into whichever build tool you prefer to use, as well as editor plugins for Atom, Sublime Text, and Visual Studio Code.

In terms of setting up your own rule set, there are multiple ways to do so. The easiest way is to create a .stylelintrc file in your project’s root directory inside which you can start to build your own rules such as:

{
  "rules": {
    'block-closing-brace-newline-before': 'always-multi-line',
    'block-closing-brace-space-before': 'always-single-line',
    'color-no-invalid-hex': true,
    'comment-no-empty': true,
    'unit-case': 'lower',
    'unit-no-unknown': true,
    // etc...
  }
}

When you then run your stylelint task – for example as part of your Gulp or webpack build – it will pick up the above configuration and use those rules to lint your styles.

Similar to JavaScript linting tools like ESLint, you can also use an existing configuration as a starting point and add your own rules. Stylelint has a recommended base configuration that you can extend, or you can choose to extend from more opinionated rule sets based on methodologies such as SUIT CSS.

My advice would be to spend a little time looking through the available rules and creating a configuration that you and your team are happy with. Once proven useful, you could take the extra step of having your configuration available as an installable npm module – like the extendable rule sets mentioned above – so that you can then install and keep your stylelint configuration in sync across all of your projects.

Linting Preprocessor Code

As I mentioned earlier, stylelint can lint Sass or Less as easily as it can CSS.

Setting this up depends on how you use stylelint. If you’re using a plugin for a build tool such as Gulp or webpack, you can pass through a value for stylelint’s syntax option. This option takes less or scss as values depending on which syntax you wish to lint.

As an example, to specify that you would like to lint your .scss files, you would pass the following object in as your stylelint options:

{
  syntax: 'scss'
}

If you want to find out more on how you can use stylelint to lint preprocessor code, there’s a great section in its documentation dedicated to explaining just that.

Go Forth and Lint!

As you can see, stylelint has brought CSS linting a long way in a relatively short time. Its flexibility and breadth of rules means that you can set up a configuration that is as detailed or as hands off as you like, helping you to keep your styles more consistent, maintainable, and error free.

It’s my hope that more developers choose to make use of such an excellent tool; so try taking it for a spin. Your stylesheets will thank you for it.

Frequently Asked Questions (FAQs) about CSS Linting and Stylelint

What is the main difference between CSS Lint and Stylelint?

CSS Lint and Stylelint are both tools used for linting CSS code, but they have some key differences. CSS Lint is a tool that checks your CSS code for efficiency, redundancy, and potential browser compatibility issues. It’s a great tool for beginners as it helps to enforce good coding practices. However, CSS Lint is not customizable and it doesn’t support the latest CSS syntax.

On the other hand, Stylelint is a modern, powerful, and highly customizable linter that supports both CSS and SCSS. It allows you to write your own rules, making it a more flexible tool. Stylelint also supports the latest CSS syntax and CSS-in-JS styles, making it a more comprehensive tool for linting CSS code.

How can I customize Stylelint to suit my needs?

One of the biggest advantages of Stylelint is its high level of customizability. You can customize Stylelint by creating a configuration file where you can specify your own rules. This file can be a JSON file, a YAML file, or a JS file that exports a configuration object. You can specify the rules you want to apply, the severity of the rules, and even turn off certain rules if you wish. This allows you to tailor Stylelint to your specific coding style and requirements.

Can I use Stylelint for CSS-in-JS styles?

Yes, Stylelint supports CSS-in-JS styles. This is a significant advantage of Stylelint over other CSS linters. With the rise of JavaScript frameworks and libraries like React, Vue, and Angular, CSS-in-JS has become a popular styling technique. Stylelint’s support for CSS-in-JS means you can lint your styles no matter how they are written, ensuring consistency and quality across your codebase.

How does Stylelint help improve my CSS code?

Stylelint helps improve your CSS code in several ways. Firstly, it enforces consistency in your code, making it easier to read and maintain. Secondly, it helps to catch errors and potential issues before they become problems. This includes everything from syntax errors to performance issues. Finally, Stylelint encourages good coding practices, helping you to write cleaner, more efficient CSS code.

Is it difficult to set up Stylelint?

Setting up Stylelint is relatively straightforward. You can install it via npm, and then create a configuration file to specify your rules. Stylelint also provides a number of pre-defined rule sets that you can extend, making it easy to get started. If you’re using a code editor like VS Code, there are also extensions available that integrate Stylelint directly into your editor, providing real-time linting as you write your CSS code.

Can I use Stylelint with other pre-processors like Less or Sass?

Yes, Stylelint supports both Less and Sass, in addition to CSS. This means you can lint your pre-processed styles with the same tool, ensuring consistency across your codebase. Stylelint’s support for pre-processors also includes syntax-specific rules, allowing you to catch potential issues that are specific to these pre-processing languages.

How does Stylelint compare to other CSS linters in terms of performance?

Stylelint is a powerful and efficient linter. It’s built on PostCSS, a tool for transforming CSS with JavaScript, which is known for its high performance. This means Stylelint can lint your CSS code quickly, even for large codebases. However, the performance of Stylelint can also depend on the complexity of your rules and the size of your CSS files.

What are some common rules that I can enforce with Stylelint?

Stylelint comes with a wide range of rules that you can enforce. These include rules for formatting, such as indentation and line length, rules for syntax, such as disallowing certain properties or values, and rules for best practices, such as avoiding duplicate selectors or properties. You can also write your own rules, giving you complete control over your linting process.

Can I integrate Stylelint into my build process?

Yes, you can integrate Stylelint into your build process. Stylelint provides a CLI that you can use to lint your CSS files as part of your build process. This allows you to catch and fix issues before your code is deployed. You can also integrate Stylelint with other tools like webpack or gulp, making it a versatile tool for any development workflow.

Is there a community or resources where I can learn more about Stylelint?

Yes, there is a large and active community around Stylelint. The official Stylelint website provides comprehensive documentation, including a guide on how to get started, a list of all the available rules, and a guide on how to write your own rules. There are also numerous tutorials, blog posts, and StackOverflow questions where you can learn more about how to use Stylelint effectively.

Ashley NolanAshley Nolan
View Author

Ashley specialises in architecting large front-end projects and is passionate about emerging front-end technologies. He is the co-author of the Kickoff front-end framework and blogs over at ashleynolan.co.uk.

AdvancedCSScss-lintlintingLouisLsassstylelint
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week