複数行のフレックスボックスレイアウトで改行を指定する方法


236

複数行のフレックスボックスで改行する方法はありますか?

たとえば、このCodePenの 3番目のアイテムごとに中断する場合

.container {
  background: tomato;
  display: flex;
  flex-flow: row wrap;
  align-content: space-between;
  justify-content: space-between;
}
.item {
  width: 100px;
  height: 100px;
  background: gold;
  border: 1px solid black;
  font-size: 30px;
  line-height: 100px;
  text-align: center;
  margin: 10px;
}
.item:nth-child(3n) {
  background: silver;
}
<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
  <div class="item">7</div>
  <div class="item">8</div>
  <div class="item">9</div>
  <div class="item">10</div>
</div>

お気に入り

.item:nth-child(3n){
  /* line-break: after; */    
}

1
同じまたは非常に似た問題がありました。4番目のアイテムごとに分割したかったので、各flexアイテムの幅を25vw(または25%)に設定しました。したがって、あなたのケースでは、3番目のアイテムごとに33.3vw(または33.3%)を使用します。私が欲しかったもののために完全に働きました。彼らがより簡単な方法を探しているなら、誰かを助けるかもしれません。
ベンクラーク2017年

ベン・クラーク!どうもありがとうございます!あなたの答えがうまくいった唯一のものです。回答として追加することを検討してください。:-)
itmuckel 2017

回答:


322

最も簡単で信頼性の高いソリューションは、適切な場所にフレックスアイテムを挿入することです。それらが十分に広い場合(width: 100%)、それらは改行を強制します。

しかし、それは醜く、意味的ではありません。代わりに、フレックスコンテナー内に疑似要素を生成し、それを使用orderして適切な場所に移動できます。

ただし、制限があります。フレックスコンテナには、::beforeおよび::after疑似要素しか含めることができません。つまり、強制できる改行は2つだけです。

これを解決するには、フレックスコンテナー内ではなく、フレックスアイテム内に擬似要素を生成します。この方法では、2に制限されません。しかし、これらの疑似要素はフレックスアイテムではないため、強制的に改行することはできません。

しかし幸いにも、CSS Display L3が導入されましたdisplay: contents(現在はFirefox 37でのみサポートされています)。

要素自体はボックスを生成しませんが、その子と疑似要素は通常どおりボックスを生成します。ボックスの生成とレイアウトのために、要素は、ドキュメントツリー内の子要素と疑似要素で置き換えられたかのように処理する必要があります。

したがってdisplay: contents、フレックスコンテナーの子に適用し、それぞれのコンテンツを追加のラッパーでラップすることができます。次に、フレックス項目は、それらの追加のラッパーと子の疑似要素になります。

または、Fragmenting Flex LayoutおよびCSS Fragmentationによると、Flexboxはbreak-beforebreak-afterまたはそれらのCSS 2.1エイリアスを使用して強制ブレークを許可します。

.item:nth-child(3n) {
  page-break-after: always; /* CSS 2.1 syntax */
  break-after: always; /* New syntax */
}

flexboxでの強制改行はまだ広くサポートされていませんが、Firefoxでは機能します。


@オリオール最初のアプローチについて、なぜそれが醜くて意味的ではないと言うのですか?ちょっと興味があるんだけど。
nacho4d 2016

18
@ nacho4d HTMLをスタイル設定の目的で変更してはならないため。また、気が変わって3列ではなく4列にする場合は、多くのHTMLを変更する必要があります。break-afterスタイルシートのセレクターを変更するだけでよいソリューションと比較してください。
Oriol

1
IEでソリューション2を機能させるdisplay: block;には、.container ::beforeおよび::after疑似クラスに追加する必要がありました。YMMV!
絡まっ

1
@twinedフレックスアイテムは自動的にブロック化されるため、これは奇妙です。
Oriol 2016

2
改ページは明らかに仕様から削除されているため、2番目のスニペットを列方向に実行し、コンテナーの高さを拡張しないようにすることは可能ですか?運が悪く、フレックスベースを100%に設定すると、アイテムの高さが伸びます。
ルーセント2017年

42

私の観点からは、フレックス項目間の<hr> 改行として要素を使用する方がセマンティックです。

