sass-lint vs stylelint
CSS and Sass Linting Strategies for Modern Frontend Architectures
sass-lintstylelintSimilar Packages:

CSS and Sass Linting Strategies for Modern Frontend Architectures

sass-lint and stylelint are both tools designed to analyze stylesheet code for errors, stylistic inconsistencies, and potential bugs. sass-lint was historically the go-to choice specifically for Sass and SCSS projects, offering rules tailored to Sass syntax features like mixins and nested selectors. However, it is now deprecated and no longer maintained. stylelint is the modern, community-driven standard for linting all CSS dialects, including standard CSS, Less, SCSS, and SugarSS. It features a powerful plugin architecture, auto-fixing capabilities, and active development, making it the robust choice for current and future projects.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
sass-lint01,746-2727 years agoMIT
stylelint011,506961 kB13614 days agoMIT

sass-lint vs stylelint: The End of an Era and the Rise of the Standard

In the world of frontend architecture, maintaining consistent styling code is just as critical as maintaining JavaScript logic. For years, developers debated between specialized linters and general-purpose ones. Today, that debate is effectively over. Let's look at why stylelint has become the undisputed standard and why sass-lint should be removed from your dependency list immediately.

🛑 Maintenance Status: Active Evolution vs. Archived Legacy

The most important factor in choosing a tool is whether it will be there tomorrow.

sass-lint is officially deprecated. The maintainers have archived the repository and marked the npm package as deprecated. This means no new features, no fixes for false positives, and no support for newer Sass syntax. Relying on it is a risk to your build stability.

# npm warning you will see today
npm warn deprecated sass-lint@1.12.1: This project is deprecated. Please use stylelint instead.

stylelint is actively maintained by a large community. It releases regular updates to support new CSS specifications, fix bugs, and improve performance. It is backed by major industry players and integrates seamlessly with modern editor tooling.

# stylelint is the current standard
npm install --save-dev stylelint stylelint-config-standard

⚙️ Configuration: Rigid Rules vs. Modular Plugins

Configuring a linter should be flexible enough to match your team's specific needs without forcing a complete rewrite when requirements change.

sass-lint used a single, monolithic configuration file (.sass-lint.yml). While simple for small projects, it lacked modularity. Adding custom rules often required writing complex JavaScript files that were hard to share across teams.

# sass-lint: .sass-lint.yml (Legacy approach)
options:
  formatter: stylish
rules:
  indentation:
    - 2
    - size: 2
  no-duplicate-properties:
    - 2
  # Adding a custom rule required complex setup

stylelint uses a modular, plugin-based configuration (usually .stylelintrc.json or stylelint.config.js). You can extend shared configs (like stylelint-config-standard) and layer your own rules on top. This makes it easy to onboard new projects and share standards across an organization.

// stylelint: .stylelintrc.json (Modern approach)
{
  "extends": "stylelint-config-standard",
  "rules": {
    "indentation": 2,
    "no-duplicate-properties": true,
    "selector-class-pattern": "^[a-z][a-zA-Z0-9]*$"
  },
  "plugins": ["stylelint-scss"]
}

🎯 Syntax Support: Sass-Only vs. Universal CSS

Your tooling should adapt to your stack, not force your stack to adapt to it.

sass-lint was built exclusively for Sass and SCSS. If your project introduced a plain CSS file or a Less file, sass-lint would either ignore it or crash. This created silos where different parts of your codebase had different quality gates.

// sass-lint: Only works here
.my-mixin {
  @include border-radius(4px); // Specific Sass syntax
}

stylelint is universal. Out of the box, it handles standard CSS. With the official stylelint-scss plugin, it fully supports SCSS and Sass syntax, including variables, mixins, and functions. It can also lint Less, SugarSS, and even CSS-in-JS via specific processors. This allows a single linting command to cover your entire frontend codebase.

// stylelint + stylelint-scss: Works here AND in plain CSS
.my-class {
  @include border-radius(4px); // Linted correctly with plugin
  color: var(--main-color);    // Linted correctly as standard CSS
}

