LoginSignup
3
2

More than 1 year has passed since last update.

ズボラでも綺麗なSCSSを書きたい!(Stylelint v15)

Last updated at Posted at 2022-11-09

はじめに

2023/3/28 追記 v15対応するように加筆修正しました。

私は、コードを書く上で、

  • 半角スペースがない!:angry:
  • ここは空行入れないと!:angry:
  • ここだけインデント違うんですけど!:angry:

とか、割と細かいところが気になります。

CSSに関して言えば、Hexは小文字にしたいし、0に単位はつけたくないし、1未満の値は0を頭につけたいし、プロパティの前には空行を入れたいし、プロパティ記述順も気にしたい。。。
メンテナブルなコードを常に書きたい(願望)

しかし、特にプロパティ記述順なんかは実際に書いているとなんだかんだブレるもので、なかなか統一するのは難しいものです。

そこで、私はStylelintを使っているのですが、最近Visual Studio Codeさんがversion 14に上げろ上げろ言うので、調べつつまとめてみました。

成し遂げたいこと

  • Stylelint v14 v15を導入する
    • v13使ってたらVSCodeに怒られたのでアップデートする
    • プロパティ記述順も揃える
  • Visual Studio CodeでSCSSを書く際、リアルタイムでエラーを出力して、保存時に直す

Stylelint v14の破壊的変更

開発環境にStylelint v13が導入されていましたが、何やらセキュリティ上の問題があったらしく、v14ではv13系から大きな変更が加わったようです。

  • the syntax option and automatic inferral of syntax were removed
    syntaxオプションとsyntax自動判定を削除
  • Node.js 10 support was dropped
    Node.js 10のサポートを終了
  • the rules deprecated in 13.7.0 were removed
    13.7.0で非推奨となったルールを削除
  • the configOverrides option was removed
    configOverridesオプションを削除
  • the function-calc-no-invalid rule was removed
    function-calc-no-invalidルールを削除

だそうです。

syntaxオプションとsyntax自動判定を削除

SCSSやSassなどの純粋なCSS以外に対して使用したい場合は、それらに対応するためのプラグインやカスタムsyntaxをインストールしなければならなくなりました。

Node.js 10のサポートを終了

Nodeは以下のバージョン以上を使います。

  • 12.20.0
  • 14.13.1
  • 16.0.0

13.7.0で非推奨となったルールを削除

非推奨ルールってなんやねんと思った方はこちらを参照ください。

configOverridesオプションを削除

代わりにoverridesプロパティを使います。

function-calc-no-invalidルールを削除

configファイルから上記ルールを削除する必要があります。

vscode-stylelintも変わった

むしろ知らなかったのですが、vscode-stylelint 0.x系はStylelintがバンドルされていたようで、これが無くなります。

また、1.x系は、最低でもStylelint 14を使用することが想定されているため、それ以前のバージョンのStylelintの使用はサポートしていません。
Stylelintはさっさと14系にした方が良さそうです。

Stylelint v15の変更

v15では以下の重要な変更がなされました。

  • スタイルルールの廃止
  • declaration-property-value-no-unknownルールの追加
  • processors設定プロパティを削除
  • Node.js 12のサポート終了
  • override.extendsの振る舞いを変更

スタイルルールの廃止

文体に関する76個のルールが非推奨となりました。

これにより、文体を整える機能はPrettierなどに任せて、Stylelintでは、文体以外のエラー回避と規約遵守を目的とするルールに重きを置いて開発が進められていく、とのことです。

v15では非推奨であることの警告が表示されるだけで、実際に使えなくなるわけではありませんが、次のメジャーリリース(恐らくv16のこと)で本格的に削除され、使えなくなるようです。
そのため、今のうちに文体に関するルールは削除しておくと良さそうです。

declaration-property-value-no-unknownルールの追加

このルール、CSSの仕様上存在しない不明なプロパティと値のペアをチェックするものです。
例えば、以下のようなものに対して反応します。
topプロパティには、<length><percentage>autoが許可されており、仕様上<color>を指定することはできないためです。

a {
  top: red;
}

processors設定プロパティを削除

CSS-in-JSなどのCSSコンテナをサポートするためのprocessors設定プロパティが削除されました。

Node.js 12のサポート終了

Node.js 12のサポートが終了したため、Stylelintでもサポートが終了しました。

overrides.extendsの動作変更

