はじめに
突然ですが、皆さんはCSSのmargin(マージン)をよく使いますか?
私はマージンを多用しないように気をつけています。というより、あまりマージンと関わりたくないと思っています。今回の記事では、「どうして避けているのか」について自分なりの考えをまとめてみたいと思います。
あくまでも個人の意見なので、こういう考えの人もいるのだなと捉えていただけますと幸いです。もっとこうしたら良くなるのに!というご意見は大募集しているので、どんどん教えてください。
マージンを使いたくない理由
マージンを使いたくない一番の理由に、スタイルが崩れるというものがあります。「崩れる」と一言で言っても、わかりずらいと思うので落ち着いて考えをまとめてみました。その結果、下記の2パターンに分かれるという結論に行きつきました。
- マージンが不可解な挙動をする
- コンポーネントとして使い回しずらい
この二つの観点から、マージンを極力使わないようにしています。
細かく説明していきます。
マージンが不可解な挙動をする
実は、これはマージンが不可解な挙動をしているわけではなく、Margin Collapseと呼ばれる現象に悩まされているのでした。
下記記事でとても丁寧にまとめられているので、抜粋してご紹介させていただきたいと思います。
マージンは、縦方向に重なるマージンは相殺される、という習性(仕様です)を持ちます。
例)二つのエレメントが同方向にマージンを持つ場合
引用:https://www.joshwcomeau.com/css/rules-of-margin-collapse/
向かい合う向きに同サイズのマージンを持つと、相殺して1つ分とみなされます。
片方が大きい場合、どういった挙動になるのか気になりますよね。
例)向かい合うマージンのサイズが異なる場合
引用:https://www.joshwcomeau.com/css/rules-of-margin-collapse/
なんと大きいマージンが優先されます。実は、これらのルールは、エレメントがネストされていても発生します。
例)ネストされたエレメントが向かい合う方向に同サイズのマージンを持つケース
引用:https://www.joshwcomeau.com/css/rules-of-margin-collapse/
図の通りマージンは、親の境界を無視し、さらにマージンを相殺するという挙動をとります。
図で見ればわかりやすいですが、デバッグするときにこれを見つけられる自信はないです。
しかも、これは複数のエレメントがいるケースでも発生します。
例)複数のネストされたエレメントが向かい合う方向に異なるサイズのマージンを持つケース
引用:https://www.joshwcomeau.com/css/rules-of-margin-collapse/
こうなったら、どこのマージンが効いているのかわからなくなりそうですね。
本記事では割愛しますが、その他のケースも紹介されていて、インタラクティブに学習できるような記事なっているので、是非ともJoshさんの記事を見てみてください。
ちなみに、この相殺が起こるのは縦方向のみというのも、個人的には直感的でないと思っています。
コンポーネントとして使い回しずらい
今度は少し角度を変えて、コンポーネントにおけるマージンの存在について考えてみます。
このようなコンポーネントを考えてみましょう。オレンジ色がマージンで、カードコンポーネントが格子状に並んでいます。
カードの一つ一つが、右と下にマージンを持っている状態です。
では、同じコンポーネントをスマートフォンのような画面の幅が狭いデバイスで見てみましょう。少し左側に寄ってしまいますね。
これは、「コンポーネント自体が周りからどのくらい離れたいか」という意思をコンポーネント自体に付与していることが原因で起きています。
今度は、カードコンポーネント内部のマージンを考えてみましょう。わかりやすいように、デザインを埋めてみました。
ここでは、テキストエレメントが「周りからどのくらい離れたいか」マージンで指定することにします。
では、ここでカード内にチップ(Chip)を入れる変更が来たらどうなるでしょうか。
図のようにChipエレメントが左詰めになってしまいます。これを回避するためには、Chipエレメント自体にマージンを持たせる必要が出てきてしまいますね。
今度は、カード下部にボタンを追加してみましょう。Chip同様、左端に追いやられてしまいましたね。こちらも、ボタンエレメント自体にマージンを持たせる必要が出てきました。
解決策
パディング
先程までは、「各エレメントが周りからどのくらい離れたいか」という視点でマージンを使っていました。親エレメントにパディングを持たせることで、各エレメントが「どのくらい離れたいのか」気にする必要がなくなりました。
また、「カードエレメントの画像部分の空白を無くしたい」という変更依頼がきても柔軟に対応することができるようになりました。(図の右)
flex/grid
同様に、flexboxやgridのgapを用いてエレメント同士を離すこともできます。こうすることにより、レスポンシブデザインにも柔軟に適用できるようになります。
まとめ
自分がマージンを避ける理由は、マージンを使うと柔軟性を欠くことがあるということが理解できました。
エレメント間を離したい際は、「そのエレメント自体がどのくらい離れたいか」という視点ではなく、なるべく親がレイアウトの責務を負う設計にすると良いと感じました。
参考文献