あのさ.Flexbox で天然で `justify-content` は「横方向の~」とか,`align-items` は「垂直に~」とか言うの,もう止めない?

て話.

タイトルなので端折ってるので(それでも長すぎて締まりの無いタイトルですが笑),改めて全部載せすると,
Flexbox で整列について,このようなお話のされ方,多くありませんか?

「横方向の整列は justify-contentで...」
「垂直方向なら, align-itemsを...」

これって何だかなぁ,って思うのです.

例えば,今回の切っ掛けが中央揃えでしたので,それを例にしますと,こんな感じ.

justify-content: center; とすれば,水平方向にセンタリングされます...」
align-items: center; で,垂直方向に中央揃えができます...」

いやですね,決して間違ってはいないのですがね.

ただ,小面倒臭いことを言うちょっと痛い人っぽいですが,説明(解説)として,肝心な部分が欠けていて,
誤解を生むんじゃないかな,と思うのです.

どう言う事かと言うと.

「横方向はjustify-content~」,「垂直ならalign-items~」て言うけど,それ flex のフロー方向 flex-direction によって替わっちゃうようなものみたいなのよ?

有名な,この図,ありますよね.

図1: `flex-direction` が `row` 方向 (デフォルト) の図

これは参照先本文にも記載があるとおり,《これは row 方向の flex-direction を持つ flex container であり,flex item は要素のテキストフローの方向 (この場合は左から右) に》配列されます.

でこの row 方向が,column 方向になると,こう.


図2: `flex-direction` が `column` 方向 の図

さっきの図を,クルっと 90 度回転させるイメージで伝えたかったので,
わざとこう描いてみました.

この “クルっ!”,つまり flex-directionrowcolumn となることで主軸 main-axis交叉軸 cross-axis の走る向きが入れ替わることになります.

ここら辺りでもう本エントリで伝えたいことはお分かり頂けるかと思います.

justify-content は横方向に整列するためのものではないし,align-items もまた縦垂直方向に整列させるもの,って言っちゃいけないんじゃないか,って

ここからは,ちょっと面倒なので,方向の表現を便宜的に x と y にさせてください.

x は "→" な感じで,横,左右方向,水平方向,
y は "↓" な感じで,縦,上下方向,垂直方向,

と.すみませんが,脳内置換してください.

表形式で整理してみると,こう書けると思います.

表1: Flexbox における flex-direction と整列の仕方

主軸の方向 flex-direction 主軸 main-axis justify-content の効き方 補足
row (defalut) x 軸方向 x 軸 方向で整列する つまり主軸の方向
column y 軸方向 y 軸 方向で整列する つまり主軸の方向

表上でも敢えて記載しましたが,Flexbox において justify-content プロパティは「主軸方向に整列させるもの」で,
「横方向,水平方向に整列する」という言い方をすると,ちょっとおかしなことになるんじゃないか,と言うわけです.

これは align-items でも同様.

Flexbox での整列/揃えは,「主軸 main-axis 方向~」「交叉軸 cross-axis 方向~」であって,それは flex 方向を決める flex-direction プロパティによって結果,水平方向の○○揃えとか,垂直方向の○○揃えになる

というのが誤解される可能性は低くなるんじゃないかと思うのです.

結構くどいかもしれませんが.

ちなみに,自身もこの「横方向は justify-content,縦方向は align-items」と言う引っ掛け問題に,しっぽりハマった性質です笑

最後にドキュメントの方でも,justify-content については《主軸方向の整列 Axis Alignment: the justify-content property》と表現してますし,align-items についても《交叉軸方向の整列 Cross-axis Alignment: the align-items and align-self properties》と言う言い方してますね.

背景

数年ぶりに思い立ってこのサイトの CSS をどうにかしたいと,それこそ数年ぶりに CSS を眺めていて.

こんな html があって,それぞれの要素を縦並びで,それをど真ん中に配置したいと考えたのが Flexbox を知った切っ掛けでした.

ここは,敢えて,自分が何も分かっていなかった時の表現で記述したいと思います.

html

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Flexbox Test</title>
<link rel="stylesheet" type="text/css" media="screen" href="any/your.css"/>
</head>
<body>
<h1>Flexbox で column 方向で中央に並べたいんだけどっ</h1>
<div class="flex-container">
    <a class="flex-item" href="">
        <img src="./image/???.gif">
    </a>
    <span class="flex-item">
        (2) span
    </span>
    <div class="flex-item">
        (3) div
    </div>
</div>
</div>
</body>
</html>

勿論,本当はもっと面倒な構造なのですが,必要な所だけサンプリングしてます.

そして CSS

CSS

難しい話ではない.(と,この時点では思っていました.)