.container {
  display: flex;
  flex-flow: wrap;
}

.container hr {
  width: 100%;
}
<div class="container">
  <div>1</div>
  <div>2</div>
  <hr>
  <div>3</div>
  <div>2</div>
  ...
</div>

Chrome 66、Firefox 60、Safari 11でテスト済み。


7
これも私がやる方法で、うまくいきます。hr {flex-basis:100%; 高さ:0; マージン:0; ボーダー:0; }は中断をシームレスにします。
Besworks

私はこのアプローチが好きです。注:gap: 10px;行間の距離を使用する場合、実際には20pxです。対処するには、サイズの半分の行ギャップを指定しますgap: 5px 10px;
CuddleBunny

@Besworks:の代わりににborder設定する必要がありますnone0
Mark

@マークはborder:0;と同じように有効ですborder:none;。参照:stackoverflow.com/questions/2922909/...
Besworks

23

@Oriolは素晴らしい答えを持っています。残念ながら、2017年10月現在、どちらdisplay:contentspage-break-after広くサポートされていません。Firefoxがこれをサポートしているが他のプレイヤーはサポートしていないと言った方がいいと思います。次の「ハック」を考えました。 3番目の要素ごとに改行を入れてコーディングすると、ページをモバイルフレンドリーにするのが非常に難しくなります。

すでに述べたように、これはハックであり、欠点は何も追加せずに非常に多くの要素を追加する必要があることですが、トリックを実行し、日付の古いIE11でもクロスブラウザーで機能します。

「ハック」は、各divの後に追加の要素を単に追加することです。これはに設定display:noneされ、CSS nth-childを使用して、実際に表示する必要があるものを決定して、次のようなラインブレーキを強制します。

.container {
  background: tomato;
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}
.item {
  width: 100px;
  background: gold;
  height: 100px;
  border: 1px solid black;
  font-size: 30px;
  line-height: 100px;
  text-align: center;
  margin: 10px
}
.item:nth-child(3n-1) {
  background: silver;
}
.breaker {display:none;}
.breaker:nth-child(3n) {
  display:block;
  width:100%;
  height:0;
 }
<div class="container">
  <div class="item">1</div><p class=breaker></p>
  <div class="item">2</div><p class=breaker></p>
  <div class="item">3</div><p class=breaker></p>
  <div class="item">4</div><p class=breaker></p>
  <div class="item">5</div><p class=breaker></p>
  <div class="item">6</div><p class=breaker></p>
  <div class="item">7</div><p class=breaker></p>
  <div class="item">8</div><p class=breaker></p>
  <div class="item">9</div><p class=breaker></p>
  <div class="item">10</div><p class=breaker></p>
</div>


2
また、「display:contents」および「page-break-after」メソッドが機能していないことがわかり、この「ハッキング」に頼りました。これはChromeのバグとして報告され、「WontFix」(bugs.chromium.org/p/chromium/issues/detail?id=473481を参照)と説明され、「CSSワーキンググループによると、 CSSを使用してフレックスボックスで改行を強制する現在の方法。」
Martin_W

セレクターを使用すると、煩雑さを軽減できます.container>p<p></p>そうすれば、これらのタグはすべてclass属性を必要としません。もちろん重要ではありません。私の怠惰な脳があなたの賢い解決策に小さな、省スペースの微調整を見つけました。もちろん、divの<p>直接の子として他のタグがないユーザーにも依存します.container。技術的には他のすべてのと同じことを行うことができ<div>、子供ができますが、より多くの可能性が高い他の持っている<div>sで.containerあなたがより<p>ので、おそらく、そこに賢明sのではありません。
スティーブ

13

セマンティックな改行が必要ですか?

次に、の使用を検討してください<br>。W3Schoolsは、それBRが詩を書くためだけのものであると提案しているかもしれません(私のものは近日公開予定です)。スタイルを変更して、コンテンツを次の行にプッシュする100%幅のブロック要素として動作させることができます。「br」が中断を示唆している場合は、hrまたは100%を使用するよりも適切であると思われdiv、HTMLが読みやすくなります。