🛠️ Auto-Fixing: Manual Cleanup vs. Instant Repair

Developer experience is heavily influenced by how much time you spend fixing trivial errors.

sass-lint did not support auto-fixing. If the linter found 50 indentation errors or missing semicolons, you had to fix them manually. This friction often led developers to disable rules or ignore warnings entirely.

# sass-lint: Only reports errors
$ sass-lint -v
src/styles.scss
  5:3  error  Indentation expected to be 2 spaces  indentation
  # Developer must open file and fix manually

stylelint includes a powerful --fix flag that automatically resolves many common issues, such as indentation, whitespace, and sorting. This saves hours of manual work and ensures consistent formatting without debate.

# stylelint: Report AND fix
$ stylelint "src/**/*.scss" --fix
# Automatically corrects indentation, removes duplicates, etc.

🌐 Real-World Integration Scenarios

Scenario 1: Migrating a Legacy Sass Project

You have a large codebase using .scss files and an old .sass-lint.yml config.

  • Action: Remove sass-lint. Install stylelint, stylelint-scss, and stylelint-config-standard-scss.
  • Why: You get immediate access to modern rules and auto-fixing while keeping full support for your existing Sass syntax.
// package.json scripts update
{
  "scripts": {
    "lint:css": "stylelint \"src/**/*.scss\" --custom-syntax postcss-scss"
  }
}

Scenario 2: Monorepo with Mixed Styling Technologies

Your monorepo contains a React app (CSS Modules), a Vue app (SCSS), and a shared UI library (Less).

  • Action: Use stylelint with specific overrides for each folder.
  • Why: sass-lint cannot handle this diversity. stylelint allows you to apply different rule sets to different file types within a single command.
// stylelint.config.js in monorepo root
module.exports = {
  overrides: [
    {
      files: "**/*.scss",
      customSyntax: "postcss-scss",
      rules: { /* SCSS specific rules */ }
    },
    {
      files: "**/*.less",
      customSyntax: "postcss-less",
      rules: { /* Less specific rules */ }
    }
  ]
};

Scenario 3: CI/CD Pipeline Enforcement

You need to block merges if styling standards are violated.

  • Action: Run stylelint in strict mode in your CI pipeline.
  • Why: Because stylelint is actively maintained, it won't break unexpectedly due to Node.js version updates, unlike the abandoned sass-lint.
# .github/workflows/lint.yml
- name: Lint Styles
  run: npx stylelint "src/**/*.{css,scss}" --formatter github

📊 Summary: Key Differences

Featuresass-lintstylelint
Status🔴 Deprecated / Archived🟢 Active / Standard
Syntax SupportSass/SCSS onlyCSS, SCSS, Less, SugarSS, CSS-in-JS
Auto-Fix❌ No✅ Yes (--fix)
Config FormatYAML (Rigid)JSON/JS (Modular & Extensible)
EcosystemDead🌱 Massive (Plugins, Shared Configs)
Recommendation❌ Remove Immediately✅ Use for All Projects

💡 The Bottom Line

There is no longer a technical trade-off to consider here. sass-lint served a purpose in the past when tooling for Sass was fragmented, but that time has passed.

sass-lint is a legacy tool that introduces risk. It should be treated as technical debt. If you see it in a package.json, plan a migration sprint to remove it.

stylelint is the professional choice. It offers the flexibility to handle any stylesheet language, the power to auto-fix errors, and the security of an active community. For any architect making decisions today, stylelint is the only logical path forward for ensuring code quality and consistency in your stylesheets.

