Skip to content

Instantly share code, notes, and snippets.

@tak-dcxi
Last active January 29, 2026 01:39
Show Gist options
  • Select an option

  • Save tak-dcxi/7aa206f63944877b361fb232126919f3 to your computer and use it in GitHub Desktop.

Select an option

Save tak-dcxi/7aa206f63944877b361fb232126919f3 to your computer and use it in GitHub Desktop.
Draft: CSSのレビューの時に見ておくものリスト

Draft: CSSのレビュー時に確認しておくものリスト

マインドセット

  • 指摘をする際は、必ず「理由」と「解決策」をセットにする(「この書き方はダメです」だけではレビューにならない)。

  • [MUST] は、仕様・コーディング規約に反するもの/バグが起きているもの/将来的に深刻な問題になりそうなものを優先して扱う。次点として「改善したほうが良いもの」を挙げる。

  • 教義的になりすぎない。趣味嗜好が入りうる指摘は IMO として扱う。

    • 私は flex と grid の使い分けについて普段発信しているが、レビューでは挙動に問題がなければ基本的にコメントしない。
    • margin-inline などの論理プロパティを「左右ショートハンドのように扱う」ことに否定的な意見を見かけるが、私は許容している。
      • 前提として、通常フロー/flex/grid/コンテナクエリなど主要なレイアウト手法は、論理的な指定を前提として成立している。flex は縦書き(writing-mode: vertical-lr)になれば主軸が変わり、grid-template は RTL 環境ではセル順が逆転する。一方でメディアクエリ、translatebackground-position などは物理指定しか存在しない。このような環境下で marginpadding だけを取り上げて物理・論理を議論してもあまり意味がない。
      • これまで justify-content: flex-end を「右揃え」と呼んでも問題視されにくかったのに、marginpadding の論理プロパティに対して突然強く批判するのは不自然に感じる。もっと言うのであれば justify-content には right のような物理指定も存在するが、使用されているのを私は見たことがない。物理・論理に拘るのであればそのあたりにも言及するべきではないだろうか。
      • margin-inline: auto のような使い方であれば RTL 環境でも同じ結果になりやすく、問題化しにくい。縦書きは基本的にデザイン都合でしか発生しないため、考慮対象ではない。むしろ、ブロック軸の margin を不要に上書きしてしまう潜在的不具合を抑えられるなら多少の認識差があっても採用する価値がある。
      • なお、私自身は発信上のコードでは topinset-block-start とするなど、論理プロパティをなるべく優先して使っている。ただしこれは多言語対応のためというより、主要なレイアウト手法と整合させたいという私的な理由が大きく、他者に強制する意図はない。実務では他者にとって馴染みが深い物理プロパティを優先して使うこともある。
      • CSS の有識者が多く関わっている Tailwind でさえ、 v4 から mxmargin-inlinepypadding-block に置き換わっている。[https://tailwindcss.com/docs/margin]
  • 意図が読み取れない記述には [Q] を付けて、質問としてコメントする。

  • レビュイーが書いた CSS は、レビューを通した時点でレビュアーも責任を負うことを自覚する。

仕様やコーディングガイドラインに則っているか

  • プロジェクトでコーディングガイドラインが定められている場合は、それを厳守できているかを最優先で確認する。
  • タイポグラフィ、カラーパレット、ボーダー、エレベーション、アニメーションイージング、各種サイズ類などのデザイントークンで定められている定数は tokens (Sass 系の CSS 設計法では setting にあたる)ディレクトリにジャンル毎にファイルを作成してカスタムプロパティに保存する。なるべくそれを指定するように勧める。
    • tokens ディレクトリは CSS から参照できるデザインガイドとして活用する
  • line-height: 1.8 のような指定があった場合は、トークンとして定義されているものであればそれを使用するように指摘する。一方でデザイントークンとして定義されていない特異的なものであれば直書きを推奨する。

インデントやプロパティの記述順は揃っているか

  • 本来この種の整形はフォーマッター/リンターの責務であり、人間が手作業で揃える仕事ではない。ただし、何らかの事情で自動化が機能していない場合は指摘する。
  • プロパティ順は「統一されていること」自体が重要であり、方式そのものはプロジェクトの合意が取れていれば基本的に何でもよい。

プロジェクトで定められている動作環境を満たしているか

  • 例として「Safari は最新メジャーバージョンの 2 つ前の最新版までを動作対象とする」という前提があるなら、現時点で Safari 17.5 で未サポートの CSS を使っていないかを確認する。
  • ただし、プログレッシブ・エンハンスメントの範囲で利用でき、品質チェックでも問題になっていないのであれば指摘しない。
    • プログレッシブ・エンハンスメントとして利用可能なもの
      • 未サポート環境では従来どおりに表示され、サポート環境ではより良い体験を提供できるもの
      • 例:View Transition API、text-wrap: prettyword-break: auto-phrase、アニメーション目的の ::details-contentfield-sizing など
    • プログレッシブ・エンハンスメントとして利用しづらいもの
      • 未サポート環境で指定自体が無視されやすいアットルール、または表示崩れが大きくなりやすいレイアウト関連の機能
      • 例:スタイルクエリ、Anchor Positioning、position: absolute / fixed に対する place-selfsibling-index() / sibling-count() 関数など
  • さらに、Chrome が先行実装しがちな「既存プロパティの新仕様」にも注意する。Chrome 最新版でのみ確認していると、意図せず差分にハマる可能性がある。
    • display: block に対する justify-items / justify-self は現時点で Chrome のみ。レスポンシブで gridblock にロールバックする場合、justify-items / justify-self の定義が残ったままになっていないか確認する。
    • calc(40px / 1280px * 100vw) のような「単位付きの除算」は typed arithmetic と呼ばれ、近年各ブラウザでサポートが進みつつある。
      • ただし現時点では Firefox が未サポートで、Safari も 18.2 以降でのサポートに留まるため扱いづらい。利用は控える。
      • calc() 周りの仕様に詳しくない初学者が意図せず使ってしまうケースも積み上げポストなどで見かけるため、レビューでは特に注意する。
    • Chrome 145 から条件下で vw がスクロールバーを含まずに計算される挙動に変わった。:https://x.com/tak_dcxi/status/2012336570293248061
      • 一方で Safari / Firefox では従来どおり横スクロールが発生し得るため、width: 100vw の使用は避ける。
      • そもそも width: 100vw は多くの場合「不要」または「別手段で置き換え可能」なので、全コアブラウザでスクロールバーを含まずに計算される挙動に置き換わったとしてもコードスメルを減らす目的で指摘対象になり得る。

命名の規則に一貫性はあるか・衝突のリスクはないか

  • class やカスタムプロパティの命名に一貫性があるかを確認する。
    • ケバブケース/スネークケース/キャメルケースが混在していないか。
    • BEM とそれ以外の命名規則が混在していないか。
  • .title のような汎用的なエレメント名は Scoped CSS によってスコープされているか確認する。
  • コンポーネントの値を操作する API 的カスタムプロパティは、衝突防止と異なる API 的カスタムプロパティが混在した際に「どのコンポーネントのものか」が判別できるよう、--foreground のような汎用名ではなく --component-name--foreground のように対象をプレフィックスで表現する方針を勧める。
  • すべてがグローバル定義になる @keyframes も、衝突防止のためコンポーネント固有であれば同様にプレフィックスを付与することを勧める。
    • レビューで指摘しないが、最近は @keyframes など「ユーザーが命名する識別子」には -- を付けるように提案している。
      • 近年の CSS では、ユーザー定義の名前を明確に区別するために -- を強制する流れがある(例:anchor-nameanimation-timeline など)。
      • 「そのプロパティでは -- が必須か?」を個別に覚える必要が減る。
      • 将来 CSS 標準側のキーワードが増えても、衝突リスクを下げられる。
      • 自分が定義した名前だと即座に判別できる。
    • ただし、これは値として扱われる名前に関する話であり、@layer のように値に関係しないものであれば付与する必要はない。

不要な記述・上書きを行っていないか

  • 余計な指定があるほど、別セレクタ(ベースCSS/レイアウトプリミティブ/コンポーネント内の別ルール)とぶつかった際に「どれが勝つか」「どの値が残るか」が状況依存になり、期待通りに動かないケースが増える。
  • 不要な指定をすると、それを打ち消すための上書きに詳細度バトルが発生して修正コストが上がる可能性がある。
  • 「なんとなく指定してみる」でCSSを書くと、設計判断が共有されず、再現性のない実装になりがち。宣言ひとつひとつに「なぜそれが必要か」を説明できる状態にすること。

何にでも width: 100% / height: 100% が指定されていないか

  • 特に初心者の書く CSS にありがちなのが「とりあえず width: 100% をぶっこんでみる」というもの。
  • 原則として、<div><p> のように UA スタイルシートで display: block が適用される要素は、初期値(auto)のままで親要素の幅に自然に追従するため、多くのケースで width: 100% は不要である。
  • position: absolute / fixed が適用された要素は置換要素などを除きinset: 0 を指定した時点で利用可能幅いっぱいに広がるため、width: 100% を重ねて書く必要は <img> などを除き基本的にない。
  • height: 100% は無限ループ抑止の都合で「親要素の高さが明示されている」場合にしか期待通りに動作しない。min-height のような提案値では成立しない。
    • 後述するが、明示的な高さ指定そのものがアンチパターンになり得るため、安易な height 固定は避ける必要がある。
    • flex / grid アイテムは stretch が効いていれば height: 100% を書かなくても高さいっぱいになり得るため、不要な指定になりやすい。
  • width: 100% / height: 100% は無意味なだけではなく、ブラウザ差分を踏んで意図しないバグを誘発することがある。
    • 過去にあった事例:Safari では list-style-type が有効な <summary> の子要素で width: 100% を指定をすると不自然な改行が起こる、Firefox では height: 100% が適用された subgrid 要素で不自然な詰めが起こる可能性がある、など。
  • width: 100% は、外部表示形式を block にしても自然には広がらない置換要素(例:<img>)や、フォームパーツ(例:<button>)など「必要性が明確な対象」に限定して使う。
    • inline-block inline-flex のような外部表示形式が inline の要素に width: 100% を指定する場合は、外部表示形式を block に変更することも検討する。この場合は vertical-align の初期値 baseline によって生じる下部の空白の発生を抑えられるメリットもある。
  • 子要素を親要素の高さに揃えたいだけであれば、親要素に display: grid を指定するだけで stretch が働き達成できることが多い。
    • この方法なら min-height でも揃えられるため、「高さ固定」というアンチパターンを回避しやすい。
  • Tailwind を使っている場合、何にでも w-full / h-full を付与していないかを確認する。特に生成 AI の出力は乱用されがち。

副作用のあるショートハンドプロパティが乱用されていないか

  • ショートハンドは便利な一方で、ロングハンドで積み上げてきた設定が後からショートハンド指定によって意図せずリセットされることがあるため注意する。
  • 例:background: whitebackground-color だけでなく、背景に関する他のサブプロパティも既定値へ戻し得る。結果として、別箇所で設定していた背景画像・サイズ等を壊し、事故につながる可能性がある。
  • 横方向の中央寄せとして margin: 0 auto / margin: auto を学んだ人は多いだろうが、これらは「本来触る必要のない上下のマージン」まで 0 / auto に上書きするのと同等である。
    • 特に Every Layout で紹介される flow レイアウトとの相性が悪く、flow 側で意図していた margin を打ち消してしまう。
    • 代替として、先述したインライン軸だけを中央寄せする margin-inline: auto を提案できる。
  • すべてのショートハンドが NG というわけではない。
    • insetborder のように「すべての辺に任意の数値を与える」用途では問題になりにくい。
    • 指摘対象は、継承や複合的な既定値が絡み、リセット事故を招きやすいもの(例:backgroundfont など)に絞る。
  • 特に font は最悪のプロパティであり、リセット目的以外では使わない方針を伝える。

デフォルト値をむやみに再指定していないか

  • ここでいう「デフォルト」とは、CSS の初期値/UA スタイルシートの値/リセット CSS の値/ベース CSS の値を総称したもの。
  • 例:margin: 0<div> に対する display: block などを場当たり的に書いていないかを確認する。意図が薄い場合は設計の一貫性が崩れているサインになりやすい。
    • 「最初の要素だけ上マージンを打ち消す」目的なら、 :not(:first-child) やフクロウセレクタなどを使い、「最初の要素にだけ margin を適用しない」という設計を提案する。
  • ブレイクポイント下で値をデフォルトへロールバックしたい場合など、デフォルト値を明示する必要がある場合は IMO として unset / initial / revert / revert-layer を使い、どの次元へ帰りたいのかを明示するよう勧める。
    • ただし、display の CSS 上の初期値は <div> だろうが <p> だろうが一律 inline であるなど、基礎知識が前提になるため、レビュイーの習熟度に応じて指摘の強度は調整する。
  • :root / body に定義されているベースのタイポグラフィは、原則として継承を利用する。局所での再指定は必要最小限に抑える。

グローバルのCSSに「重い指定」が入っていないか確認する

  • ここでいう「重い指定」はパフォーマンスの重さではなく、影響範囲が大きく、結果として保守性の治安を悪化させやすい指定を指す。

ベースCSSの詳細度は極限まで下げられているか

  • ベースレイヤーで定義するタイプセレクタの詳細度が高いと、後からの上書きが難しくなり、破綻の原因になりやすい。
  • 例として、ベースレイヤーに次のような指定があるケースがある。
    a:link, 
    a:visited {
      color: var(--foreground-link);
    }
  • この指定の問題は、詳細度が高い点にある。a(タイプセレクタ)+ :link / :visited(擬似クラス)で詳細度は 0.1.1 になり、class 1つでは上書きできない。
    • その結果として、リンク色を変えるだけのために、 意味の薄いセレクタの組み合わせで詳細度を上げたり、最悪!important を付けるといった対応が増え、治安悪化を招きやすい。
  • 新規プロジェクトでは、まずカスケードレイヤー(@layer)の導入を検討する。
    • レイヤー設計が明確なら、上記のようなセレクタでも詳細度バトルが起きにくくなる。
  • カスケードレイヤーの導入が難しい場合は、ベースのタイプセレクタを原則 :where() で包み、詳細度を 0 に落とすことを推奨する。
    :where(a:any-link) {
      color: var(--foreground-link);
    }
  • ただし :where() には落とし穴もあり、サードパーティ製リセットCSS(例:destyle.css)が :where() を使っておらず、タイプセレクタの詳細度が残っている場合、リセット側が優先されてベースの指定が打ち消される可能性がある。そのため、リセットCSSは可能な限り kiso.css のように :where() によって詳細度が下げられているものを選定する。

ベースCSSで破壊的なプロパティが指定されていないか

  • display / position / margin など、レイアウトに関わるプロパティは非常に繊細で、色や文字周りのプロパティと比べて破壊的になりやすい。
  • 極端な例として、次のような発想は明確に危険だと理解できるだろう。
    • flex を多用するからと言って、div 全部に display: flex を付ける
    • position: absolute の相対先の指定が面倒だからと言って、全称セレクタに position: relative を付ける
  • 上記のような実装はさすがに見かけたことは無いものの、実際には次のような指定が紛れ込むことがある。
    • a をすべて inline-block にする
    • pmax-width を指定する
  • レイアウト系プロパティはコンテキストによって何を指定するか変動するのを覚えておく。ベースのスタイルでレイアウト系の定義が行われている場合、異なるコンテキストでは unset / revert が頻発して手間が増えたり、意図しない不具合を引き起こすといったリスクが高い。
  • レイアウト系プロパティは、リセットCSSで最低限の前提を整えた上で、さらに平坦化が必要な場合にのみ慎重に定義する。ベースでの特異な指定は避けるように伝える。

アクセシビリティを阻害する指定が入っていないか

  • 典型例は、リンクやインタラクティブ要素への outline: none。アウトラインを消すと、キーボード操作時にフォーカス位置が見えなくなり、アクセシビリティを阻害するためアンチパターンである。
    • 近年のUAスタイルではフォーカスリングは主に :focus-visible のときだけ表示されるため、クリック時に常時アウトラインが出る状況は基本的に起きにくい。
  • 「コーディングしやすいから」という理由で、デフォルトの line-height1 にするアプローチも見かけるが、これも擁護できないレベルのアンチパターンである。
    • デザイン上では1行でも、コンテンツ変動やレスポンシブで改行が発生しうる。フォント次第では行が重なり、読めなくなる可能性がある。
    • ベースでは、アクセシビリティの観点から line-height: 1.5 以上を基準に指定し、継承させるように進言する。
    • デザイン上どうしても line-height: 1 が必要な箇所があっても、text-box-trimcalc((1lh - 1em) / 2) でハーフレディングを算出して詰めるなどの代替手段は存在する。
    • レビュー時は line-height: 1 の指定は MUST で指摘する。
  • ダークモード対応が行われていないのに color-scheme: light dark を指定しているサイトも見かける。
    • 背景色やテキスト色の指定が不足していると、ダークモード時にシステムカラーが適用され、文字色と背景色が同化するなどの事故が起こりうる。
    • 海外製のリセットCSSやフレームワーク由来の可能性もあるが、ダークモード非対応なら color-scheme: light dark は取り除くよう指摘する。
    • 暗い背景のサイトであれば、<meta name="color-scheme" content="dark"> を設定するとよい。ユーザーの外観モードに左右されず、スクロールバーなども暗い見た目に寄り、体験の一貫性が上がる。
    • 明るい背景のサイトでは、color-scheme については特に何も指定しない方針で問題ない。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment