エンジニアのためのデザイン4大原則

この記事はGoodpatch Advent Calendar 2022 の5日目の記事です。

こんにちは!エンジニアの藤井(@touyou_dev)です。先日宣言型UIフレームワークを比較してみたという記事を出したばかりですが、今年も昨年のアドベントカレンダー同様、2日目と5日目の二日間を担当しようと思いたち、今年ふたつ目となるこの記事を書いています。

今回扱うテーマはタイトルの通り「デザインの4大原則」です。 デザインをする人たちにとっては、UIであれグラフィックであれ基本中の基本となるこの原則。ですが、今年自分が参加したとある技術カンファレンスでの周りの反応を見て、これが世間一般のエンジニア界隈にとっては当たり前じゃないということに気付いたことがありました。その記憶もあってこの記事を書いています。

といっても、逐一原則の細かい説明を普通にするだけでは意味がないと考えています。というより、それであれば名著ノンデザイナーズ・デザインブックに任せるのが一番早いです。

ザ・技術書といった価格帯ですが、この記事を読んでもっと知りたくなった方はぜひお買い求めください。特に本のタイトルの通りこれはノンデザイナーズの方におすすめの本です。

デザインの4大原則とは

それでは早速、まずはデザインの4大原則とはなんなのかというところをざっくり紹介したいと思います。 以下の4つがその原則です。

  • 近接
  • 整列
  • 強弱(対比)
  • 反復

それぞれを一言で言うと、まず近接とは関連する要素は近づけ、関連が低い要素は遠ざけようという原則。整列はその名の通り要素を整列させて一体性を持たせようというもの。強弱は要素に対して優先度をはっきりと示すようにすること、反復は特徴的なものを繰り返し使うという原則です。 これらはできたからと言って全てがいいデザインになるとは限りませんが、守れていることでデザイン上の減点がグッと減るものになっています。

と同時に、デザイナーは大前提としてこの原則があって、この原則を自分のデザインの理由を根拠づけるものとしてデザインを組み立てていることが多いです。 ただ大抵は当たり前の原則であるので、「この要素とこの要素は関連が強いので近づけます。」という説明のみでその裏にある「なぜなら関連が強いものは近づけた方がわかりやすいという原則があるからです。」の部分をわざわざ語る人は少ないかと思います。

ここでおそらく多くの現場で、デザイナーとエンジニアの間の認識のギャップが生まれています。 もちろんコミュニケーションの方法を改善する、エンジニアがデザインについて学ぶ、いろんな解決策がありうると思いますが、今回はあくまでエンジニアリングを学ぶという手段でここを解決していこうと思います。

エンジニアリングの世界の中心でデザインを学ぶ

というわけでいよいよこの記事の本題です。エンジニアリングの世界の中で先ほど紹介した4つの原則がどう実現されているかを見ることで、理由まで理解せずともこうコーディングすればいいんだ!とUIデザインを見てすぐ最適な実装を思いつくことを目指します。

近接を学ぶ

ではまず近接に関して。 あらかじめ一点断っておくと、この部分については内容の性質上iOSDC2022で@tokoromさんがLT発表したUIStackView逆引きレシピの内容とかなり重複する部分があります。その点あらかじめご理解いただければと思います。

前提はさておき、近接に関してエンジニアが理解する最短距離にあるのは、各種UIフレームワークに最近用意されていることが多いStackというコンポーネントです。CSSだとflexが該当します。 Stackを使うようなデザインに出くわした時、デザインを知らないエンジニアが考えがちなこととして、「Stackに入れると楽に作れるから全ての要素の間隔は同じにするとか、一個のStackで楽に作れるようなルールにしてほしい」というものがあります。ですがStackの本来の使い道はそうではありません。

Stackの真価は「関連した情報をあるルールでまとめる」ことにあります。つまりデザインの近接を実現する手段こそがStackというコンポーネントになるわけです*1。 この考えに従えば、近接でのグルーピングはひとつのデザインにひとつだけなんてことはないため、積極的に複数使ったりネストさせたりしなければならないものがStackと捉えることができます。

もう少しイメージをつけるために具体例で見てみましょう。

Figmaで作ったこのUIを実装することを考えます。試しに各要素の間隔を見てみましょう。

アイコンの黒枠はアイコンの範囲をわかりやすくするために便宜上つけてみました。これをどう実装すればいいでしょうか?

まず愚直に思いつくのは毎回この間隔をマージンやパディングとして設定するという方法。これは確かにデザイン通りの実装ができますが、メンテナンス性はめちゃくちゃ下がりますよね。 続いてが全ての間隔を同じにするようにデザインを変えてもらうという方法。これはせっかくのデザインを台無しにする最悪の方法です。

じゃあどうするか?そのヒントはこのデザインを作ったFigmaのデザインファイルに眠っています。このデザインを実際のレイヤー構造と一緒にあらためて見てみましょう。

今回も便宜上枠線をつけていますが、タイトルと説明文をまとめたtextsという塊があり、textsとアイコンをまとめたinfoという塊があり、ボタン二つをまとめたbuttonsという塊があるといったように、いくつかの塊が組み合わさってできていることがわかります。この塊=グルーピングこそが近接です。

これを踏まえてStackが用意されていることが多い宣言的なUIフレームワークでの実装を、SwiftUIライクな擬似コードで書いてみると次のようになります。

// 全体の塊
Stack(方向: 縦積み, 間隔: 16px) {
  // infoの塊
  Stack(方向: 縦積み, 間隔: 8px) {
    Icon()
    // textsの塊
    Stack(方向: 縦積み, 間隔: 4px) {
      Title()
      Description()
    }
  }
  // buttonsの塊
  Stack(方向: 縦積み, 間隔: 4px) {
    OKButton()
    CancelButton()
  }
}

もうお気づきでしょうか?そうなんです。Stackとデザインファイル上の先ほど紹介した塊が一対一対応するわけです。 もちろん、これはFigmaのAutoLayout機能を使ってかなり丁寧に作ったデザインファイルのため、もしかすると読んでいる方の職場のデザインファイルはこうなっていないかもしれません。ですが考え方は同じです。 つまり、間隔を統一するためにデザインを変える、のではなく、間隔が統一されている部分を一つの塊とみなしてStackにまとめ、時にはネストさせる、というのがいいデザインを実装する考え方になってくるわけです。

これには実装上のメリットもあります。今回のデザイン例だと少し無理矢理になってしまうのですが、例えばタイトルと説明文の組み合わせが別の場所のデザインでも同じように出てきたとします。 そうした場合、このようにあらかじめ関連するものをStackにまとめておくことで後から該当する部分だけコンポーネント化するのが簡単になります。コンポーネント化できればネストも減るし、似たデザインの細部を改めて実装しなおす必要がなくなるので便利ですよね。

これがたとえば各要素の下にマージンを持たせるような作りになっていた場合、切り出した時にそのマージンごと持っていってしまう可能性が高く、別の使い方に対応しにくくなってしまいます。

以上しょっぱなから長くなってしまいましたが、近接はStackで実現でき、Stackを複数組み合わせないとできないデザインには必ず理由がある、ということをまずはぜひ理解してUI実装に向き合っていきましょう。

整列を学ぶ

整列は比較的簡単な概念です。先ほどの例にまた登場してもらって、まずは3パターンの整列を見てみましょう。

一番左は中央に、真ん中は要素の左側が、一番右は要素の右側がそれぞれ揃っていることがわかるでしょうか?このようにどこかで揃えることで、見た目上整理された印象を持たせるのが整列です。例えばこんなふうになってたらちょっと気持ち悪いですよね*2

整列があるかどうかによる効果というものは感じてもらった上で*3、これをどう実装するのかまた考えてみたいと思います。

正解はまたもやStackです。大抵のStackには必ずalignmentといったような名前の設定項目が用意されています。CSSで言えば、align-itemsjustify-contentですね*4。 よって例えば左揃え版の実装は以下のようになります。

// 全体の塊
Stack(方向: 縦積み, 間隔: 16px) {
  // infoの塊
  Stack(方向: 縦積み, align: 左揃え, 間隔: 8px) {
    Icon()
    // textsの塊
    Stack(方向: 縦積み, align: 左揃え, 間隔: 4px) {
      Title()
      Description()
    }
  }
  // buttonsの塊
  Stack(方向: 縦積み, 間隔: 4px) {
    OKButton()
    CancelButton()
  }
}

言語やフレームワークによってデフォルトが何揃えになるのかは変わってくるため、一概にこれだけとは言えませんが、本当にalignを設定するだけで実現できてしまいました。 これがStackが多くのUIフレームワークに実装される所以です。先ほど近接はStackで実現できる、と書きましたが、Stackは近接に加えて整列の実現も手伝ってくれるわけです。しかも必ずいずれかの方法で揃えられているため、ネストさせているStackalignmentをわざとばらけさせる、要素に変なパディングを持たせるなどしない限り、Stackを使った時点で整列が保証されます。

ですのでぜひ、適切な設定でStackを使いこなせるようになっていきましょう。

強弱を学ぶ

3つ目の強弱は、例えば先ほどまでのデザインだとこの部分に登場しています。

タイトルが太字で大きく、その下の説明は小さく太字にはなっていないため、ぱっと見た時必ずタイトルから目に入るようになりますよね。 このように視覚的な差をつけることで、情報の優先度をわかりやすくするのが強弱なわけですが、これはエンジニアリング観点でどのように学べばよいでしょうか?

