web-dev-qa-db-ja.com

flexbox要素の中央揃えと右揃え

ABCを中央に揃えたいです。

Dを取得して完全に右に移動するにはどうすればよいですか?

前:

enter image description here

後:

enter image description here

これを行うためのベストプラクティスは何ですか?

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;
}
li:last-child {
  background: #ddd;
  /* magic to throw to the right*/
}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>

https://jsfiddle.net/z44p7bsx/

81
hazyred

以下は、このレイアウトを実現するための5つのオプションです。

  • CSSポジショニング
  • 不可視のDOM要素を持つFlexbox
  • 目に見えない擬似要素を持つFlexbox
  • flex: 1を含むFlexbox
  • CSSグリッドレイアウト

方法#1:CSSの配置プロパティ

position: relativeをflexコンテナに適用します。

position: absoluteをアイテムDに適用します。

これで、このアイテムはflexコンテナ内に完全に配置されました。

より具体的には、アイテム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つの注意点この方法の場合、一部のブラウザーでは、通常のフローから絶対配置のflexアイテムを完全に削除できない場合があります。これにより、非標準の予期しない方法でアライメントが変更されます。詳細:絶対位置のflexアイテムはIE11の通常のフローから削除されません


方法#2:Flexの自動マージンと非表示のFlexアイテム(DOM要素)

autoマージン と新しい不可視のフレックスアイテムの組み合わせにより、レイアウトを実現できます。

新しいフレックスアイテムはアイテムDと同じで、反対側の端(左端)に配置されます。

より具体的には、フレックスアライメントは空きスペースの分布に基づいているため、新しいアイテムは、3つの中央のボックスを水平方向に中央に保つために必要なカウンターバランスです。新しいアイテムは、既存のDアイテムと同じ幅でなければなりません。そうしないと、中央のボックスが正確に中央に配置されません。

visibility: hiddenを使用して、新しいアイテムがビューから削除されます。

要するに:

  • D要素の複製を作成します。
  • リストの先頭に配置します。
  • フレックスautoマージンを使用して、AB、および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アイテム(擬似要素)

このメソッドは、セマンティックにクリーンであり、Dの幅がわかっている必要があることを除いて、#2に似ています。

  • Dと同じ幅の擬似要素を作成します。
  • ::beforeを使用して、コンテナの先頭に配置します。
  • フレックスautoマージンを使用して、ABおよび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から始めて、左右のアイテムの幅を等しくしてバランスを維持する代わりに、それぞれにflex: 1を与えるだけです。これにより、両方の使用可能なスペースが消費され、中央のアイテムが中央に配置されます。

その後、display: flexを個々のアイテムに追加して、コンテンツを揃えることができます。

NOTEmin-heightでこのメソッドを使用することについて現在、Chrome、Firefox、Edgeおよび場合によっては他のブラウザでは、簡略ルールflex: 1は次のように分類されます。

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0%

flex-basisパーセント単位(%)を指定すると、min-heightがコンテナで使用されると、このメソッドが中断します。これは、原則として、子の高さのパーセンテージには親の明示的なheightプロパティ設定が必要だからです。

これは1998年に遡る古いCSSルール( CSSレベル2 )であり、多くのブラウザーである程度有効です。詳細については、 here および here を参照してください。

ser2651804 によってコメントに投稿された問題の図を以下に示します。

#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>
130
Michael_B

整列させたい場合は、単純に空のスパンを接続し、3つの子スパンをそれらに分割します。

1
Ali Korkmaz

非常に明確な質問。数時間掘り下げた後、答えを投稿せざるを得なかった。テーブル、テーブルセル、絶対位置、変換でこれを解決できましたが、flexboxでそれをしなければなりませんでした:)

.parent {
  display: flex;
  justify-content: flex-end;
}

.center {
  margin: auto;
}

http://codepen.io/rgfx/pen/BLorgd

0
rgfx

display:gridアプローチを使用すると、すべてのulの子を同じセルに配置してからjustify-selfを設定できます。

ul {
  display: grid;
}

ul > * {
  grid-column-start: 1;
  grid-row-start: 1;
  justify-self:center;
}

ul > *:last-child {
  justify-self: right;
}

/* Make Fancy */
li {
  display:inline-block;
  margin: 1px;
  padding: 5px;
  background: #bbb;
}
<ul>
  <span>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  </span>
  <li>D</li>
</ul>
0
Steven Spungin

Michael_Banswer を展開しました

.center-flex__2-of-3 > :nth-child(1), .center-flex__2-of-3 > :nth-child(3) {
  flex: 1;
}
.center-flex__2-of-3 > :nth-child(1) {
  justify-content: flex-start;
}
.center-flex__2-of-3 > :nth-child(3) {
  justify-content: flex-end;
}
.center-flex__1-of-2 > :nth-child(1) {
  margin: auto;
}
.center-flex__1-of-2 > :nth-child(2) {
  flex: 1;
  justify-content: flex-end;
}
.center-flex__2-of-2 > :nth-child(1) {
  flex: 1;
  justify-content: flex-start;
}
.center-flex__2-of-2 > :nth-child(2) {
  margin: auto;
}
.center-flex__1-of-2:before, .center-flex__1-of-1:before {
  content: '';
  flex: 1;
}
.center-flex__1-of-1:after, .center-flex__2-of-2:after {
  content: '';
  flex: 1;
}

[class*=center-flex] {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  border: 10px solid rgba(0, 0, 0, 0.1);
}
[class*=center-flex] > * {
  display: flex;
}
li {
  padding: 3px 5px;
}
2 of 3
<ul class="center-flex__2-of-3">
  <span>
    <li>Accusamus</li>
    <li>Porro</li>
  </span>
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
</ul>

<br><br>
1 of 2
<ul class="akex center-flex__1-of-2">
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
</ul>

<br><br>
2 of 2
<ul class="akex center-flex__2-of-2">
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
</ul>

<br><br>
1 of 1
<ul class="center-flex__1-of-1">
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
</ul>

ここではSASSをコードペンとして使用

0
yunzen