ピクセルパーフェクトの奥にある本質を見よう
Published
数年前プチ論争になったこの話題。火の消えた頃合いを見計らって今回はピクセルパーフェクトについて自分の考えるところを書いていきたいと思います。
話を進めるうえでの前提
ピクセルパーフェクトの定義
ここでは「デザイナーが作成したデザインカンプに対して1pxの誤差もなく実装がされること」をピクセルパーフェクトとして話を進めたいと思います。
事業形態
ここでは「自社でサービスを展開、開発を行っている」ことを前提にしたいと思います。Web制作会社など「案件を受注して納品することがゴール」としている企業を前提としてしまうと、成果物に対して明確な要件があるのでその場合はクライアントが「ピクセルパーフェクトじゃないと受け取れません」と言えばそこで話は終わりなので、自社開発をしている企業を前提にします。
ピクセルパーフェクトに実装するということ
自分はフロントエンドエンジニアで、業務ではデザイナーさんが作ってくれたデザインカンプをもとにコーディングをしています。デザイナーさん側もリソースは有限なのでデザインカンプは多くてもスマホ、タブレット、PCの3パターンくらいです。一方で令和となったこの時代、ユーザーが使うデバイス、画面サイズ、ブラウザは多岐にわたります。そんな中、渡されたデザインカンプをもとに我々エンジニアは実装をするわけですが、前述の通りユーザーがその画面を見る環境というのは様々でなので、エンジニア的にはデザインカンプがスマホ(480px)、タブレット(768px)、PC(1024px)というサイズで渡されたとしても「500pxのときは?2560pxのときは?」など画面サイズが連続的な値をとる以上それに耐えられるような実装にするわけです。これはつまり、各要素に対して柔軟な値を指定することになるのでサイズを固定値で指定するようなピクセルパーフェクトの考え方とは相性が悪いということになります。
ピクセルパーフェクトじゃないって怒られるケース
これまでの話だけだと「ピクセルパーフェクト何がそんなに不都合なの?」と思われてしまうので具体例とともに説明したいと思います。
今回作成するのは Figma で作成された以下のコンポーネントです。

ちょっと上手くSS撮れなかったので必要な情報をピックアップすると
- テキストサイズ : 16px
- line-height : 1.3
- padding : 上下10px、左右16px
- 灰色の四角のサイズ : 高さ41px、幅80px
という感じです。
この要件を満たすコンポーネントを実装するには以下の2パターンが考えられると思います。
① padding で幅と高さを出す方針
自分が実装するとしたらこの方針です。おそらく同じ考えの方も多いのではないでしょうか?
この方針で実装した場合はこんな感じになるかと思います。(実装例は React のコンポーネントをイメージしています)
<div
style={{
backgroundColor: '#CACACA',
padding: '10px 16px',
lineHeight: 1.3,
}}
>
<p>テスト</p>
</div>

devtools から確認してもやりたいことはできていそうです。
ただこれをやるとデザイナーさんから「幅と高さが違いますけど。。。」と言われることがあるかと思います。
たしかに実装したグレーの四角のサイズを見てみると高さが 40.8px、幅が 79.2pxとなっていて、Figma と比較すると高さが 0.2px、幅が 0.8px ズレています。

エンジニア的にはデザイン通りに実装したはずがなぜこんなことが起きるのでしょうか?それは lineHeight=1.3 という値が関係しています。今回は fontSize=16px なのでハーフレディングを含めたテキストの高さは小数を含む幅になります。(参考 : 【CSS】知っておきたい! line-heightの使い方)
実際に p 要素のサイズを確認してみると小数を含むサイズがここからきていることが確認できます。

ピクセルパーフェクトを目指すにあたって高さや幅が違うのは話にならないのでエンジニアは泣く泣く別の方針で実装することになります。(この時点でデザイナーさんと話し合うべきみたいな意見は話が脱線してしまうのでスルーします)
ちなみにこれ、サイズが合わなくなるのは Figma 上でのコンポーネントの作り方も原因だと思うのですが上手く作れる方法があったら教えていただけると助かります🙏
② 高さと幅を固定する方針
今回は幸いなことに上下、左右の padding がそれぞれ同じなので高さと幅を固定してその上下左右中央にテキストを置けば要件は満たされるという考え方です。
<div
style={{
backgroundColor: '#CACACA',
display: 'grid',
placeItems: 'center',
height: '41px',
width: '80px',
lineHeight: 1.3,
}}
>
<p>テスト</p>
</div>