How to Choose: sass-lint vs stylelint

  • sass-lint:

    Do NOT choose sass-lint for any new project or active codebase. This package has been officially deprecated and archived by its maintainers, meaning it receives no security updates, bug fixes, or support for modern Sass features. Using it introduces technical debt and risks breaking your build pipeline as dependencies age. If you are currently using it, you should plan an immediate migration to stylelint.

  • stylelint:

    Choose stylelint for virtually every scenario, whether you are writing plain CSS, SCSS, Less, or using CSS-in-JS. It is the only actively maintained option with a vast ecosystem of shared configurations and plugins. Select stylelint if you need reliable auto-fixing, integration with modern build tools (like Vite or Webpack), and the ability to enforce consistent styling rules across a large team. Its flexibility allows you to start with a preset and gradually add custom rules as your project grows.

README for sass-lint

Sass Lint npm version Build Status Coverage Status Dependency Status Dev Dependency Status

A Node-only Sass linter for both sass and scss syntax!


Install

You can get sass-lint from NPM:

Install globally

npm install -g sass-lint

To save to a project as a dev dependency

npm install sass-lint --save-dev

Configuring

Sass-lint can be configured from a .sass-lint.yml or .sasslintrc file in your project. The .sasslintrc file can be in either JSON format or YAML. Both formats are interchangeable easily using tools such as json2yaml. If you don't either file in the root of your project or you would like all your projects to follow a standard config file then you can specify the path to one in your project's package.json file with the sasslintConfig option.

For example:

{
  "name": "my-project",
  "version": "1.0.0",
  "sasslintConfig": "PATH/TO/YOUR/CONFIG/FILE"
}

Use the Sample Config (YAML) or Sample Config (JSON) as a guide to create your own config file. The default configuration can be found here.

Configuration Documentation

Migrating from SCSS-Lint: If you already have a config for SCSS-Lint, you can instantly convert it to the equivalent Sass Lint config at sasstools.github.io/make-sass-lint-config.

Options

The following are options that you can use to config the Sass Linter.

  • cache-config - Allows you to cache your config for a small speed boost when not changing the contents of your config file
  • config-file - Specify another config file to load
  • formatter - Choose the format for any warnings/errors to be displayed
  • merge-default-rules - Allows you to merge your rules with the default config file included with sass-lint
  • output-file - Choose to write the linters output to a file

Files

The files option contains two properties, include and ignore. Both can be set to either a glob or an array of glob strings/file paths depending on your projects' needs and setup.

For example below we are providing a singular glob string to our include property and an array of patterns to our ignore property:

files:
  include: 'sass/**/*.s+(a|c)ss'
  ignore:
    - 'sass/vendor/**/*.scss'
    - 'sass/tests/**/*.scss'

As mentioned you can also provide an array to the include property like so

files:
  include:
    - 'sass/blocks/*.s+(a|c)ss'
    - 'sass/elements/*.s+(a|c)ss'
  ignore:
    - 'sass/vendor/**/*.scss'
    - 'sass/tests/**/*.scss'

Rules

For all rules, setting their severity to 0 turns it off, setting to 1 sets it as a warning (something that should not be committed in), and setting to 2 sets it to an error (something that should not be written). If a rule is set to just a severity, it will use the default configuration (where available).

If you want to configure options, set the rule to an array, where the first item in the array is the severity, and the second item in the array is an object including the options you would like to set.

Here is an example configuration of a rule, where we are specifying that breaking the indentation rule should be treated as an error (its severity set to two), and setting the size option of the rule to 2 spaces:

rules:
  indentation:
    - 2
    -
      size: 2

Rules Documentation


Disabling Linters via Source

Special comments can be used to disable and enable certain rules throughout your source files in a variety of scenarios. These can be useful when dealing with legacy code or with certain necessary code smells. You can read the documentation for this feature here.

Below are examples of how to use this feature:

Disable a rule for the entire file

// sass-lint:disable border-zero
p {
  border: none; // No lint reported
}

Disable more than 1 rule

// sass-lint:disable border-zero, quotes
p {
  border: none; // No lint reported
  content: "hello"; // No lint reported
}

Disable a rule for a single line

p {
  border: none; // sass-lint:disable-line border-zero
}

Disable all lints within a block (and all contained blocks)

p {
  // sass-lint:disable-block border-zero
  border: none; // No result reported
}