<br>改行が必要な場所に挿入し、次のようにスタイル設定します。

 // Use `>` to avoid styling `<br>` inside your boxes 
 .container > br 
 {
    width: 100%;
    content: '';
 }

あなたができる無効に<br>メディアクエリを設定することで、display:blockたりnone、必要に応じて(私はこれの例を含めましたが、それはコメントアウト左)。

order:必要に応じて、を使用して順序を設定することもできます。

そして、クラスや名前を変えて、好きなだけ置くことができます:-)

.container {
  background: tomato;
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}
.item {
  width: 100px;
  background: gold;
  height: 100px;
  border: 1px solid black;
  font-size: 30px;
  line-height: 100px;
  text-align: center;
  margin: 10px
}

.container > br
{
  width: 100%;
  content: '';
}

// .linebreak1 
// { 
//    display: none;
// }

// @media (min-width: 768px) 
// {
//    .linebreak1
//    {
//       display: block;
//    }
// }
<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <br class="linebreak1"/>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
  <div class="item">7</div>
  <div class="item">8</div>
  <div class="item">9</div>
  <div class="item">10</div>
</div>


W3Schoolsが言うことに自分を制限する必要はありません:

ここに画像の説明を入力してください


テクニックの拡張の1つは、<br class="2col">2つおきのアイテムの<br class="3col">後に、3つおきのアイテムの後に置くことです。次にcols-2、コンテナーにクラスを適用し、cssを作成して、その数の列に適切な改行のみを有効にします。例えば。br { display: none; } .cols-2 br.2col { display: block; }
Simon_Weaver

いいえ、br改行のためではない要素は、それがためにあるテキストdeveloper.mozilla.org/en-US/docs/Web/HTML/Element/br ... stackoverflow.com/questions/3937515/...
朝臣

2
これを完璧な解決策として提示しないように表現を変更しますが、場合によっては、これが他のdivまたは疑似要素の解決策よりも悪いとは思われません。多分私はそれについての詩を書きに行きます。
Simon_Weaver

うん...詩はいいだろう、ここへのリンクをここに投稿することを忘れないでください:) ...完璧な解決策に関しては、(break-*承認された回答に示されている)1つありますが、残念ながらまだクロスブラウザに到達していませんなので、2番目の方法は、親の幅をネイティブで埋める要素を使用し、次の兄弟をそれらの行にプッシュすることです。これも、受け入れられた回答で示されます。したがって、ブロックのような要素以外の要素を使用することは、意味的にはのように悪化しbrます。
エイソン

5
W3CではなくW3Schoolの印刷物を投稿することを忘れないでください。それらは接続されていません。
Edu Ruiz

7

従来の方法は柔軟性があり、かなり理解しやすいと思います。

マークアップ

<div class="flex-grid">
    <div class="col-4">.col-4</div>
    <div class="col-4">.col-4</div>
    <div class="col-4">.col-4</div>

    <div class="col-4">.col-4</div>
    <div class="col-4">.col-4</div>
    <div class="col-4">.col-4</div>

    <div class="col-3">.col-3</div>
    <div class="col-9">.col-9</div>

    <div class="col-6">.col-6</div>
    <div class="col-6">.col-6</div>
</div>

grid.cssファイルを作成します。

.flex-grid {
  display: flex;
  flex-flow: wrap;
}

.col-1 {flex: 0 0 8.3333%}
.col-2 {flex: 0 0 16.6666%}
.col-3 {flex: 0 0 25%}
.col-4 {flex: 0 0 33.3333%}
.col-5 {flex: 0 0 41.6666%}
.col-6 {flex: 0 0 50%}
.col-7 {flex: 0 0 58.3333%}
.col-8 {flex: 0 0 66.6666%}
.col-9 {flex: 0 0 75%}
.col-10 {flex: 0 0 83.3333%}
.col-11 {flex: 0 0 91.6666%}
.col-12 {flex: 0 0 100%}

