1. ホーム
  2. ハイパーリンク

[解決済み】フレックスボックスの要素を中央に配置し、他の要素を右/左揃えする

2022-04-30 19:08:21

質問

が欲しいです。 A BC を真ん中に並べました。

どうすれば D を完全に右へ移動させることはできますか?

ビフォーです。

AFTER

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/

解決方法は?

このレイアウトを実現するための選択肢は、以下の5つです。

  • CSSによる位置決め
  • 不可視のDOM要素によるフレックスボックス
  • フレックスボックスと不可視の疑似要素
  • フレックスボックス flex: 1
  • CSSグリッドレイアウト

方法その1:CSSの位置決めプロパティ

適用 position: relative をフレックスコンテナに追加します。

適用 position: absolute を項目Dに追加します。

これで、このアイテムはフレックスコンテナ内に絶対配置されました。

具体的には、アイテムDはドキュメントフローからは外れるが 最も近い位置にある祖先 .

CSSオフセットプロパティを使用する topright でこの要素を所定の位置に移動させます。

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:フレックス自動マージン & インビジブルフレックスアイテム(DOM要素)

の組み合わせで auto 余白 と、レイアウトが見えない新しいフレックスアイテムを実現することができます。

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

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

新しいアイテムが表示されないようにするには visibility: hidden .

要するに

  • の複製を作成します。 D 要素を使用します。
  • リストの先頭に配置する。
  • フレックスを使用する auto を維持するためにマージン A , BC を中央に配置し、両者を 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:フレックス自動マージン & 不可視のフレックスアイテム(擬似要素)

この方法は#2と似ていますが、セマンティックにすっきりしており、また D は既知でなければならない。

  • と同じ幅の擬似要素を作成します。 D .
  • でコンテナの先頭に配置します。 ::before .
  • フレックスの使用 auto を維持するためにマージン A , BC が完全に中央に配置され、疑似と 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 を個々の項目に追加して、その内容を整列させることができます。

注意事項 との併用について 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 ) は、現在でも多くのブラウザである程度有効です。詳細については こちら ここで .

のコメントに投稿された問題の図解を紹介します。 ユーザー2651804 :

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