孔版印刷の制約をデザイントークンに翻訳する
このサイトの視覚方向は孔版印刷(リソ)です。実際にやったのは印刷の物理的な制約をトークンに書き出すことで、おかげで見た目を変えても触ったのは 2 ファイルだけ、コンポーネントは 1 行も直していません。
このサイトの視覚方向は「孔版印刷」——2 色のインク、粗い粒、わずかにずれた版ずれ、そういう見た目です。懐古趣味ではありません。印刷はもともと抑制されたメディアだからです。制約が美的ではなく物理的なので、「グラデーション + 角丸 + 柔らかい影」という、どこにでもある同じテンプレートの見た目に勝手に膨らみません。
本当の作業量は「その見た目を描くこと」ではなく、その制約をトークンに書き出すことでした。
印刷の制約を 1 つずつ CSS に対応させる
| 印刷側 | ここでのトークン / 決定 |
|---|---|
| 1 版に 1 色 | 2 色:紙色 + 蛍光オレンジ + インクブルー。3 つ目のアクセントは無し |
| 断ち切りは直線 | --radius-* はすべて 0。角丸は 1 つも残さない |
| 圧印はベタ | --shadow-ink は常にぼかし 0。ぼけた影が出たら脱線 |
| インクの線は太る | --border-width: 3px、細線は --border-hair: 2px |
| 見当がずれる | --misreg: 4px(カードのハードシャドウ)、--overprint: 2px(見出しの重なり) |
| 網点 | @include mx.halftone(...)。--halftone-size と --halftone-dot で密度を決める |
| 紙は白くない | --c-bg は紙色 #f5f1e8 |
右の列はすべて src/styles/settings/_tokens.scss の中にあります。見た目を変えるときに触るのはここだけで、あとは tools/_mixins.scss の 3 つの mixin。
トークン層の中身
ライトとダークは 2 つの map、展開する mixin は 1 つです。
$light: (
'bg': #f5f1e8,
'surface': #fffdf7,
'accent': #ff4a17,
'ink-2': #1b2a6b,
// …
);
$dark: (
'bg': #101433,
'accent': #ff4a17,
'ink-2': #5fd3e8,
// …
);
@mixin palette($map) {
@each $name, $value in $map {
--c-#{$name}: #{$value};
}
}
利点ははっきりしています。コンポーネントは var(--c-accent) と書くだけで、自分が何色目のインクか知りません。 ダークモードはレシピを差し替えるだけで、コンポーネントは 1 行も変わりません。後でスクロールバーを中立の黒灰にしたとき、2 つの map に 2 つキーを足すだけで済んだのも同じ理由です。
「版ずれが騒音になる」のを防ぐ 2 つのルール
版ずれは癖になります。一度手に入れると何にでも付けたくなります。そこで 2 つ決めました。
重なりはページの主見出し(h1)だけ、しかも必ず別のインクで。
同色の重なり(text-shadow を文字と同色、ぼかし 0、2px ずらす)は実際に踏んだ罠です。2 枚がほぼ重なるので文字の輪郭が一回り太り、行全体が汚れて、レンダリングが壊れたように見えます。別のインクで初めて「2 版がずれた」という意味になります。繰り返し出る h2〜h4 には重ねず、h2 は左のベタのインクバーにしています。
網点は本文の下に敷かない。
ファーストビューでは右端のグラデーション網(右が濃く、左へ mask で消える)で、本文の下には決して回り込みません。網の上に文字を置いたら、どれだけ組版が良くても読めません。
どちらも好みではなく、可読性の下限です。装飾が本文のコントラストを食い始めたら、それはもう装飾ではありません。
システム部品は版に参加させない
先日、グローバルなスクロールバーを「ベタのインクバー」から、静かに隠れて中立の黒灰に変えました。同じ論理の延長です。
スクロールバー、セレクトの矢印、日付ピッカー——こうしたシステム部品は版の主役を奪うべきではありません。OS の延長として読まれるものに蛍光オレンジを塗ると、雰囲気ではなく干渉になります。だから専用の中立トークンを使い、--c-accent は使いません。
視覚方向が統べるのは「見た目」で、「部品の意味」ではありません。混ぜると騒音になります。
この分層が効く理由
却下した方向は明るい Bento カード——角丸、グラデーション、柔らかい影。醜いからではありません。制約が無いからです。制約が無いと、どのコンポーネントも自分で少しずつ足し、最後はサイト全体が同じ漠然とした柔らかさになります。
印刷は逆です。先に「インクは 2 色、直線、ベタ」と告げ、その箱の中で決めさせます。制約をトークンにしてしまえば:
- 新しいコンポーネント:
var(--c-*)とvar(--space-*)だけ使えば自動的に正しい。 - 配色や線幅の変更:
_tokens.scssを直す。 - 脱線の確認:
border-radiusとblurを検索する。ヒットしたら脱線。
制約は手間を省く道具ではなく、散らばった決定を 1 つの決定に変える道具です。

コメント
…