フォント ガイドラインを作りmixinしよう


前提

  • web開発
    • だけどネイティブアプリ、ゲーム開発などでも適用できそうな設計思想
  • ReactなどのComponent指向開発
  • styled-compmonents などのmixin機能を持つCSS in JSを使っている
    • SCSS, CSSの場合も考察

概要

「このプロダクトではこれしか使わない」というフォント関係の属性集合を作り、mixinし、フォント周りに秩序をもたらしていきましょう
今回は次の属性を定めていきます

  • font-size
  • font-weight
  • line-height

これらは相互の関係性が非常に高い(ワンセットとして決めて問題ない)と思います
font-familyはもっと上層のbodyに一括指定している事が多いと思うので除きますが、使い分けたいならそれも対象にすると良いかもしれません
colorは流石に自由度が高すぎて一緒には集合化できないと思います。単に定数化で済ませるのが良さそうです

手順の例

1. フォント ガイドラインを作る

次のような集合を決めて作ります
これはAdobe XDでデザイナーさんに作ってもらった例です

  • W: font-weight
  • S: font-size
  • L: 行送り

weightごとにまとめられています
https://note.com/lby/n/ne71f93c72702 にもある通り、XDの行送りとCSSのline-heightは異なるので変換が必要なことに注意です

2. mixin用styleを作る

styled-componentsを用いて次のようなファイルを作る

import { css } from 'styled-components';

const w7 = 700;

export const fontGuideline = {
  pc: {
    w7s40: css`
      font-size: 40px;
      font-weight: ${w7};
      line-height: calc(55 / 40);
    `,
.
.
.
}

3. mixinする

const HogeComponent = styled.div`
  ${fontGuideline.pc.w7s40}
`

メリット

無限の組み合わせから有限の集合になることで、以下のメリットがあります

  • font周りのスタイルに一貫性が保たれる
  • XDなど、デザイナーの指定どおりになっているか確認しやすい
    • 無限の可能性があると、デザイナーの指定が正しいのか実は間違っているのかわからない。フォントガイドラインがあれば、そこになければ間違いだと分かる
    • 特にfont-heightは地味なので指定漏れ・間違いやすいが、集約しつつcalcを使うことで指定通り作りやすい
  • エンジニアだけでなくデザイナーもどこをどういうフォントにするか意識しやすくなる

他の手法 Composition

Reactなどを使っていれば、以下のようにTypography Componentを作ってCompositionする方法もあります

独自に作って適用すると次のような使用感になりそうです

<TypographyW7S40>hogehoge</TypographyW7S40>

スタイルのMixin vs ComponentのComposition

以下のような考えで、ComponentをCompositionするよりスタイルをMixinする方が良さそうと思っています

  • 上記UI Componentのライブラリがそうなっているのは、単にComponentのライブラリとして画一的に便利な機能を提供するためであって、スタイルのライブラリではないから
  • マークアップの構成は極力Semanticにした方が扱いやすく、デザインの関心は分離されて差し替え可能な状態で当ててあるだけ、というのが理想
  • スタイルのためだけのElementが大量に現れてくるのはマークアップが肥大化して見づらいのでは?
  • フォントの関心はweb開発のスタイルのどこにでも現れるアスペクトという感があるのでスタイル部分に自由に差し込みたい

他の場合どうするかの考察

SCSS

http://www.sass-lang.com/documentation/at-rules/mixin
を使えば同じことができます

CSS

素のCSS+HTMLでmixinする手法はclass指定しかないです

デザイン専用のclassがマークアップのあちこちに挟まることを許容する派閥の場合

マークアップ上で明示的にclassでmixinすることで楽ができます
(もちろんCSS in JSも内部的にclassを使っていたりするが、それは隠蔽されている)

.w7s40 {
  font-size: 40px;
  font-weight: 700;
  line-height: calc(55 / 40);
}
<div class="hoge w7s40">hoge</div>

許容しない場合

css上ではなるべくセット同士が分かりやすいような名前で変数化して、
マークアップ上ではセマンティックなclass指定をして、
その中で1つずつ指定するしかないと思います

変数定義の例 (Special Thanks 同僚):

:root {
  --w7: 700;
  --w7s40: 40px;
  --w7s40h: calc(55 / 40);
}

/* semanticなクラス名 */
.hoge {
  ...
  font-size: var(--w7s40);
  font-weight: var(--w7);
  line-height: var(--w7s40h);
}
<div class="hoge">hoge</div>

CSS modules

composes が使えます
https://postd.cc/css-modules/
この場合もマークアップに適用するのはセマンティックなクラス名にして、その中で使うのが常套手段だと思います

scss-loaderなども導入してSCSSのmixinを使う方法もあります

まとめ

横断的に現れるスタイルの集合作成 + mixinはいいぞ