a {
  border: none; // Failing result reported
}

Disable and enable again

// sass-lint:disable border-zero
p {
  border: none; // No result reported
}
// sass-lint:enable border-zero

a {
  border: none; // Failing result reported
}

Disable/enable all linters

// sass-lint:disable-all
p {
  border: none; // No result reported
}
// sass-lint:enable-all

a {
  border: none; // Failing result reported
}

CLI

Sass Lint v1.1.0 introduced the ability to run Sass Lint through a command line interface. See the CLI Docs for full documentation on how to use the CLI.

There are small differences which are useful to understand over other CLI tools you may have encountered with other linters.

By default any rule set to severity: 2 in your config will throw an error which will stop the CLI on the first error it encounters. If you wish to see a list of errors and not have the CLI exit then you'll need to use the -q or --no-exit flag.

Warnings or any rule set to severity: 1 in your config by default will not be reported by the CLI tool unless you use verbose flag -v or --verbose.

With this in mind if you would like to have the CLI show both warnings and errors then at the very least your starting point to use the cli should be the following command. sass-lint -v -q

CLI Examples

Specify a config

Below is an example of the command being used to load a config -c app/config/.sass-lint.yml file, show errors and warnings on the command line, and target a glob pattern **/*.scss:

sass-lint -c app/config/.sass-lint.yml '**/*.scss' -v -q

or with long form flags

sass-lint --config app/config/.sass-lint.yml '**/*.scss' --verbose --no-exit

Including multiple source destinations

By default when specifying a directory/file to lint from the CLI you would do something similar to the following

sass-lint 'myapp/**/*.scss' -v -q

or with long form flags

sass-lint 'myapp/**/*.scss' --verbose --no-exit

Notice that you need to wrap glob patterns in quotation marks

If you want to specify multiple input sources then you need to include a single comma and a space , to separate each pattern as shown in the following

sass-lint 'myapp/dir1/**.*.scss, myapp/dir2/**/*.scss' -v -q

or with long form flags

sass-lint 'myapp/dir1/**.*.scss, myapp/dir2/**/*.scss' --verbose --no-exit

If you don't include the extra space after the comma then the multiple patterns will not be interpreted correctly and you could see sass-lint fail.

Ignore files/patterns

To add a list of files to ignore tests/**/*.scss, dist/other.scss into the mix you could do the following:

sass-lint -c app/config/.sass-lint.yml '**/*.scss' -v -q -i 'tests/**/*.scss, dist/other.scss'

or with long form flags

sass-lint --config app/config/.sass-lint.yml '**/*.scss' --verbose --no-exit --ignore 'tests/**/*.scss, dist/other.scss'

Notice that glob patterns need to be wrapped in quotation or single quote marks in order to be passed to sass-lint correctly and if you want to ignore multiple paths you also need to wrap it in quotation marks and separate each pattern/file with a comma and a space , .

This will be revisited and updated in sass-lint v2.0.0.

For further information you can visit our CLI documentation linked below.

CLI Documentation


Front matter

Certain static site generators such as Jekyll include the YAML front matter block at the top of their scss file. Sass-lint by default checks a file for this block and attempts to parse your Sass without this front matter. You can see an example of a front matter block below.


---
# Only the main Sass file needs front matter (the dashes are enough)
---

.test {
  color: red;
}


Contributions

We welcome all contributions to this project but please do read our contribution guidelines first, especially before opening a pull request. It would also be good to read our code of conduct.

Please don't feel hurt or embarrassed if you find your issues/PR's that don't follow these guidelines closed as it can be a very time consuming process managing the quantity of issues and PR's we receive. If you have any questions just ask!


Creating Rules

Our AST is Gonzales-PE. Each rule will be passed the full AST which they can traverse as they please. There are many different node types that may be traversed, and an extensive API for working with nodes. The file of the rule must have the same name as the name of the rule. All of the available rules are in our rules directory. Default options will be merged in with user config.


Task Runner Integration

Module Bundler Integration

IDE Integration