以下は、このレイアウトを実現するための5つのオプションです。
- CSSポジショニング
- 非表示のDOM要素を持つFlexbox
- 非表示の疑似要素を持つフレックスボックス
- フレックスボックス
flex: 1
- CSSグリッドレイアウト
方法#1:CSS配置プロパティ
position: relative
フレックスコンテナーに適用します。
position: absolute
項目Dに適用します。
これで、このアイテムはフレックスコンテナー内に完全に配置されます。
より具体的には、アイテムDはドキュメントフローから削除されますが、最も近くに配置されている祖先の境界内にとどまります。
CSSオフセットプロパティtop
を使用して、right
この要素を適切な位置に移動します。
li:last-child {
position: absolute;
top: 0;
right: 0;
background: #ddd;
}
ul {
position: relative;
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
p {
text-align: center;
margin-top: 0;
}
span {
background-color: aqua;
}
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
この方法の注意点の1つは、一部のブラウザーでは、絶対位置のフレックス項目を通常のフローから完全に削除できない場合があることです。これにより、非標準の予期しない方法で配置が変更されます。詳細:絶対配置されたフレックスアイテムがIE11の通常のフローから削除されない
方法#2:Flexの自動マージンと非表示のFlexアイテム(DOM要素)
auto
マージンと新しい非表示のフレックスアイテムの組み合わせにより、レイアウトを実現できます。
新しいflexアイテムはアイテムDと同じで、反対側の端(左端)に配置されます。
より具体的には、フレックスアラインメントは空き領域の分布に基づいているため、新しいアイテムは、中央の3つのボックスを水平方向に中央に保つために必要なバランスです。新しいアイテムは既存のDアイテムと同じ幅でなければなりません。そうしないと、中央のボックスが正確に中央に配置されません。
新しいアイテムはでビューから削除されますvisibility: hidden
。
要するに:
D
要素の複製を作成します。
- リストの最初に配置します。
- フレックス使用
auto
維持するマージンをA
、B
そしてC
両方に、センタリングD
要素は両端から等しくバランスを作成します。
visibility: hidden
複製に適用D
li:first-child {
margin-right: auto;
visibility: hidden;
}
li:last-child {
margin-left: auto;
background: #ddd;
}
ul {
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
<ul>
<li>D</li><!-- new; invisible spacer item -->
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
方法#3:Flexの自動マージンと非表示のFlexアイテム(疑似要素)
この方法は#2に似ていますが、意味的によりクリーンであり、幅D
がわかっている必要があります。
- と同じ幅の疑似要素を作成します
D
。
- でコンテナの先頭に配置し
::before
ます。
- フレックス使用
auto
維持するマージンA
、B
及びC
疑似として、完全に中心D
要素は両端から等しくバランスを作成します。
ul::before {
content:"D";
margin: 1px auto 1px 1px;
visibility: hidden;
padding: 5px;
background: #ddd;
}
li:last-child {
margin-left: auto;
background: #ddd;
}
ul {
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
方法#4:flex: 1
左と右のアイテムに追加する
上記の方法#2または#3から始めて、均等なバランスを維持するために左右のアイテムの幅が等しいことを心配する代わりに、それぞれに1つずつ指定しflex: 1
ます。これにより、両方が使用可能なスペースを強制的に消費するため、中央のアイテムが中央に配置されます。
次にdisplay: flex
、個々のアイテムに追加して、それらのコンテンツを揃えることができます。
このメソッドをで使用する場合のmin-height
注意:現在Chrome、Firefox、Edge、およびおそらく他のブラウザーでは、省略ルールflex: 1
はこれに分類されます:
flex-grow: 1
flex-shrink: 1
flex-basis: 0%
そのパーセンテージ単位(%)がオンになっているflex-basis
と、このメソッドmin-height
がコンテナーで使用されている場合にこのメソッドが壊れます。これは、原則として、子のパーセントの高さheight
には親の明示的なプロパティ設定が必要であるためです。
これは1998年に遡る古いCSSルール(CSSレベル2)で、多くのブラウザである程度有効です。詳細については、こことここを参照してください。
これは、user2651804のコメントに投稿された問題の図です。
#flex-container {
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
}
#flex-container>div {
background: orange;
margin: 5px;
}
#flex-container>div:first-child {
flex: 1;
}
#flex-container::after {
content: "";
flex: 1;
}
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
解決策は、パーセント単位を使用しないことです。試してみるpx
か、まったく何もしないでください(これは、主要なブラウザの少なくとも一部が何らかの理由でパーセント単位を追加しているという事実にもかかわらず、仕様で実際に推奨されていることです)。
#flex-container {
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
}
#flex-container > div {
background: orange;
margin: 5px;
}
/* OVERRIDE THE BROWSER SETTING IN THE FLEX PROPERTY */
#flex-container > div:first-child {
flex: 1;
flex-basis: 0;
}
#flex-container::after {
content: "";
flex: 1;
flex-basis: 0;
}
/* OR... JUST SET THE LONG-HAND PROPERTIES INDIVIDUALLY
#flex-container > div:first-child {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
#flex-container::after {
content: "";
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
*/
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
方法#5:CSSグリッドレイアウト
これは最もクリーンで効率的な方法かもしれません。絶対配置、偽の要素、その他のハッカーの必要はありません。
複数の列を持つグリッドを作成するだけです。次に、アイテムを中央と最後の列に配置します。基本的に、最初の列は空のままにしておきます。
ul {
display: grid;
grid-template-columns: 1fr repeat(3, auto) 1fr;
grid-column-gap: 5px;
justify-items: center;
}
li:nth-child(1) { grid-column-start: 2; }
li:nth-child(4) { margin-left: auto; }
/* for demo only */
ul { padding: 0; margin: 0; list-style: none; }
li { padding: 5px; background: #aaa; }
p { text-align: center; }
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>| true center |</span></p>