CSSでdivを中央揃えする方法
(joshwcomeau.com)- CSSの中央揃えはもはや単一のテクニックではなく、要素が文書フロー内にあるか・浮いているか・複数あるかによって、Flow、Flexbox、Positioned layout、CSS Grid、text-align から選ぶ問題である
- 単一要素を水平方向の中央に置くときは、
max-width: fit-contentで幅を制限しmargin-inline: autoを適用する Flow layout の方法が、兄弟要素への影響が少ない - Flexboxは
justify-content: centerとalign-items: centerだけで、単一・複数の子要素を水平・垂直方向の中央に配置でき、子要素がはみ出しても 対称的にオーバーフロー する - モーダル・バナーのような浮いたUIには、
position: fixed、inset: 0、サイズ制限、margin: autoの組み合わせが適しており、CSS Gridは短い記法と 重ねて配置する 用途に強い - テキスト自体はレイアウトの整列ではなく
text-align: centerが必要で、Flow layout のalign-contentサポートが広がれば、単純な垂直中央揃えのために Flexbox や Grid に切り替える場面は減る可能性がある
Flow layoutでauto marginを使って水平方向の中央揃え
- 古くからある戦略のひとつは、要素の幅を制限したうえで左右のマージンを
autoにする方法である
.element {
max-width: fit-content;
margin-left: auto;
margin-right: auto;
}
- Flow layout の要素はデフォルトで横方向の空間を埋めるため、中央に置くにはまず 幅の制限 が必要になる
fit-contentは要素がコンテンツを包み込むようにし、widthがheightのようにコンテンツサイズによって決まるようにするwidthではなくmax-widthを使うと最大サイズだけを制限するため、コンテナが狭くなったときに要素も一緒に縮められるmargin-left: autoだけなら余った空間は左マージンに入り、左右両方のマージンをautoにすると余白が均等に分配されて要素が中央に置かれる
.element {
max-width: fit-content;
margin-inline: auto;
}
margin-inlineはmargin-leftとmargin-rightに同じ値を設定するモダンな方法で、ブラウザ対応 も良いmargin-inlineは 論理プロパティ(logical properties) の一部であり、左右ではなく書字方向の inline 軸を基準に動作する- 左から右に書く言語でも右から左に書く言語でも、正しい側にマージンを適用できる
- この方法は、ブログ記事中の画像のように 単一の子要素だけを中央揃え し、兄弟要素には影響を与えたくない場合に有用である
Flexboxで単一・複数の子要素を中央揃え
- Flexbox は主軸に沿って複数の項目を配置するのに強いレイアウトモードで、中央揃えにもよく使われる
.container {
display: flex;
justify-content: center;
align-items: center;
}
justify-content: centerとalign-items: centerを併用すると、子要素を水平・垂直方向の中央に置ける- 子要素がコンテナに収まらなくても整列は維持され、はみ出す場合でも 対称的にオーバーフロー する
- 複数の子要素も中央揃えでき、
flex-directionで積み重なる方向を制御する
.container {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 4px;
}
- 単一または複数の子要素に幅広く適用できる 基本の選択肢 として使いやすい
Positioned layoutで浮いたUIを中央揃え
- モーダル、プロンプト、バナーのように通常の文書フローから外れて上に浮く必要がある要素は、Positioned layout で扱える
.element {
position: fixed;
inset: 0px;
width: 12rem;
height: 5rem;
max-width: 100vw;
max-height: 100dvh;
margin: auto;
}
position: fixedは要素を viewport に固定し、inset: 0pxはtop、left、right、bottomをすべて0pxに設定するinset: 0pxだけだと要素は viewport 全体を埋めようとするため、width、height、max-width、max-heightでサイズを制限する必要がある- この組み合わせは、意図的に成立しない条件を作り出す
- 要素が左と右の両方から
0px離れていながら、同時に12remの幅を持つことはできない - CSS レンダリングエンジンは
widthの制約を優先し、言語方向に応じて片側に寄せる形でその緊張を解消する
- 要素が左と右の両方から
- ここに
margin: autoを入れると、ブラウザの解消方法が変わり、要素が 水平・垂直方向の中央 に置かれる - 必要な4つの条件は、
position: fixed、inset: 0px、制限された幅と高さ、margin: autoである -
下部バナーのように一方向だけ中央揃え
.element { position: fixed; left: 0px; right: 0px; bottom: 8px; width: 12rem; max-width: calc( 100vw - 8px * 2 ); margin-inline: auto; }top: 0pxを省略すると垂直方向の成立しない条件がなくなり、要素は下部に固定されるcalc(100vw - 8px * 2)は viewport の左右に余白を残すよう最大幅を制限するmargin-inline: autoは、水平方向を中央揃えしたい意図をより正確に表している
-
サイズが分からない要素
.element { position: fixed; inset: 0; width: fit-content; height: fit-content; margin: auto; }- 要素サイズを事前に把握できない場合は、
width: fit-contentとheight: fit-contentでコンテンツを包ませられる max-width: 60vwのような制限を追加することもできるが必須ではなく、要素は viewport 内に収まる
- 要素サイズを事前に把握できない場合は、
-
意図的に少しずらした中央
bottom: 48pxのように片側の inset 値を調整すると、要素は指定値の半分だけ移動するbottom: 48pxなら要素は上に24px移動する- これは要素が上下の境界のあいだにある 仮想ボックス の中で中央に吊られているためである
transform: translateY(-48px)を使えば、要素を正確に48px上へ移動できるbottomオフセット方式なら、transformプロパティを後のアニメーションや導入エフェクト用に残しておける
CSS Gridで短く中央揃えし、重ねて配置する
- CSS Grid で最も短い中央揃えコードは、
display: gridとplace-content: centerの組み合わせである
.container {
display: grid;
place-content: center;
}
-
place-contentはjustify-contentとalign-contentの短縮形で、行と列に同じ値を適用する -
この設定によって、親コンテナの中央に 1×1 Grid セルが作られる
-
Flexboxとの違い
- 見た目は Flexbox と似ていても、CSS Grid はまったく異なるレイアウトアルゴリズムを使う
- 子要素に
width: 50%とheight: 50%を与えると違いが現れる - Flexbox ではパーセンテージは親
.container基準で計算される - CSS Grid ではパーセンテージは Grid セル 基準で計算される
grid-template-columnsやgrid-template-rowsを指定しない場合、Grid トラックはコンテンツ基準でサイズ計算されるため、要素が想定より小さくなることがある- このような場合は Grid を修正するために CSS を追加できるが、単純な中央揃えなら Flexbox のほうが簡単なこともある
-
複数要素を同じ位置に重ねて配置
.container { display: grid; place-content: center; } .element { grid-row: 1; grid-column: 1; }- CSS Grid は複数の子要素を同じセルに配置できる
- すべての
.elementにgrid-row: 1とgrid-column: 1を与えると、要素同士が同じ Grid 空間を共有し、前後に重なって積み上がる - 子要素のサイズが互いに異なっていても機能する
.container { display: grid; place-content: center; place-items: center; } .element { grid-row: 1; grid-column: 1; }- サイズの異なる子要素を中央で重ねたい場合は、追加で
place-items: centerが必要である place-itemsはjustify-itemsとalign-itemsの短縮形で、Grid セル内での画像の整列を制御する- このプロパティがないと Grid セル自体は中央にあっても、セル内の画像は左上に積み重なる
- CSS Grid をさらに深く知りたいなら An Interactive Guide to CSS Grid を参照できる
テキストはtext-alignで別途整列する
- テキストは CSS では別個に扱う必要があり、Flexbox のようなレイアウト手法は個々の文字を整列しない
- Flexbox で段落を中央に置くと、段落ブロック は中央に来ても、段落内の文字は左揃えのまま残る
- テキスト自体を中央揃えするには
text-align: centerを使う必要がある
.container {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
Flow layoutの未来: align-content
- Flow layout では水平方向の中央揃えは auto margin で可能だが、垂直方向の中央揃えにはこれまで Flexbox や Grid のような別のレイアウトモードが必要だった
- 2024年初頭時点でブラウザベンダーは、Flow layout における
align-contentを実装中である - この新しい挙動はコンテンツの block 方向の整列 を制御し、当時は Chrome Canary のフラグ付き機能と Safari Technical Preview でのみ利用できた
- 例のデモは実際の Flow layout の挙動ではなく、Chrome Canary と Safari TP の動作を確認したうえで Flexbox で再現したものである
- この機能は新しいUIを生み出すものではないが、単純な中央揃えのために別のレイアウトモードへ切り替える必要性を減らせる可能性がある
状況別の選び方
- 単一要素を兄弟要素に影響を与えず水平方向に中央揃えしたいなら、Flow layout の auto margin 戦略を使う
- モーダルやバナーのような浮いたUIは、Positioned layout と auto margin で中央に配置する
- 複数要素を同じ位置に重ねて中央に積み上げたいなら、CSS Grid が適している
- テキストを中央揃えしたいなら
text-alignを使い、ほかの中央揃え手法と組み合わせられる - それ以外の大半の状況では、Flexbox が最も汎用的な選択肢である
- 単一または複数の子要素を扱える
- 水平・垂直方向の中央揃えの両方が可能である
- 子要素がコンテナ内にあっても、はみ出していても使える
3件のコメント
そういえば、GeekNewsも記事が中央揃えになっていないのが急に気になりますね(泣)笑
place-items: center;を愛用していますが、方法はほかにもいろいろあるんですね。Hacker Newsのコメント
他のコメントがコメント自体を論評しているので、私も口を挟むと、CSS中央揃えミームはたいてい「ある要素を別の要素のど真ん中に置く方法」を意味していると思う
実装の観点から見て中央揃えが難しく、複数の意味を持ちうるという話はその通りだが、GeoCities や AngelFire の世代にとっては、HTML で 90 年代にも 600x600 の黄色いボックスのど真ん中に
helloを問題なく入れられたので、納得しづらかったより良いとされた新しい道具が、すでにできていた標準的な作業をこなせないのだから腹が立ち、だから 2000 年代後半まで テーブルレイアウトを使い続けていた
CSS は好きだが、これは一種のストックホルム症候群なのかもしれない
valignは Chromium ではなくても動くので驚いたが、最近の変化なのかは分からないhelloを入れることは、CSS の最初のバージョンから可能だった。たとえば HTML のvalign属性は、inline、inline-block、table-cellボックスのvertical-alignCSS プロパティに対応しているただ経験上、テーブルだけを使おうとロマンチックに語ったり、CSS は制限だらけで混乱していると不満を言ったりする人のかなり多くは、実際に CSS がどう動くのかを学ぼうとする努力をほとんどしていなかった。筆者は少なくともその点を自覚している
"valign"属性なしで動作する。ただし固定レイアウトなしでテーブルを使う場合、主要 3 ブラウザ間で微妙な違いを常に見てきたので、一般的には 自動レイアウトの挙動には依存しないだろう良い記事で、名目上は技術系の読者層であることを考えると、ここの反応にはかなり驚いた。自動ページレイアウトと組版は本当に難しく、実際に博士論文のテーマになるほどだ[1]
その複雑さを「自分の意図どおりにしてくれ」のような単純な表現で抽象化できると期待するのは現実的ではない
Gwern Branwen のウェブサイト[2]を見ると芸術に近いが、要点はまず欲しい見た目を決め、そのスタイルの中で文章が表現可能になるよう制約をかけることだ
1995 年に「ウェブ初のゴルフ雑誌」スタートアップ[3]に参加して以来、ウェブページレイアウトを見てきたが、Zen Garden と
A List Apartのメーリングリスト / ウェブサイト[4]のおかげで、さまざまな出力環境でうまく見えるウェブコンテンツを作ることがどれほど難しいかを理解するようになった意味的なコンテンツを画面、紙、有限の平面へ移すことは、もともとの空間から目的地の空間にある規則の集合への 写像または射影であり、その規則には物理的制約、ブラウザソフトウェアの制約、各ブラウザ固有の挙動がすべて含まれる
だから CSS は「最初からウェブページを作ろう」とする人にはめちゃくちゃに見えるが、実際にはできることを妨げる制約というより、選択肢が多すぎる側に近い
[1] https://scholar.google.com/scholar?hl=en&as_sdt=0%2C5&q=thes...
[2] https://gwern.net/
[3] Golfweb という名前で、最終的には CBS Sports の一部になったようだ
[4] https://www.alistapart.com
[1] https://every-layout.dev/rudiments/boxes/
とくに、あらゆるページに当てはまる一つの大きなモデルを志向し、各ページごとに自動レイアウトを毎回再計算しようとするシーシュポス的な目標がある。これにあらゆるウィンドウサイズを対象にするという目標まで加わると、なぜそれが可能だと思ったのか分からない
https://css-art.com/the-girl-with-a-p-e-a-r-l-css-earring/
中央揃えされた
divがいくつ含まれているのかは分からないとくに列ごとにサイズの異なるテキストやオブジェクトが入っている表で、要素をいつどうやって次のページへ送るかを決めるのは、よいヒューリスティクスを選ぶ厄介な作業だ
custom appkit、GTK コントロール、非公開の Lua ベースのツールキットでも、コンテンツの中央揃えや要素の折り返し・整列は大したことではなかったのに、ウェブでは何を見落としているのか気になる
「選択肢が豊富なだけ」という言い方は、ずっと前に葬られた TMTOWTDI にも少し似て聞こえる
素晴らしい記事で、インタラクティブな要素がとくに良い。数年前に CSS の位置指定と中央揃えを理解するうえで大いに役立ったのは ボックスモデルを読んだことだった
ボックスモデルを理解すると DOM 内のフローを判断する助けになり、
displayとpositionの CSS プロパティも位置指定を学ぶうえで基本になる。MDN のドキュメントはよくできているhttps://developer.mozilla.org/en-US/docs/Learn/CSS/Building_...
https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layou...
「中央揃えの方法」は CSS の古典的な質問であり、それが目の前に見えているほど明白ではないという事実自体が多くを物語っている。CSS は 混沌とした寄せ集め に近く、単一の委員会ではなく複数の委員会が同時に設計した流し台式の詰め合わせだ
実際のリリースという概念はずっと前に放棄されており、現在の CSS の状態は、変化し続ける個別モジュールの状態を寄せ集めたものに近い。これはソフトウェアを開発するやり方ではなく、実際、何かを作るうえで良いやり方でもない
Web とその技術群が集団としてどこへ向かっているのかも明確ではないため、失敗した実験や不一致が多く生まれるのは避けられない。明確な目標と道筋がある、よく計画された工学プロジェクトよりもはるかに広い範囲なのだから
Web ページを望む見た目にしようとする人が最初に学ぶのは、たいてい文字サイズ、色、背景色、配置であり、配置を除けば残りは CSS 以前のやり方とほぼ 1:1 に対応している
CSS 以前は、コンテンツを中央に置きたければ単にタグに入れればよく、テキストであれ
div、表、ボタンのような HTML オブジェクトであれ関係なかった。多くの人は CSS も昔のように インライン要素とブロック要素の区別なく 動くことを期待していたが、CSS がその先入観に合わなかったため、こうした質問が生まれたのだこの記事は本当に良く、特にインタラクションのしかたが素晴らしい。かなり前から、ほぼいつも望んだ結果をくれたツールもある
http://howtocenterincss.com
CSS がコンテンツを中央に置くテーブル並みに使える解決策を出すまでに何十年もかかったが、その間 レイアウトにテーブルを使うこと は非難されていた
HTML テーブルはアクセシビリティのために少なくとも `` のような処理が必要だ
https://developer.mozilla.org/en-US/docs/Learn/HTML/Tables/A...
CSS Grid Layout の資料も参考になる
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_la...
Firefox DevTools > INTRODUCTION TO CSS GRID LAYOUT: https://mozilladevelopers.github.io/playground/css-grid/
CSS Grid Garden: https://cssgridgarden.com/
MDN > "Relationship of grid layout to other layout methods": https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_la...
MDN: "Box alignment in grid layout": https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_la...
Web 開発にはコンテンツがページのどこに置かれるか以上の要素があり、だからこそ良い Web 開発は難しいのだ
divと CSS の利点はヒップスター的な評判で、欠点は DIV スープ だった当時の CSS は、人々がやろうとしていたことに対して信じられないほど不向きだった。文書の書式設定用に設計されていて、Web アプリや画面レイアウト用に設計されたものではなかったからだと思う
一方で
tableの利点は、実際に動作することだったここにいる多くの人と同じく、CSS は完全な災厄だと思う。核心的な問題は、スタイル指定が絶えず互いを 上書きしたり、まったく効果がないまま静かに失敗したりすることだ
例のひとつにあったクッキー案内が残酷なほど正直で良かった
「私たちはあなたの個人情報データを大切にしています。ブラウジング体験を向上させるため、このデータを広告主に販売するクッキーを使用します。これは非常に価値があります」
レイアウトにテーブルを使ってきた歴史から学べることがあるのは興味深い。テーブルには境界線、パディング、列に並んだセルベースのレイアウトがあり、拡張するとテーブルとセルの周囲には余白、つまりマージンも必要になる
テーブルはレイアウトにおいて長く確立された要素であり、実際、すべての要素がある程度 テーブルセルのように振る舞うべきだ という知恵を含んでいた
要素はボックスモデルに従うべきで、これはタイポグラフィを扱う人にはかなり自明だが、同時に列に並ぶべきだという点はそれほど明白ではなく、Grid layout や Bootstrap の基盤になっている
レイアウト問題に出会ってテーブルで解決したあと、テーブルの一部の特性は持つが全部ではない新機能が必要だと気づくのは自然な進化だ
CSS はこれを見いだしたが、不思議なことに、ワードプロセッサのような一部のシステムは要素をボックスモデルの下に統合できなかった
「なぜいまだにこんなに難しいのか」という不満は、かなり的外れに感じられる。記事でも述べられているように、Flexbox は単純なあらゆるケースの中央揃えを直感的に解決する。
Flexbox で解決できないなら、それは単に中央揃えをしているだけではなく、より複雑なことをしているのであって、実装がとても単純であることを期待するのは適切ではない
今では方法が多すぎて、複雑さに圧倒される。新しく作る場合より古いコードを直す場合のほうが多く、なぜ CSS が特定の書き方になっているのか、どんなエッジケースが壊れるのか、直してよいのか、単純でないときに複数の解法のうちどれを選ぶべきかを考えなければならない。
記事をざっと見ても直感的ではない。Flexbox でも横方向の設定は
justify-content、縦方向の設定はalign-itemsだが、CSS のプロパティ名は多すぎて恣意的で、もううまく覚えられない。結局のところ違いは、単純で直感的かつ信頼できるビルディングブロックで複雑な解法を組み立てるのか、それとも一部が重なり合い、毎回検索し続けなければならない複雑なビルディングブロックで複雑な解法を組み立てるのか、という点にある。
Go や Python は前者に近く、CSS は後者に近い
人々が Bootstrap のグリッドシステムを好んでいたのには理由があり、Flexbox はそれらすべてと、それ以上のことをブラウザ内でそのまま実現してくれる。どれほど気に入っているかは誇張しようがないほどだ
divを中央揃えするのが錬金術とロケット科学の中間のようなものだと語る人がいる。Web 開発のほかの部分ほど CSS の変化を追っていないのに、そういう断言だけは気軽にする姿勢が表れている
外側から内側へ、親要素から子要素へとたどると、ずっと簡単になる。技術は必要だが、基本的には 弾性代数 に近い