Vize

Musea と CSS のルール

このページに、各ルールの目的・前提・設定と、省略のない悪い例・良い例をまとめています。変更箇所は行の色で示します。コードをコピーすると、ソースコード全体を取得できます。各例に現在の対応範囲も明記しています。

ルール 例 目的
css/no-display-none 悪い · 良い 表示切り替えに display: none を使う箇所で v-show を検討します。
css/no-hardcoded-values 悪い · 良い CSS に直接記述した値を CSS 変数にまとめます。
css/no-id-selectors 悪い · 良い 詳細度が高い CSS の ID セレクターを検出します。
css/no-important 悪い · 良い 通常のカスケードを上書きする !important を検出します。
css/no-utility-classes 悪い · 良い コンポーネント内でユーティリティクラスを定義する箇所を検出します。
css/no-v-bind-performance 悪い · 良い CSS v-bind() の実行時コストを検討するための警告です。
css/prefer-logical-properties 悪い · 良い 書字方向に対応する CSS の論理プロパティを使います。
css/prefer-nested-selectors 悪い · 良い 子孫セレクターを CSS のネスト構文でまとめます。
css/prefer-slotted 悪い · 良い slot や子コンポーネントに対する scoped CSS のセレクターを検査します。
css/require-font-display 悪い · 良い @font-face に font-display を指定します。
musea/no-empty-variant 悪い · 良い 内容のない variant ブロックを検出します。
musea/prefer-design-tokens 悪い · 良い CSS に直接記述した値が登録済みのデザイントークンの値に一致する場合、対応する CSS 変数で表現します。
musea/require-component 悪い · 良い art ブロックに対象の component を指定します。
musea/require-title 悪い · 良い art ブロックに title を指定します。
musea/unique-variant-names 悪い · 良い 同じ Art ファイル内の variant 名を一意にします。
musea/valid-variant 悪い · 良い variant ブロックに name を指定します。

全ルール · ルールのオプション · ESLint 移行対応表 · プロジェクトの検査 · 子への属性の継承

css/no-display-none

表示切り替えに display: none を使う箇所で v-show を検討します。

悪い例 · 良い例

既定の重大度: warning
プリセット: opinionated, nuxt
自動修正: なし。修正内容を確認してください
適用範囲: プレーン CSS の style ブロック(scss・sass・less・stylus のブロックは対象外)
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "css/no-display-none": "warn"
      }
    },
  },
});
vp run lint

悪い

このコンポーネントの p 要素を .message の CSS で非表示にし、テンプレートには表示条件を指定していません。

<template>
  <p class="message">Saved</p>
</template>

<style scoped>
.message {
  display: none;
}
</style>

良い

同じ p に v-show="isSaved" で表示条件を指定し、display: none を取り除きます。

<template>
  <p v-show="isSaved" class="message">Saved</p>
</template>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

css/no-hardcoded-values

CSS に直接記述した値を CSS 変数にまとめます。

悪い例 · 良い例

既定の重大度: warning
プリセット: opinionated, nuxt
自動修正: なし。修正内容を確認してください
適用範囲: プレーン CSS の style ブロック(scss・sass・less・stylus のブロックは対象外)
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "css/no-hardcoded-values": "warn"
      }
    },
  },
});
vp run lint

悪い

.button のスタイルで、余白の数値と 16 進数の色を宣言に直接指定しています。

<style scoped>
.button {
  padding: 12px 16px;
  color: #174ea6;
}
</style>

良い

余白と色を名前付きのカスタムプロパティで参照し、トークンとして管理できる形にします。

<style scoped>
.button {
  padding: var(--space-3) var(--space-4);
  color: var(--color-action-text);
}
</style>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

css/no-id-selectors

詳細度が高い CSS の ID セレクターを検出します。

悪い例 · 良い例

既定の重大度: warning
プリセット: opinionated, nuxt
自動修正: なし。修正内容を確認してください
適用範囲: プレーン CSS の style ブロック(scss・sass・less・stylus のブロックは対象外)
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "css/no-id-selectors": "warn"
      }
    },
  },
});
vp run lint

悪い

#submit で ID セレクターにスタイルを結び付けています。

<style scoped>
#submit {
  font-weight: 600;
}
</style>

良い

再利用できる .submit のクラスを使い、ID セレクターを取り除きます。

<style scoped>
.submit {
  font-weight: 600;
}
</style>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

css/no-important

通常のカスケードを上書きする !important を検出します。

悪い例 · 良い例

既定の重大度: warning
プリセット: opinionated, nuxt
自動修正: なし。修正内容を確認してください
適用範囲: プレーン CSS の style ブロック(scss・sass・less・stylus のブロックは対象外)
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "css/no-important": "warn"
      }
    },
  },
});
vp run lint

悪い

color に !important を付け、通常のカスケードの優先順位を上書きしています。

