Edited at

UIコンポーネントにはマージンをつけるな!絶対にだ!!

私は長年、CSSmarginをどのように書くか悩んできました。

たとえば、このようなボタン。


<button class="button">ボタンだよ</button>


.button {
display: block;
margin: 50px auto 0;
padding: 8px 20px;
border: solid 2px #ddd;
border-radius: 10px;
font-size: 16px;
}


See the Pen
button_01
by Otsuka Yuhi (@boltkeep)
on CodePen.

パット見、いい感じのボタンです。

しかし、このボタンには一点重大な欠点があります。

それは、このボタンは必ず上に50pxの余白が付き、かつ中央寄せされるということです。


デザイナー登場

デザイナーがこう言いました。

「ボタンを横に2つ並べたい」

「ボタンとボタンの間隔は20px」

「その上で中央寄せで!」

さて、どうしましょう??display: flex;でしょうか?

<div class="flex">

<button class="button">ボタンだよ</button>
<button class="button">ボタンだよ</button>
</div>

.flex {

display: flex;
}

.button {
display: block;
margin: 50px auto 0;
padding: 8px 20px;
border: solid 2px #ddd;
border-radius: 10px;
font-size: 16px;
}


See the Pen
qBWXoWa
by Otsuka Yuhi (@boltkeep)
on CodePen.

。。。どうやら、.buttonからmargin: 50px auto 0;を削除しないことには無理そうです。。

しかし、このボタンはすでに別のページで使われており、margin: 50px auto 0;を削除すると、様々なページのボタンから上の余白と中央寄せが失われてしまいます。

これは非常にまずい!

影響がないように、.row-buttonをつくりましょうか。


<div class="row-buttons">
<button class="row-button">横並びボタンだよ</button>
<button class="row-button">横並びボタンだよ</button>
</div>


.row-buttons {
display: flex;
justify-content: center;
}

.row-button {
padding: 8px 20px;
border: solid 2px #ddd;
border-radius: 10px;
font-size: 16px;

&:nth-child(n+2) {
margin-left: 20px;
}
}


See the Pen
OJLjvyE
by Otsuka Yuhi (@boltkeep)
on CodePen.

なんとか難は逃れたようです。よかったよかった。


デザイナー再登場

「縦に20pxの間隔で積まれたボタンが必要です」

な、なんだと。。。

<div class="column-buttons-container">

<div class="column-buttons">
<button class="column-button">縦並びボタンだよ</button>
<button class="column-button">縦並びボタンだよ</button>
</div>
</div>


.column-buttons-container {
display: flex;
justify-content: center;
}

.column-buttons {
display: inline-flex;
flex-direction: column;
}

.column-button {
padding: 8px 20px;
border: solid 2px #ddd;
border-radius: 10px;
font-size: 16px;

&:nth-child(n+2) {
margin-top: 20px;
}
}


See the Pen
flex column button
by Otsuka Yuhi (@boltkeep)
on CodePen.

だんだんいい感じになってきましたね!\(^o^)/


.buttonにマージンがなければ問題なかった

もうお気づきかと思いますが、.buttonがマージンを持っていなければたくさんのボタン用CSSクラスは不要でした。


<button class="button">ボタンだよ</button>


.button {
padding: 8px 20px;
border: solid 2px #ddd;
border-radius: 10px;
font-size: 16px;
}


単体中央寄せ


<div class="centering">
<button class="button">中央寄せボタン</button>
</div>


.centering {
display: flex;
justify-content: center;
margin-top: 50px;
}

.button {
padding: 8px 20px;
border: solid 2px #ddd;
border-radius: 10px;
font-size: 16px;
}


See the Pen
中央センタリング上マージン
by Otsuka Yuhi (@boltkeep)
on CodePen.


横並び中央寄せ

<div class="row-buttons">

<button class="button">横並びボタン</button>
<button class="button">横並びボタン</button>
</div>

.row-buttons {

display: flex;
justify-content: center;

> *:nth-child(n+2) {
margin-left: 20px;
}
}

.button {
padding: 8px 20px;
border: solid 2px #ddd;
border-radius: 10px;
font-size: 16px;
}


See the Pen
横並び中央寄せ
by Otsuka Yuhi (@boltkeep)
on CodePen.


縦積み

<div class="column-buttons-container">

<div class="column-buttons">
<button class="button">縦積みボタン</button>
<button class="button">縦積みボタン</button>
</div>
</div>

.column-buttons-container {

display: flex;
justify-content: center;
}

.column-buttons {
display: inline-flex;
flex-direction: column;

> *:nth-child(n+2) {
margin-top: 20px;
}
}

.button {
padding: 8px 20px;
border: solid 2px #ddd;
border-radius: 10px;
font-size: 16px;
}


See the Pen
yLBoKXL
by Otsuka Yuhi (@boltkeep)
on CodePen.

クラス名がダサいのはご容赦願います\(^o^)/


まとめ

今回はbuttonのみの例でしたが、ほかの要素やUIコンポーネントでもページによってマージンが違ったりするスタイルはよくあるかと思います。

デザインに柔軟に対応するためにも、UIコンポーネントにはマージンを持たせず、使う側から指定してあげるというルールを設けてあげれば、CSSが少し楽になるかもしれません。

もちろん、例外は存在しますので、例えばLPとかでそのUIにはこのマージンしか絶対に存在しないみたいなことがあれば、直接書いても良いかと思います。

それでは、また。