overrides.pluginsと同様に、overrides.extendsの動きがリプレースからマージに変更されました。

Stylelintの導入

インストール

まとめ

$ yarn add --dev stylelint stylelint-config-recommended-scss stylelint-order postcss@8

それぞれの説明

Stylelintを導入します。

$ yarn add --dev stylelint

SCSSを使っているので、stylelint-config-recommended-scssを導入します。
これは、avoid errorsのための最低限のルールをまとめたものです。

$ yarn add --dev stylelint-config-recommended-scss

プロパティ記述順をソートするため、stylelint-orderを導入します。
Bootstrapなどを参考にソート順を予め決められるものもありますが、気に入らなかったのでソートするためのモジュールだけインストールします。

$ yarn add --dev stylelint-order

postcss@8を導入します。
なんでやねんと思った方はこちらをご参照ください。

$ yarn add --dev postcss@8

syntaxとして登録する必要があるはずのpostcss-scssは、後述の拡張モジュールに含まれているためインストールしなくてOKです。

インストールが終わったら、Stylelintのconfigを記述します。

.stylelintrc
{
  "extends": [
    "stylelint-config-recommended-scss"
  ],
  "plugins": [
    "stylelint-order"
  ]
}

ルールの設定

筆者のこだわりも多く含むため、万人受けはしないかもしれませんが、一応記載します。

Stylelintのルール

"rules"に追記して、ちょっとカスタムします。

"alpha-value-notation": "number"

アルファ値を小数で表します。

"color-hex-length": "short"

16進数で短記法が使える場合は使います。

"length-zero-no-unit": true

値が0のとき、length単位は省略します。

"rule-empty-line-before": ["always-multi-line", {"ignore": ["after-comment", "first-nested"]}]

ルールの前に1行空けます。
ただし、コメントの後やネストの一番最初の行の場合は無視します。

"selector-class-pattern": "^(ly|bl|el|hp|un|js|is|)(_[a-zA-Z0-9]+)+(__[a-zA-Z0-9]+)?$"

セレクタクラスのパターンを指定します。

PRECSS向けの正規表現です。
※PRECSSは拡張性が売りなので、正規表現でガチガチに固めるのは良くないかも知れませんが一例として記載します。

FLOCSSだとこんな感じかと。

^(l|c|p|u)(-[a-z0-9]+)+(__[a-z0-9]+(-[a-z0-9]+)+)?(--[a-z0-9]+(-[a-z0-9]+)+)?$

"selector-pseudo-element-colon-notation": "double"

疑似要素セレクタにダブルコロンを用います。

"shorthand-property-no-redundant-values": true

ショートハンドプロパティ内の冗長な値を禁止します。

Order