正解のひとつとしてアクセシビリティがあります。Webが一番わかりやすいのでWebの例で言うと、例えば色の濃淡の差が小さい要素が隣接しているとLighthouseに怒られたり、見出し一つとってもHTMLでそのレベルを分けるためにわざわざh1からh6のタグを使い分けたりしますよね。 このようなことに対応していくのが強弱であり、デザインではそれを視覚的に実現するために色やサイズ、見た目で差をつけていくわけです。

このようにアクセシビリティに関連が深いため、おそらく強弱に関してはそれ自体は知らなくともアクセシビリティ向上の取り組みとして知らないうちに実践している方も多いのではないでしょうか。 ですが一点、エンジニアのみで作ったデザインの中でも特にダサいものにありがちなこととして強弱のつけすぎがあげられると思います。

もちろん極端と言えるぐらい差をつけなければ、差を認識できないという方もいるでしょう。ですがアクセシビリティはあくまで全ての人が情報にアクセスしやすくするためのものです。そしてそのためにアクセシビリティガイドラインにわざわざ具体的な数値が決められているのであって、それ以上の差をわざわざつける必要はほとんどないと思います。また拡張性という意味で考えれば、一箇所に差をつけ過ぎてしまうと、それよりも強調したいであったり、弱めたいといったような多段階の強弱をつけなければいけない時にどうしようもなくなります

ですので適切なかたちでアクセシビリティを意識してみることが、デザインの強弱にも繋がってくると思います。すでにご存知の方はこの意識を持って実践して、アクセシビリティについてあまり詳しくない方はぜひ学んでみましょう。

ちなみに余談ですが、エンジニアには強弱をつけすぎる傾向が強いと感じているのですが、一方で逆にデザイナーは特に色やサイズなどに関して強弱を十分につけようとしない人が多い傾向があると思います。なぜかというと、淡い色合いであったり、小さい文字をうまく使うとデザインがすごく「かっこよく」見えがちだからです。もちろんアクセシビリティを意識しなくていいプロダクトというのも中にはあるかもしれませんが、そういう傾向のあるデザイナーとあった時はぜひ一緒にアクセシビリティについて学ぶということをやってみてください。そうすることで共通認識が生まれ、いいものづくりになると思います。

反復

最後は反復です。反復と言えばプログラミングではお馴染み繰り返し文が思いつきますよね、モバイルエンジニアであればTableView/ListView/CollectionViewとかを思い浮かべるでしょうか。 もちろんこれらも反復ですが、デザイン上での反復はもう少し意味が広がります。厳密には、TableView/ListView/CollectionViewなどの元になっている考え方がまさしく反復にあたります。

ずばり言う前にこれも例を見てみましょう。

成功のアラートにキャンセルボタンなんてあるのか、というツッコミはさておきこの二つ似ていますね。 このように役割の似ているものの見た目を揃えることで、一目でそれがどんなものなのかを理解しやすくするのが反復です。

そしてこの二つを実装しようという時、別々に実装しようという人は少ないんじゃないでしょうか? もうわかる人はわかったんじゃないかと思いますが、反復の考え方はコンポーネント化の考え方とまさしく同じなわけです。

そしてこのコンポーネント化という作業、実装を実際に行うエンジニアの方が感覚的に掴めていることが多い部分でもあります。 視覚的に違うように見えても、構造としては同じ、といったようなもののコンポーネント化は大体の場合エンジニアの方が気づきやすいと思うので、ぜひそういう場合はコンポーネント化をエンジニア側から提案していきましょう。

まとめ

実質今回紹介した例は一つだけでしたが、その実装方法を考えることを通じて、デザインの4大原則がエンジニアリングでどのように実現されているかを見て、そしてそこから4大原則自体を学ぼうという試みでしたがいかがだったでしょうか? 最後に改めてエンジニアになじみにある方法でデザインの4大原則をまとめてみましょう。

  • 近接 ... Stackによって関連のあるものをまとめること
  • 整列 ... Stackの整列機能を使って何かしらのルールにしたがって要素を揃えること
  • 強弱 ... アクセシビリティで考えるように、情報に強弱をつけること
  • 反復 ... 似た役割のものをコンポーネントとしてまとめること

最初の説明に比べて、だいぶ身近になったんじゃないでしょうか?これで少しでも世の中のデザイナーとエンジニアの食い違いが減れば幸いです。

*1:まとめるという意味では、Stackでなくてもグルーピングさえ正しくできていれば近接は実現可能です。ですがその他の原則も考えるとStackを使うのが一番楽な実現方法になります。

*2:もちろんみなさん中央揃えのアラートが一番見慣れているかと思うので、左揃え・右揃えも変に感じる人も多いかと思います。ですが整列されていないと、慣れている慣れていない以前の問題になってしまいます。せっかくの近接もわからなくなってきますしね。

*3:ランダムに並んだデザインがかっこよくなる場合もありますが、少なくともUIではなかなかないでしょう。なによりカッコよく見せる難易度が跳ね上がります。

*4:どっちがどっち向きの設定かわからなくなるので個人的には嫌いです笑