親要素に display: flex: 置いて...
↓ 縦に並べたいので flex-direction: column; でしょ.
↓ うん,縦に並んだ.Flexbox 便利!
↓ で,横の方向にセンタリングだから,justfy-content: center; ね.
↓ ...

「?」

何でっ!? 何でっ!? ...と焦りと迷走.

この恥を晒すと.

「もしかしてインライン要素の場合はダメだったり?」とか,
「もしかして flex じゃなく,inline-flex なの?」とか,
「つか,みんなブロック要素でばかり話していて何さ?つか,アイテムがインライン要素だと何か違ったりすんの?」とか,
「インライン要素だと,li 要素ばかりで,横に並べるのばかりだし.」とか,
「ってさ,そもそも inline-flex が居る意味って何だよ.」とか,

今思えば「何を的外れな」と思うのですが,つくづくそんな自分もまた嫌であり.

そんな末,辿り着いた原因知って「...」って.
その原因は上述の通り.

@charset "UTF-8";

.flex-container {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
        -ms-flex-direction: column;
            flex-direction: column;
    /* ↓flex-direction が column だったら,その水平方向での中央揃えは,これじゃない.
    justify-content: center;
     */
    -webkit-box-align: center;
        -ms-flex-align: center;
            align-items: center;
    width: 400px;
    height: 280px;
    border:1px solid gray;
}

.flex-item {
    width:  80px;
    height:  80px;
    font-size: x-small;
    border:1px solid #639;
    text-align:center;
}

正解を知ったきっかけは,「知りたいの上下中央じゃないんだよな...」と思いながら,こちらのサンプルを使って,justify-content: center;align-items: center; を片方ずつ,取っ替え引っ替えコメントしていたら気付いたのです.

あとこちらも.;

これがflex-directionをcolumnにするなどしてメイン軸が縦方向に設定された場合、justify-contentは縦方向の、align-itemsは横方向のレイアウトをするようになります。

「justify-contentは横方向のレイアウトをするものだ」と間違って理解すると複雑な段組をしようとした時にあっという間に破綻するので、メイン軸とクロス軸の理解はしておいたほうがいいでしょう。

有り難い.

そういうことでして

いやぁあれね.

CSS 見たの,数年ぶりのことで*1,世からは完全に取り残されていて,安っぽい表現ですが,まさにウラシ&マタロー状態.

まぁ言っていること,分かんないこと分かんないこと 笑

  • その数年前に書いた時は clone したデータの拡張子が less だった,ということで LESS 使ったけど,
  • どうも世の中的には Sass らしいから今度こそ Sass だ,と見渡してみたら,もうそんな時代ではなく,
  • Grunt ってタスクランナーと言うのあるらしいの知って踏み出したら,
  • もはや Grunt でもなくて,gulp というビルドシステムがあることを知る.
  • わかった,gulp だ,と手を伸ばしたら,実はもうそれすらでもなく,
  • PostCSS があるって言うじゃない.
  • そしたらさ,今度は Grunt でも gulp でもないって言うじゃない.結局は npm-scripts が一番スマートかも,ということで Grunt も gulp ポイする.

もう.

いつか,この作業で通ってきたモノゴト,まとめておかなくちゃな思っています.

最後にひとつメモ.
そういえば,今回の作業で「うっわー」って思ったのが.

もう今は,ボックス要素とかインライン要素って言わないんだってね

html5 では インライン要素 とか ボックス要素 と言う概念は無くなったようで.

inline-flex について探していたらこんな記述に巡り合いまして.

inline-flexは「インラインレベルのflexコンテナ」ですから基本的にはインライン要素に使用するもので。spanタグやaタグに対して使用するものでしょう。けれどもここでちょっとした疑問が出てきます。
インラインであろうが、何であろうが、flexコンテナを作成するものなら何らかのコンテナ的な役割をする要素に設定するものでしょう。けれどもインライン要素は(HTML5ではその概念がなくなりました)どちらかというとflexアイテム的な要素ですから、更にflexコンテナ化、しかもinline-flexとしてコンテナ化する用途は少ないかもしれません。

文中《インライン要素は(HTML5ではその概念がなくなりました)》とかって,理解することを脳が拒否反応おこす程に,「は?ちょっと何言ってんのか分かんない」でしたけど.

"html5 ブロック要素 インライン要素" って Web へ流してみたら,まぁ出るわ出るわ.

でも,これ知ったお蔭で.

flexible の議論では水平/inline 軸や垂直/block 軸といった用語から解放される一方で、モデルを適切に説明するための新たな用語が必要になります。

この辺りで言っているような事,やっと腑に落ちました.

もうね,さすがに時の流れというものを感じずにはいられません.

はいおしまい.

*1:今見たら前回のコミット,2015 年だってさ.おーこわ.