rules
{
  "rules": {
    "order/properties-order": [
      "content",

      "display",
      "visibility",
      "overflow",
      "overflow-x",
      "overflow-y",
      "opacity",
      "clip-path",

      "flex",
      "flex-grow",
      "flex-shrink",
      "flex-basis",
      "flex-flow",
      "flex-direction",
      "flex-wrap",

      "grid",
      "grid-area",
      "grid-template",
      "grid-template-areas",
      "grid-template-rows",
      "grid-template-columns",
      "grid-row",
      "grid-row-start",
      "grid-row-end",
      "grid-column",
      "grid-column-start",
      "grid-column-end",
      "grid-auto-rows",
      "grid-auto-columns",
      "grid-auto-flow",
      "grid-gap",
      "grid-row-gap",
      "grid-column-gap",

      "gap",
      "row-gap",
      "column-gap",

      "place-content",
      "place-items",
      "place-self",
      "justify-content",
      "justify-items",
      "justify-self",
      "align-content",
      "align-items",
      "align-self",

      "order",

      "box-sizing",
      "position",
      "z-index",
      "top",
      "right",
      "bottom",
      "left",

      "transform",
      "transform-origin",

      "float",
      "clear",

      "margin",
      "margin-top",
      "margin-right",
      "margin-bottom",
      "margin-left",
      "padding",
      "padding-top",
      "padding-right",
      "padding-bottom",
      "padding-left",
      "width",
      "min-width",
      "max-width",
      "height",
      "min-height",
      "max-height",

      "border",
      "border-width",
      "border-style",
      "border-color",
      "border-top",
      "border-top-width",
      "border-top-style",
      "border-top-color",
      "border-right",
      "border-right-width",
      "border-right-style",
      "border-right-color",
      "border-bottom",
      "border-bottom-width",
      "border-bottom-style",
      "border-bottom-color",
      "border-left",
      "border-left-width",
      "border-left-style",
      "border-left-color",
      "border-radius",
      "border-top-left-radius",
      "border-top-right-radius",
      "border-bottom-right-radius",
      "border-bottom-left-radius",
      "border-image",
      "border-image-source",
      "border-image-slice",
      "border-image-width",
      "border-image-outset",
      "border-image-repeat",

      "outline",
      "outline-width",
      "outline-style",
      "outline-color",
      "outline-offset",

      "box-decoration-break",
      "box-shadow",

      "list-style",
      "list-style-position",
      "list-style-type",
      "list-style-image",

      "background",
      "background-color",
      "background-image",
      "background-repeat",
      "background-attachment",
      "background-position",
      "background-position-x",
      "background-position-y",
      "background-clip",
      "background-origin",
      "background-size",

      "filter",
      "mix-blend-mode",

      "text-align",
      "text-align-last",
      "vertical-align",
      "white-space",
      "text-decoration",
      "text-emphasis",
      "text-emphasis-color",
      "text-emphasis-style",
      "text-emphasis-position",
      "text-indent",
      "text-justify",
      "text-transform",
      "letter-spacing",
      "word-spacing",
      "text-outline",
      "text-transform",
      "text-wrap",
      "text-overflow",
      "text-overflow-ellipsis",
      "text-overflow-mode",
      "word-wrap",
      "word-break",
      "tab-size",
      "hyphens",

      "color",
      "text-shadow",
      "font",
      "font-family",
      "font-size",
      "font-weight",
      "font-style",
      "font-variant",
      "font-size-adjust",
      "font-stretch",
      "font-effect",
      "font-emphasize",
      "font-emphasize-position",
      "font-emphasize-style",
      "font-smooth",
      "line-height",
      "alignment-baseline",
      "baseline-shift",
      "dominant-baseline",
      "text-anchor",
      "word-spacing",
      "writing-mode",

      "fill",
      "fill-opacity",
      "fill-rule",
      "stroke",
      "stroke-dasharray",
      "stroke-dashoffset",
      "stroke-linecap",
      "stroke-linejoin",
      "stroke-miterlimit",
      "stroke-opacity",
      "stroke-width",
      "color-interpolation",
      "color-interpolation-filters",
      "color-profile",
      "color-rendering",
      "flood-color",
      "flood-opacity",
      "image-rendering",
      "lighting-color",
      "marker-start",
      "marker-mid",
      "marker-end",
      "mask",
      "shape-rendering",
      "stop-color",
      "stop-opacity",
      
      "table-layout",
      "empty-cells",
      "caption-side",
      "border-spacing",
      "border-collapse",

      "pointer-events",
      "quotes",
      "counter-reset",
      "counter-increment",
      "resize",
      "cursor",
      "nav-index",
      "nav-up",
      "nav-right",
      "nav-down",
      "nav-left",

      "transition",
      "transition-delay",
      "transition-timing-function",
      "transition-duration",
      "transition-property",
      "animation",
      "animation-name",
      "animation-duration",
      "animation-play-state",
      "animation-timing-function",
      "animation-delay",
      "animation-iteration-count",
      "animation-iteration-count",
      "animation-direction"
    ]
  }
}

Visual Studio Codeの設定

vscode-stylelintの設定

Stylelintの拡張機能をインストールします。

VSCodeのsetting.jsonを編集します。

  • デフォルトのVSCode組み込みのバリデーションを切る
  • stylelintの方を有効にする
  • stylelint.validateでSCSSも指定する
  • 保存時に自動でstylelint --fix
{
    "css.validate": false,
    "scss.validate": false,
    "stylelint.validate": ["css", "scss"],
    "stylelint.configFile": "./.stylelintrc",
    "editor.codeActionsOnSave": {
        "source.fixAll.stylelint": true
    },
}

まとめ

成し遂げたいことを成し遂げられました。ハッピー:relaxed:

「Stylelint v14が破壊的変更がある」ということを聞いていただけだったので、調べるきっかけになりました。
また、VSCodeの右下にひょこっと出てくる通知はちゃんと見ずに消しちゃうこともあるので、気をつけないとなと戒めました。

3
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2