サイズはバッチリです。
ただこれも p 要素が小数を含む値になっているのは変わらないので厳密にはピクセルパーフェクトの実装になっていません。この場合はデザインカンプ上の padding にあたる「四角の枠線からテキストまでの距離」が違います。ただ自分の経験上、この問題点はデザイナーさんからはかなりの確率でスルーされます。なぜならこのコンポーネントには padding という概念がないためその値を確認できないからです。1 px にも満たないような誤差は視覚的には判別が難しいので誰もそれに気付かずチェックを通過してしまうのです。
まぁ、何はともあれ高さと幅がデザインカンプと一致したので「ピクセルパーフェクトで実装できました」となるかと思います。
ピクセルパーフェクトで UI が崩壊するケース
鋭い方はもう分かっているかと思いますが、先ほど大団円を迎えた②の実装だと簡単に UI が崩壊してしまいます。
テキスト幅が予想を超えるケース
これはテキストが何らかの影響によって親要素(今回で言うグレーの四角)のサイズを超えたときに UI が崩壊します。「今回のコンポーネントだとテキストは固定だし、テキスト幅が親要素を超えることなんてある?」と思う方もいるかもしれませんが、自分が経験した例だと Windows だと UI が崩れるというのがありました。デザインカンプでは Mac で使われるヒラギノフォントが使われていて開発も Mac で行っているためそのままピクセルパーフェクトで実装、Windows だとメイリオフォントが使われていて、メイリオの方がテキストの横幅が大きいためテキストが親要素に収まらず UI 崩れが発生したケースです。親要素はピクセルパーフェクトのために高さと幅が固定値で固定されているため子要素に合わせて柔軟にサイズを変えることができないんですよね。
以下は無理矢理テキストが親要素を超える状態を作ってみた例です。

今回のケースだとグレーの四角にそこそこの大きさがあるため2行の表示まで耐えられるようになっていますが、3行目以降はテキストが親要素からはみ出して UI が崩れてしまっています。仮に親要素が子要素に対してギリギリの大きさでデザインが作られていた場合は前述のようにフォントによる違いから少し文字サイズが大きくなってテキストが改行されてしまっただけでもうアウトです。
じゃあどうするの?
今回のようなケース、テキストが可変だと「テキストが長くなった場合はどう表示する?」みたいな会話が行われますが、固定テキストに対してこのような会話が行われることは稀だと思います。そこまで確認していたらキリがないので。なのでどうしても「デザインカンプを再現しつつ、様々な表示に耐えられるような実装にする」という「エンジニアがよしなに実装する部分」というのが出てきます。
じゃあ今回のケースを「よしなに実装」した場合どうなるのかと言うと、① の padding で幅と高さを出す方針で実装することになります。この方針だと子要素のサイズに応じて親要素のサイズが決まるので致命的な UI 崩れは回避できます。

親要素に maxWidth を指定しなければ横に長くなりますし、指定すればその幅で改行されて縦に長くなります。ただ、いずれもテキストがグレーの四角の中に収まっています。
でもこれってさぁ、、、
そう、UI が崩れにくい padding を指定する実装ですが、これは序盤に示したように幅と高さがデザインカンプと違う(ピクセルパーフェクトではない)実装なのです。このままでは二兎を追う者は一兎をも得ず状態です。
ピクセルパーフェクトは大事だけど大事じゃない
開発者がピクセルパーフェクトを意識して実装をするのは大事です。なんか、ピクセルパーフェクト論争のときに「ピクセルパーフェクトじゃなくて良い = それっぽい見た目になっていれば margin とか適当でも良い」みたいな事を言う人がいますが、ああいう系の話は論外だと思っていて、今回みたいに「ユーザー環境由来の不測の事態にも耐えられるような実装にしたときに生じるデザインカンプとのズレ」についての話だと思っています。基本はピクセルパーフェクトです。
ただ、実装をデザイナーさんたちとレビューするときにピクセルパーフェクト的な観点を入れてレビューするのはあまり良くないと思っています。レビュー時に注目するべき点は「デザイナーの意図が満たされた実装になっているか」ということです。今回の例だと「グレーの四角に対してテキストをどこに配置したいか」が論点になるのかなと思います。おそらく今回は、「四角のサイズとテキストサイズがピッタリだと余白がなくなるのでテキストが見辛くなる。なので padding をとってテキストを見やすくしたい」という意図があると思うので、その意図が満たされていれば小数点以下のサイズの違いというのはどうでも良く、今回の場合は UI 崩れを起こしにくい padding を使った実装の方が良いという結論になるかと思います。ピクセルパーフェクトの作品をユーザーに届けるのが目標ではなく、ユーザー視点でレビューが行えると良いですね。特に実装成果物に対してのレビューは。
最後に
最初にも言いましたが、令和となったこの時代、ユーザーが使うデバイス、画面サイズ、ブラウザは多岐にわたります。そんな中でピクセルパーフェクトに拘って細かくピクセル数を指定することは思わぬ UI 崩れを招いてしまいます。ピクセル数を固定すればするほど画面としての柔軟性はなくなってしまうので、以下のような観点からピクセルパーフェクトとうまく付き合うことが重要かなと思っています
- デザイン意図の理解:デザイナーがなぜその配置やサイズを選んだのかの背景を理解する。これによって「見た目の完全一致」より「意図の完全実現」を優先できる
- コンポーネント設計段階からの協業:実装の制約をデザイン段階から共有して柔軟性を持たせたデザインと実装の両立を目指す
- レビュー基準の明確化:「ピクセル単位の一致」ではなく「ユーザー体験の一貫性」を基準にレビューを行う
結局のところ、ピクセルパーフェクトは目的ではなく手段の一つです。最終的にはユーザーにとって使いやすく、デザイナーの意図した体験を実現できているかが重要だと思っています。