web-dev-qa-db-ja.com

flexbox /グリッドレイアウトで折りたたむ最後のマージン/パディング

フレックスボックスでスクロール可能な水平レイアウトに配置しようとしているアイテムのリストがあります。

コンテナ内の各アイテムには左と右のマージンがありますが、最後のアイテムの右マージンは縮小されています。

これを阻止する方法、または良い回避策はありますか?

ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
  display: flex;
  height: 300px;
  overflow: auto;
  width: 600px;
  background: orange;
}
ul li {
  background: blue;
  color: #fff;
  padding: 90px;
  margin: 0 30px;
  white-space: nowrap;
  flex-basis: auto;
}
<div class="container">
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
  </ul>
</div>
30
Kevin Wilson

潜在的な問題#1

最後のマージンは崩れていません。無視されています。

overflowプロパティはcontentにのみ適用されます。パディングやマージンには適用されません。

これは、仕様でそれが言うことです:

11.1.1オーバーフロー:overflowプロパティ

このプロパティは、要素のボックスをオーバーフローしたときに、ブロックコンテナー要素のコンテンツをクリップするかどうかを指定します。

CSSボックスモデル を見てみましょう。

enter image description here

ソース: W3C

overflowプロパティは、コンテンツボックス領域に制限されています。コンテンツがコンテナからオーバーフローする場合、overflowが適用されます。ただし、overflowは、パディングやマージンの領域には入りません(もちろん、次のような内容がある場合を除きます)。


潜在的な問題#2

潜在的な問題#1の問題は、フレックスまたはグリッドのフォーマットコンテキストの範囲外にあるように見えることです。たとえば、標準のブロックレイアウトでは、最後のマージンが崩れているように見えません。ですから、仕様で何を言っているかに関係なく、overflowはマージン/パディングをカバーすることが許可されています。

div {
  height: 150px;
  overflow: auto;
  width: 600px;
  background: orange;
  white-space: nowrap;
}
span {
  background: blue;
  color: #fff;
  padding: 50px;
  margin: 0 30px;
  display: inline-block;
}
<div class="container">
    <span>Item 1</span>
    <span>Item 2</span>
    <span>Item 3</span>
    <span>Item 4</span>
</div>

したがって、問題は代わりに「過剰制約」されている要素に関連している可能性があります。

10.3.3通常のフローでブロックレベルの非置換要素

次の制約は、他のプロパティの使用された値の間で保持する必要があります。

margin-left + border-left-width + padding-left + width + padding-right + border-right-width + margin-right =包含ブロックの幅

widthautoではなく、border-left-width + padding-left + width + padding-right + border-right-width(およびmargin-leftまたはmargin-rightのうち、auto以外のいずれか)がより大きい場合包含ブロックの幅、およびmargin-leftまたはmargin-rightauto値は、以下のルールではゼロとして扱われます。

上記のすべてにauto以外の計算値がある場合、値は「過剰制約」されていると言われ、使用される値の1つは計算値とは異なります。包含ブロックのdirectionプロパティの値がltrの場合、指定されたmargin-rightの値は無視され、等式が真になるように値が計算されます。 = directionの値がrtlの場合、代わりにmargin-leftが発生します

(強調を追加)

したがって、 CSS Visual Formatting Model によると、要素は「過剰に制約されている」可能性があり、その結果、右マージンが破棄されます。


考えられる回避策

マージンやパディングの代わりに、最後の要素で右borderを使用します。

li:last-child {
  border-right: 30px solid orange;
}
ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
  display: flex;
  height: 100px; /* adjusted for demo */
  overflow: auto;
  width: 600px;
  background: orange;
}
ul li {
  background: blue;
  color: #fff;
  padding: 90px;
  margin: 0 30px;
  white-space: nowrap;
  flex-basis: auto;
}
li:last-child {
  border-right: 30px solid orange;
}
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>
</ul>

別のソリューションでは、マージンやパディングの代わりにpseudo-elementsを使用します。

フレックスコンテナー上の疑似要素は、フレックスアイテムとしてレンダリングされます。コンテナの最初のアイテムは::beforeで、最後のアイテムは::afterです。

ul::after {
  content: "";
  flex: 0 0 30px;
}
ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
  display: flex;
  height: 100px; /* adjusted for demo */
  overflow: auto;
  width: 600px;
  background: orange;
}
ul li {
  margin: 0 30px;
  background: blue;
  color: #fff;
  padding: 90px;
  white-space: nowrap;
  flex-basis: auto;
}
ul::after {
  content: "";
  flex: 0 0 30px;
}

ul::before {
  content: "";
  flex: 0 0 30px;
}
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>
</ul>
34
Michael_B

あなたの問題自体はマージンではありません。これは、要素の表示可能なコンテンツのみの寸法を記入するスクロールバーです。

それを解決する1つのハックは、マージンを占める目に見える要素を作成することです

このソリューションは、最後の子の疑似を使用してこれを処理します

ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
  display: flex;
  height: 300px;
  overflow: auto;
  width: 600px;
  background: orange;
}
ul li {
  background: blue;
  color: #fff;
  padding: 90px;
  margin: 0 30px;
  white-space: nowrap;
  flex-basis: auto;
  position: relative;
}
li:last-child:after {
  content: "";
  width: 30px;
  height: 1px;
  position: absolute;
  left: 100%;
  top: 0px;
}
<div class"container">
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
  </ul>
</div>
5
vals

widthコンテナにはoverflowdivを設定でき、flexではなくulではなくdisplay: inline-flexを設定できます。フレックスボックスのサイズが内部のアイテムに基づいて計算され、すべてのパディングとマージンが問題なく適用されるようにします。

.container {
  width: 600px;
  overflow: auto;
}

.container ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: inline-flex;
  background: orange;
}

.container li {
  padding: 60px;
  margin: 0 30px;
  white-space: nowrap;
  background: blue;
  color: #fff;
}
<div class="container">
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
  </ul>
</div>
3
Stickers