Skip to content

Stylelint Plugin

A Stylelint plugin that validates SpiraCSS design rules in SCSS files.
Designed to be used with the SpiraCSS Design Principles.

Install

Stylelint v16 or later is required. Node.js >= 20 is required.

Terminal window
yarn add -D @spiracss/stylelint-plugin stylelint stylelint-scss postcss-scss
Terminal window
npm install -D @spiracss/stylelint-plugin stylelint stylelint-scss postcss-scss

Rules

RuleDescription
spiracss/class-structureNaming, parent-child structure, section structure
spiracss/property-placementProperty placement (container / item / internal)
spiracss/page-layerPage entry SCSS boundaries and component links
spiracss/interaction-scopeInteraction section placement and structure
spiracss/interaction-propertiesTransition / animation usage inside interaction
spiracss/keyframes-naming@keyframes placement and naming
spiracss/pseudo-nestingPseudo-class / pseudo-element nesting
spiracss/rel-comments@rel comments for parent-child links

For rule details (OK / NG examples), see the rule pages.

Configuration

This plugin reads spiracss.config.js at the project root.
Use createRules() to generate rule settings from the config.

Choose one configuration style depending on your project module system: CommonJS or ESM.

stylelint.config.js
const spiracss = require('@spiracss/stylelint-plugin')
const plugin = spiracss.default ?? spiracss
const { createRules } = spiracss
module.exports = {
plugins: [plugin, 'stylelint-scss'],
customSyntax: 'postcss-scss',
// Exclude shared partials; keep shared keyframes linted.
ignoreFiles: ['src/styles/partials/**/*.scss', '!src/styles/partials/keyframes.scss'],
rules: {
...createRules('./spiracss.config.js'),
'scss/at-rule-no-unknown': true
}
}

ESM projects

If package.json has "type": "module", use export default.

Passing config object directly

stylelint.config.js
import spiracssPlugin, { createRules } from '@spiracss/stylelint-plugin'
import spiracssConfig from './spiracss.config.js'
export default {
plugins: [spiracssPlugin, 'stylelint-scss'],
customSyntax: 'postcss-scss',
// Exclude shared partials; keep shared keyframes linted.
ignoreFiles: ['src/styles/partials/**/*.scss', '!src/styles/partials/keyframes.scss'],
rules: {
...createRules(spiracssConfig),
'scss/at-rule-no-unknown': true
}
}

Path-based loading

If you need path-based loading in ESM, use createRulesAsync().

stylelint.config.js
import spiracssPlugin, { createRulesAsync } from '@spiracss/stylelint-plugin'
const rules = await createRulesAsync('./spiracss.config.js')
export default {
plugins: [spiracssPlugin, 'stylelint-scss'],
customSyntax: 'postcss-scss',
// Exclude shared partials; keep shared keyframes linted.
ignoreFiles: ['src/styles/partials/**/*.scss', '!src/styles/partials/keyframes.scss'],
rules: {
...rules,
'scss/at-rule-no-unknown': true
}
}

Note: aliasRoots is required when using createRules() or createRulesAsync().

Disabling rules

There are two ways to disable or relax rules:

  1. Stylelint config: set a rule to null (always works).
module.exports = {
rules: {
...createRules('./spiracss.config.js'),
'spiracss/rel-comments': null // disable this rule
}
}
  1. spiracss.config.js: set stylelint.<rule>.enabled = false or adjust rule options (only when using createRules() / createRulesAsync()).
spiracss.config.js
export default {
stylelint: {
keyframes: { enabled: false },
pseudo: { enabled: false },
rel: { requireChild: false }
}
}

For detailed options, see Configuration Options.

Limitations

  • Validates structural elements (class names, selector structure, @rel comments)
  • Cannot automatically judge design decisions (Element chain intent, data/state validity)
  • Supplement with design reviews or code reviews

Recommended setup: stylelint-config-standard-scss + stylelint-config-recess-order.
The recommended config for that setup is documented in Tips.