<style scoped>
.button {
  color: red !important;
}
</style>

良い

important を使わず、カスタムプロパティから色を参照します。

<style scoped>
.button {
  color: var(--button-color);
}
</style>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

css/no-utility-classes

コンポーネント内でユーティリティクラスを定義する箇所を検出します。

悪い例 · 良い例

既定の重大度: warning
プリセット: opinionated, nuxt
自動修正: なし。修正内容を確認してください
適用範囲: プレーン CSS の style ブロック(scss・sass・less・stylus のブロックは対象外)
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "css/no-utility-classes": "warn"
      }
    },
  },
});
vp run lint

悪い

.flex、.mt-4、.text-center のように、個々の見た目を名前にしたクラスを定義しています。

<style scoped>
.flex { display: flex; }
.mt-4 { margin-top: 1rem; }
.text-center { text-align: center; }
</style>

良い

コンポーネント固有の .my-component にスタイルをまとめます。

<style scoped>
.my-component { display: flex; margin-top: 1rem; }
</style>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

css/no-v-bind-performance

CSS v-bind() の実行時コストを検討するための警告です。

悪い例 · 良い例

既定の重大度: warning
プリセット: opinionated, nuxt
自動修正: なし。修正内容を確認してください
適用範囲: プレーン CSS の style ブロック(scss・sass・less・stylus のブロックは対象外)
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "css/no-v-bind-performance": "warn"
      }
    },
  },
});
vp run lint

悪い

変化する offset を SFC の CSS の v-bind() で参照しています。

<style scoped>
.card {
  transform: translateX(v-bind(offset));
}
</style>

良い

変化する transform を要素の style バインディングに直接指定します。

<template>
  <article :style="{ transform: `translateX(${offset}px)` }" class="card" />
</template>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

css/prefer-logical-properties

書字方向に対応する CSS の論理プロパティを使います。

悪い例 · 良い例

既定の重大度: warning
プリセット: opinionated, nuxt
自動修正: なし。修正内容を確認してください
適用範囲: プレーン CSS の style ブロック(scss・sass・less・stylus のブロックは対象外)
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "css/prefer-logical-properties": "warn"
      }
    },
  },
});
vp run lint

悪い

margin-left は文字の方向に関係なく物理的な左側を指定します。

<style scoped>
.panel {
  margin-left: 1rem;
}
</style>

良い

margin-inline-start を使い、インライン方向の開始側に余白を指定します。

<style scoped>
.panel {
  margin-inline-start: 1rem;
}
</style>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

css/prefer-nested-selectors

子孫セレクターを CSS のネスト構文でまとめます。

悪い例 · 良い例

既定の重大度: warning
プリセット: opinionated, nuxt
自動修正: なし。修正内容を確認してください
適用範囲: プレーン CSS の style ブロック(scss・sass・less・stylus のブロックは対象外)
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "css/prefer-nested-selectors": "warn"
      }
    },
  },
});
vp run lint

悪い

ルールをネストせず、子孫セレクター .card .title に親のセレクターも含めて指定しています。

<style scoped>
.card .title { color: red; }
</style>

良い

.title のルールを .card の中にネストし、親子のスタイルの関係を一か所にまとめます。

<style scoped>
.card { .title { color: red; } }
</style>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

css/prefer-slotted

slot や子コンポーネントに対する scoped CSS のセレクターを検査します。

悪い例 · 良い例

既定の重大度: warning
プリセット: opinionated, nuxt
自動修正: なし。修正内容を確認してください
適用範囲: プレーン CSS の style ブロック(scss・sass・less・stylus のブロックは対象外)
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "css/prefer-slotted": "warn"
      }
    },
  },
});
vp run lint

悪い

scoped の CSS で、スロットに渡された要素ではなく、スロットの挿入位置を表す slot を対象にしています。

<style scoped>
slot { color: red; }
</style>

良い

:slotted(.label) を使い、スロットに渡された .label クラスを持つ要素を対象にします。

<style scoped>
:slotted(.label) { color: red; }
</style>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

css/require-font-display

@font-face に font-display を指定します。

悪い例 · 良い例

既定の重大度: warning
プリセット: opinionated, nuxt
自動修正: なし。修正内容を確認してください
適用範囲: プレーン CSS の style ブロック(scss・sass・less・stylus のブロックは対象外)
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "css/require-font-display": "warn"
      }
    },
  },
});
vp run lint

悪い

font-face にフォントの参照先はありますが、font-display の方針を指定していません。

<style>
@font-face {
  font-family: "Inter";
  src: url("/inter.woff2") format("woff2");
}
</style>

良い

font-display: swap を追加し、代替フォントで表示した後、読み込まれたフォントへ切り替える方針を指定します。

<style>
@font-face {
  font-family: "Inter";
  src: url("/inter.woff2") format("woff2");
  font-display: swap;
}
</style>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

musea/no-empty-variant

内容のない variant ブロックを検出します。

悪い例 · 良い例

既定の重大度: warning
プリセット: none
自動修正: なし。修正内容を確認してください
適用範囲: Musea の .art.vue ファイルの art / variant / style
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "musea/no-empty-variant": "warn"
      }
    },
  },
});
vp run lint

悪い

name を primary にしているものの、variant の中身が空で、プレビューする内容がありません。

<art title="Button" component="./Button.vue">
  <variant name="primary" />
</art>

良い

variant の中に tone="primary" の Button を置き、Save を表示します。

<art title="Button" component="./Button.vue">
  <variant name="primary">
    <Button tone="primary">Save</Button>
  </variant>
</art>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

musea/prefer-design-tokens

CSS に直接記述した値が登録済みのデザイントークンの値に一致する場合、対応する CSS 変数で表現します。

悪い例 · 良い例

既定の重大度: warning
プリセット: none
自動修正: なし。修正内容を確認してください
適用範囲: Musea の .art.vue ファイルの art / variant / style
オプション: 型付きオプションと既定値を参照してください。

.art.vue ファイルと下記のデザイントークン一覧が必要です。任意の色からトークンを推測するルールではありません。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "musea/prefer-design-tokens": "warn"
      },
      "ruleOptions": {
        "musea/prefer-design-tokens": {
          "tokens": [
            {
              "path": "color.primary",
              "value": "#3b82f6",
              "tier": "semantic"
            }
          ]
        }
      }
    },
  },
});
vp run lint

悪い

art の例で、設定した primary のデザイントークンではなく、青の色を直接指定しています。

Button.art.vue

<art title="Button" component="Button">
<variant name="Primary"><Button /></variant>
</art>
<style scoped>
.button {
  color: #3b82f6;
}
</style>

良い

この例の設定に登録された --color-primary のトークンを参照します。

Button.art.vue

<art title="Button" component="Button">
<variant name="Primary"><Button /></variant>
</art>
<style scoped>
.button {
  color: var(--color-primary);
}
</style>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

musea/require-component

art ブロックに対象の component を指定します。

悪い例 · 良い例

既定の重大度: warning
プリセット: none
自動修正: なし。修正内容を確認してください
適用範囲: Musea の .art.vue ファイルの art / variant / style
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "musea/require-component": "warn"
      }
    },
  },
});
vp run lint

悪い

art に title はありますが、プレビューする component の指定がありません。

<art title="Button">
  <variant name="primary" />
</art>

良い

defineArt で ./Button.vue を art の component として指定します。

<script setup>
defineArt("./Button.vue", { title: "Button" });
</script>

<art>
  <variant name="primary" />
</art>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

musea/require-title

art ブロックに title を指定します。

悪い例 · 良い例

既定の重大度: error
プリセット: none
自動修正: なし。修正内容を確認してください
適用範囲: Musea の .art.vue ファイルの art / variant / style
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "musea/require-title": "error"
      }
    },
  },
});
vp run lint

悪い

art に Button.vue の指定はありますが、title がありません。

<art component="./Button.vue">
  <variant name="primary" />
</art>

良い

defineArt のオプションで title を Button にし、art ブロックのタイトルを指定します。

<script setup>
defineArt("./Button.vue", { title: "Button" });
</script>

<art>
  <variant name="primary" />
</art>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

musea/unique-variant-names

同じ Art ファイル内の variant 名を一意にします。

悪い例 · 良い例

既定の重大度: error
プリセット: none
自動修正: なし。修正内容を確認してください
適用範囲: Musea の .art.vue ファイルの art / variant / style
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "musea/unique-variant-names": "error"
      }
    },
  },
});
vp run lint

悪い

同じ art の二つの variant に primary の名前を使っています。

<art title="Button" component="./Button.vue">
  <variant name="primary" />
  <variant name="primary" />
</art>

良い

primary と secondary の別々の名前を指定します。

<art title="Button" component="./Button.vue">
  <variant name="primary" />
  <variant name="secondary" />
</art>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール

musea/valid-variant

variant ブロックに name を指定します。

悪い例 · 良い例

既定の重大度: error
プリセット: none
自動修正: なし。修正内容を確認してください
適用範囲: Musea の .art.vue ファイルの art / variant / style
オプション: ルール固有のオプションはありません。重大度とプリセットは設定できます。

設定(Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  vue: {
    linter: {
      "preset": "incremental",
      "rules": {
        "musea/valid-variant": "error"
      }
    },
  },
});
vp run lint

悪い

プレビューを識別する variant の name がありません。

<art title="Button" component="./Button.vue">
  <variant />
</art>

良い

variant に primary の name を指定します。

<art title="Button" component="./Button.vue">
  <variant name="primary" />
</art>

良い例は上記の設定でこのルールの診断が出ない例です。他のルールの診断は出る場合があります。

実装 · 全ルール