@morev/sass/no-unused-variables SASS-only
Reports SASS variables that are declared but not used.
.the-component {
$b: #{&};
$foo: #{$b}__foo; // ❌ Variable is unused
&__element {
#{$b}--active {
color: red;
}
}
}
Motivation
Defining variables that are never used leads to unnecessary noise, confusion, and potential maintenance issues during refactoring.
This rule helps keep your component code clean and intentional by reporting variables that:
- Are declared with a valid SASS syntax;
- Are never referenced within their corresponding scope or nested scopes;
- Are not explicitly ignored via configuration.
Rule options
All options are optional and have sensible default values.
// 📄 .stylelintrc.js
export default {
plugins: ['@morev/stylelint-plugin'],
rules: {
'@morev/sass/no-unused-variables': true,
}
}
// 📄 .stylelintrc.js
export default {
plugins: ['@morev/stylelint-plugin'],
rules: {
'@morev/sass/no-unused-variables': [true, {
ignore: ['b'],
messages: {
unused: (name) =>
`Found unused variable "${name}".`,
}
}],
}
}
Show full type of the options
type NoUnusedVariablesOptions = {
/**
* Whether variables declared at the root level should also be checked.
* By default, root-level variables are ignored,
* assuming they may be imported elsewhere.
*
* @default false
*/
checkRoot?: boolean;
/**
* A list of variable names to ignore (without leading `$`).
* Supports both exact string matches and wildcard patterns.
*
* @example ['my-var']
*
* @default []
*/
ignore?: Array<string | RegExp>;
/**
* Custom message functions for rule violations.
* If provided, overrides the default error messages.
*/
messages?: {
/**
* Custom message for an unused variable violation.
*
* @param name Variable name (with leading `$`).
*
* @returns The error message to report.
*/
unused?: (name: string) => string;
};
};
Show info about Stylelint-wide options
Every rule in this plugin also supports the standard Stylelint per-rule options (disableFix
, severity
, url
, reportDisables
, and message
), even though they are not explicitly reflected in the type definitions to avoid unnecessary noise.
Note: the message
option is technically available, but its use is discouraged: each rule already provides a typed messages
object, which not only offers IDE autocompletion but also supports multiline strings and automatically handles indentation.
For more information, see the official Stylelint configuration docs.
checkRoot
Whether variables declared at the root level should be checked.
/**
* @default false
*/
type CheckRootOption = boolean;
By default, the rule skips root-level variables, assuming they might be imported or used across multiple files. Enable this option if you want to enforce that all root-level variables are actually used within the same file.
Examples
// Config: [true, { checkRoot: true }]
// ❌ Root-level variable is unused
$foo: red;
.the-component {}
ignore
A list of variables to exclude from the unused check.
/**
* @default []
*/
type IgnoreOption = Array<string | RegExp>;
Supports:
- Exact matches by variable name (without
$
prefix in config) - Wildcard patterns using
*
- Regular expressions for advanced matching
TIP
The $
prefix is automatically handled by the rule - in the config, you only specify the name part.
INFO
If you want to use it together with the block-variable
rule, you need to set ignore: ['b']
to ensure consistency across all style files.
Examples
// Config: [true, { ignore: ['b'] }]
// ✅ Variable $b is ignored
.the-component {
$b: #{&};
}
// Config: [true, { ignore: ['-*'] }]
// ✅ Variables starting with `-` are ignored
.the-component {
$-foo: #{&};
$-bar: #{&};
}
// Config: [true, { ignore: [/.*foo.*/] }]
// ✅ Variables containing 'foo' are ignored
.the-component {
$foo: #{&};
$bar-foo: #{&};
}
messages
The rule provides built-in error messages for all violations it detects.
You can customize them using the messages
option. This can be useful to:
- Adjust the tone of voice to match your team's style;
- Translate messages into another language;
- Provide additional project-specific context or documentation links.
INFO
You don't need to override all message functions — or any of them at all.
Message function receives the detected unused variable name with leading $
as an argument.
Example
export default {
plugins: ['@morev/stylelint-plugin'],
rules: {
'@morev/sass/no-unused-variables': [true, {
messages: {
unused: (name) =>
`⛔ Unused variable "${name}" found.`,
},
},
}],
},
}
Show function signature
export type MessagesOption = {
/**
* Custom message for an unused variable violation.
*
* @param name Variable name (with leading `$`).
*
* @returns The error message to report.
*/
unused?: (name: string) => string;
};
How message formatting works
If your custom message function returns anything other than a string
(e.g., undefined
), the rule will automatically fall back to the default built-in message.
Additionally, all custom messages are automatically processed through stripIndent
function, so it's safe and recommended to use template literals (backticks, `
) for multiline messages without worrying about inconsistent indentation.
Additional notes
- The rule correctly tracks scope: nested variables can shadow outer ones.
- Escaped variables inside strings (e.g.,
"\\$var"
) or comments (e.g.,// $foo
) do not count as usage.