[class*="col-"] {
  margin: 0 0 10px 0;

  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

@media (max-width: 400px) {
  .flex-grid {
    display: block;
  }
}

を作成しました(jsfiddle)

400px未満でウィンドウのサイズを変更してみてください。


このソリューションでは、要素が一緒になっています。アイデアは、要素間に長い空白スペースを設けることです。
Juanma Menendez

2

マークアップを追加する必要のないもう1つの解決策は、動的なマージンを追加して要素を分離することです。

例の場合、これはの助けを借りて行うことができるcalc()だけ加算、margin-left及びmargin-right3N + 2要素(2、5、8)〜

.item:nth-child(3n+2) {
  background: silver;
  margin: 10px calc(50% - 175px);
}

スニペットの例

.container {
  background: tomato;
  display: flex;
  flex-flow: row wrap;
  align-content: space-between;
  justify-content: space-between;
}
.item {
  width: 100px;
  height: 100px;
  background: gold;
  border: 1px solid black;
  font-size: 30px;
  line-height: 100px;
  text-align: center;
  margin: 10px;
}
.item:nth-child(3n+2) {
  background: silver;
  margin: 10px calc(50% - 175px);
}
<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
  <div class="item">7</div>
  <div class="item">8</div>
  <div class="item">9</div>
  <div class="item">10</div>
</div>


1
これは投票に値します。フレックスとマージンの組み合わせは、改行をサポートするための本当に簡単な方法です。またcalc、この回答で概説されているように、それは本当にうまく機能します。
stwilz

私はこれが好きでmargin-right: 1px、アイテムだけです。次のアイテムが新しい行から始まるようになります。
アービル

0

今後の質問については、floatプロパティを使用して3つの要素ごとにクリアすることもできます。

これが私が作った例です。

.grid {
  display: inline-block;
}

.cell {
  display: inline-block;
  position: relative;
  float: left;
  margin: 8px;
  width: 48px;
  height: 48px;
  background-color: #bdbdbd;
  font-family: 'Helvetica', 'Arial', sans-serif;
  font-size: 14px;
  font-weight: 400;
  line-height: 20px;
  text-indent: 4px;
  color: #fff;
}

.cell:nth-child(3n) + .cell {
  clear: both;
}
<div class="grid">
  <div class="cell">1</div>
  <div class="cell">2</div>
  <div class="cell">3</div>
  <div class="cell">4</div>
  <div class="cell">5</div>
  <div class="cell">6</div>
  <div class="cell">7</div>
  <div class="cell">8</div>
  <div class="cell">9</div>
  <div class="cell">10</div>
</div>


3
ここでの問題は、解決策を述べたOPが利用フレキシボックスに持っているかであるdisplay: flex;、ないdisplay: inline-block;
bafromca

1
.cell:nth-child(3n + 1)代わりに次のように書くことができます
Si7ius

-1

ここでいくつかの答えを試しましたが、どれもうまくいきませんでした。皮肉なことに、うまくいったのは、<br/>試行できる最も簡単な代替策でした。

<div style="flex-basis: 100%;"></div>

またはあなたも行うことができます:

<div style="width: 100%;"></div>

改行したい場所に配置します。隣接するでも動作するよう<span>ですが、隣接で使用してい<div>ます。


2
100%幅のdivは、受け入れられた回答で与えられた最初のソリューションです。
TylerH

1
本当です。彼らは悪い理由で見下されています(本当に、醜いですか?)。また、私の答えはflex-basisです。
Andrew

-4

.container {
  background: tomato;
  display: flex;
  flex-flow: row wrap;
  align-content: space-between;
  justify-content: space-between;
}

.item {
  width: 100px;
  height: 100px;
  background: gold;
  border: 1px solid black;
  font-size: 30px;
  line-height: 100px;
  text-align: center;
  margin: 10px;
}
<div class="container">
  <div>
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
  </div>
  <div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
  </div>
  <div>
    <div class="item">7</div>
    <div class="item">8</div>
    <div class="item">9</div>
  </div>
  <div class="item">10</div>
</div>

このようなdom要素でアイテムをラップしてみることができます。これを使えば、良い構造を持っているだけで多くのcssが問題を解決することを知る必要はありません。


1
コンテナを通常にdisplay: blockして、それらの新しい階層2 divフレックスボックスにすることができます。これは行に対して機能します。列モードを使用する場合は、divをスパンに置き換えます。
jiggunjer 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.