リストマーカーの「微妙なズレ」を許すな。プロが実践する完璧なアライメント制御術
フロントエンド開発の現場で、デザインカンプを忠実に再現しようとしたとき、一度は「リストのマーカー(・)」に殺意を覚えたことはないだろうか?
「行間を広げるとマーカーが上に浮く」「フォントサイズを変えるとマーカーとの距離が狂う」「ブラウザによって微妙に垂直位置がズレる」。
これらはCSSの `list-style-type` を安易に使っている限り、永遠に解決しない呪いだ。ブラウザのレンダリングエンジンは、マーカーの配置について「そこそこ」の仕事しかしてくれない。しかし、UXを突き詰める我々にとって「そこそこ」は「失敗」と同義だ。
今回は、この厄介なリストマーカーを完全に制御下に置くための、現場直結のテクニックを伝授しよう。
—
なぜ `list-style-type` は「詰み」なのか
まず、ブラウザの裏側で何が起きているかを理解する必要がある。
`list-style-type` は、ブラウザが `::marker` という特殊な擬似要素を生成することで描画される。厄介なのは、この `::marker` がボックスモデルの範疇外にあるということだ。`padding` や `margin` で微調整しようとしても、CSSの物理法則がうまく働かない場面が多い。
特に、テキストが複数行にわたる場合、マーカーが1行目のベースラインに固定されてしまう仕様が、UI上の致命的なズレを引き起こす。これを「標準仕様だから」と片付けるのは、プロの仕事ではない。
—
現場で通用する「マーカー完全制御」のベストプラクティス
結論から言えば、「 `list-style` を捨てて、 `::before` で疑似要素を作り、自身で制御する」のが最も堅実かつ柔軟な解だ。これなら、フォントサイズが変わろうが、行間が広がろうが、レイアウトが崩れることはない。
以下は、私がプロダクション環境で常用している、メンテナンス性の高いスニペットだ。
.custom-list {
list-style: none; / ブラウザ標準のマーカーを無効化 /
padding-left: 0;
}
.custom-list li {
position: relative;
/ マーカー分のスペースを左側に確保 /
padding-left: 1.5em;
line-height: 1.6;
}
.custom-list li::before {
content: “●”; / ここを好きなアイコンや記号に変える /
position: absolute;
left: 0;
/ 垂直位置を微調整:top: 0 ではなく計算値で制御 /
top: 0;
font-size: 0.8em; / テキストより少し小さくするのがコツ /
color: #333;
/ マーカーとテキストのベースラインを揃えるための調整 /
display: inline-flex;
align-items: center;
height: 1.6em; / liのline-heightと合わせると垂直中央揃えが容易 /
}
このコードが「勝てる」理由
1. `display: inline-flex` の活用: マーカーを Flex コンテナにすることで、`align-items: center` が機能する。これにより、行の高さがどれだけ変わろうと、マーカーは常に垂直方向の中央を維持する。
2. マジックナンバーを排除: `line-height` と `height` を同期させることで、数値の変更に追従する柔軟なレイアウトを実現している。
3. アクセシビリティ: `::before` はスクリーンリーダーに読み上げられないことが多いため、重要な情報であれば `aria-label` を検討するか、そもそも装飾目的のみに使用するのが鉄則だ。
—
dl/dt/dd で「記述リスト」を正しく扱う時の注意点
`ul`/`li` だけでなく、定義リスト `dl` を使う場面も多いはずだ。ここでも同様のことが言える。特に `dt` と `dd` の関係性において、マーカーや装飾を当てたい場合、親要素のレイアウトコンテキストが重要になる。
もし、定義リストでマーカー的な役割を果たすアイコンを置くなら、`grid` を使うのが今の時代の正解だ。
.description-list {
display: grid;
/ dtとddの幅を定義。これでマーカー位置が完璧に揃う /
grid-template-columns: 2em 1fr;
gap: 0.5rem;
}
.description-list dt::before {
content: “✓”;
color: #007bff;
}
`grid` を使えば、マーカー(`dt::before`)の幅を `2em` と固定し、テキスト部分を `1fr` とすることで、マーカーの位置が1ピクセルもブレないレイアウトが完成する。
—
最後に:完璧主義のその先へ
正直に言おう。ここまでやるのは面倒だ。しかし、この「たった数ピクセルのズレ」にこだわる姿勢こそが、あなたの作るUIに「洗練された空気感」を宿す。ユーザーは無意識のうちに、その「整然とした心地よさ」を感じ取っているのだ。
次回のコードレビューで、もし誰かが `list-style-type: disc` を使ってレイアウト崩れに苦戦していたら、黙ってこの手法を教えてあげてほしい。技術的な正しさはもちろん、細部へのこだわりこそが、一流のエンジニアを定義するのだから。
それでは、また次回のコードでお会いしよう。

コメント