display: flexとinline-flexの違い|margin: autoで中央揃えできなかった理由

Figmaのデザインを見ながら模写コーディングをしていたとき、ボタンを中央に配置しようとして少しつまずきました。

ボタンの中の文字を中央に配置するため、最初に書いていたCSSがこちらです。

.help-button {
    width: 192px;
    height: 62px;
    display: inline-flex;
    justify-content: center;
    align-items: center;
    margin: 0 auto;
}

justify-content: centerとalign-items: centerで文字はボタンの中央に配置できています。

さらにmargin: 0 autoを指定したので、ボタン自体も中央に来ると思っていました。

ところが、ボタンは中央に来ませんでした。

そこで、

display: inline-flex;

を、

display: flex;

に変更すると、今度はmargin: 0 autoで中央に配置できました。

なぜでしょうか。

調べてみると、flexとinline-flexの違いだけでなく、「ボタンの中身を中央にすること」と「ボタン自体を中央にすること」は別の話だということが分かりました。

display: flexとinline-flexの違い

flexとinline-flexは名前が似ています。

実際、どちらを指定しても要素はFlexコンテナになり、その子要素をFlexboxで配置できるようになります。

違うのは、主にFlexコンテナ自身が周囲のレイアウトでどう扱われるかです。

display: flexはブロックレベルとして扱われる

.box {
    display: flex;
}

display: flexを指定すると、その要素は外側に対してブロックレベルのFlexコンテナとして振る舞います。

イメージとしては、

外側:ブロック
内側:Flexbox

です。

そのため、幅を指定したブロックを左右のmargin: autoで中央に配置する、というよく使われる方法が使えます。

.help-button {
    width: 192px;
    display: flex;
    margin: 0 auto;
}

今回ボタンを中央に配置できたのも、この形です。

display: inline-flexはインラインレベルとして扱われる

一方で、

.box {
    display: inline-flex;
}

とすると、内側では同じようにFlexboxを使えますが、要素自身は外側に対してインラインレベルとして振る舞います。

つまり、

外側:インライン
内側:Flexbox

です。

inline-flexだからFlexboxが使えないわけではありません。

justify-contentやalign-itemsはどちらでも使えます。

違うのは、そのFlexコンテナ自身を周囲にどう配置するかです。

なぜmargin: 0 autoで中央揃えできなかった?

今回混乱した原因は、margin: 0 autoとjustify-content: centerが、どちらも「中央」に関係するCSSだったことです。

しかし、この2つは中央にする対象が違います。

margin: 0 autoは要素自体の配置に使う

幅を指定したブロックレベルの要素なら、

.help-button {
    width: 192px;
    margin: 0 auto;
}

とすることで、左右の余ったスペースがautoのmarginに割り振られ、要素自体を中央に配置できます。

今回inline-flexからflexへ変更したことで、ボタンはブロックレベルのFlexコンテナとして扱われるようになりました。

その結果、指定していたmargin: 0 autoによる中央配置が意図した形で機能した、というわけです。

justify-contentはボタン自体を中央にするCSSではない

もう一つ勘違いしていたのが、

justify-content: center;
align-items: center;

の役割です。

これらは、Flexコンテナの中にある子要素を配置するためのCSSです。

たとえば、

<a class="help-button" href="#">Help Me</a>

なら、justify-content: centerやalign-items: centerで調整しているのは、ボタンそのものではなく中にあるテキストの位置です。

つまり今回必要だったのは、

ボタンの中の文字を中央にする
→ justify-content・align-items

ボタンそのものを中央にする
→ 親要素との関係で配置を決める

という2つの別々の中央揃えでした。

ここを分けて考えると、かなり理解しやすくなりました。

inline-flexを中央揃えしたい場合は?

では、inline-flexでは中央揃えできないのでしょうか。

もちろん、そんなことはありません。

中央にする方法が違うだけです。

親要素にtext-align: centerを指定する

inline-flexの要素を中央に配置する方法の一つが、親要素へのtext-align: centerです。

<div class="button-area">
    <a class="help-button" href="#">Help Me</a>
</div>
.button-area {
    text-align: center;
}

.help-button {
    display: inline-flex;
    width: 192px;
    height: 62px;
    justify-content: center;
    align-items: center;
}

inline-flexは外側に対してインラインレベルとして扱われるため、親要素のtext-align: centerによって中央へ配置できます。

つまり、

「inline-flexでは中央揃えできない」わけではありません。

今回たまたまdisplay: flex+margin: 0 autoという組み合わせが、作りたいレイアウトに合っていたということです。

flexとinline-flexは目的で使い分ける

flexとinline-flexのどちらが優れているというものでもありません。

たとえば、独立したボックスとして配置しながら、その中身をFlexboxで整えたいならflexが使いやすいでしょう。

一方、テキストやほかのインライン要素との流れを保ちながら、中身にはFlexboxを使いたい場合はinline-flexが便利です。

判断するときは、**「中身をどう並べるか」だけでなく、「その要素自体を周囲の中でどう扱いたいか」**まで考えるのがポイントです。

【まとめ】flexとinline-flexは外側の振る舞いが違う

display: flexとdisplay: inline-flexは、どちらも子要素をFlexboxで配置するために使えます。

大きな違いは、Flexコンテナ自身が外側に対してどう振る舞うかです。

  • display: flex:外側はブロックレベル、内側はFlexbox
  • display: inline-flex:外側はインラインレベル、内側はFlexbox
  • justify-content:Flexコンテナ内の子要素を配置する
  • margin: 0 auto:今回のような幅を指定したブロックを中央配置するときに使える
  • inline-flexを中央にしたい場合は、親要素のtext-align: centerなどを使える

今回、inline-flexからflexへ変更したことでボタンが中央に来たのは、Flexboxそのものが直ったからではありません。

ボタンの中身をどう配置するかと、ボタン自身をどう配置するか。この2つを同じ「中央揃え」として考えていたことが、つまずいた原因でした。

CSSで思った位置に要素が動かないときは、プロパティだけを見るのではなく、**「今、どの要素の位置を変えようとしているのか」**を確認すると原因を見つけやすくなります。

← Research Notes ← Home