Letzter Rand / Padding kollabiert in Flexbox / Grid-Layout

Lesezeit: 6 Minuten

Letzter Rand Padding kollabiert in Flexbox Grid Layout
Kevin Wilson

Ich habe eine Liste von Elementen, die ich mit Flexbox in einem scrollbaren horizontalen Layout anordnen möchte.

Jedes Element im Container hat links und rechts einen Rand, aber der rechte Rand des letzten Elements wird reduziert.

Gibt es eine Möglichkeit, dies zu verhindern, oder einen guten Workaround?

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>

Letzter Rand Padding kollabiert in Flexbox Grid Layout
Michael Benjamin

Mögliches Problem Nr. 1

Der letzte Rand wird nicht reduziert. Es wird ignoriert.

Die overflow Eigentum gilt nur für Inhalt. Es gilt nicht für Polsterung oder Ränder.

So steht es in der Spezifikation:

11.1.1 Überlauf: der overflow
Eigentum

Diese Eigenschaft gibt an, ob der Inhalt eines Blockcontainerelements abgeschnitten wird, wenn er die Box des Elements überläuft.

Werfen wir nun einen Blick auf die CSS-Box-Modell:

Geben Sie hier die Bildbeschreibung ein

Quelle: W3C

Die overflow -Eigenschaft ist auf den Bereich der Inhaltsbox beschränkt. Wenn der Inhalt seinen Container überläuft, dann overflow gilt. Aber overflow geht nicht in die Polster- oder Randbereiche (es sei denn, es folgt natürlich mehr Inhalt).


Mögliches Problem Nr. 2

Das Problem mit potenziellem Problem Nr. 1 besteht darin, dass es außerhalb eines Flex- oder Grid-Formatierungskontexts auseinanderzufallen scheint. Beispielsweise scheint der letzte Rand in einem Standard-Blocklayout nicht zusammenzufallen. Also vielleicht overflow darf Ränder/Auffüllungen abdecken, unabhängig davon, was in der Spezifikation steht.

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>

Daher hängt das Problem möglicherweise stattdessen mit Elementen zusammen, die “überbeschränkt” sind.

10.3.3 Nicht ersetzte Elemente auf Blockebene im normalen Fluss

Die folgenden Einschränkungen müssen für die verwendeten Werte der anderen Eigenschaften gelten:

margin-left + border-left-width + padding-left + width +
padding-right + border-right-width + margin-right = Breite des umgebenden Blocks

Wenn width ist nicht auto und border-left-width + padding-left +
width + padding-right + border-right-width (plus evtl
margin-left oder margin-right das sind nicht auto) größer als die Breite des umgebenden Blocks ist, dann beliebig auto Werte für
margin-left oder margin-right werden für die folgenden Regeln als Null behandelt.

Wenn alle oben genannten Werte einen anderen berechneten Wert haben als auto, werden die Werte als “überbeschränkt” bezeichnet und einer der verwendeten Werte muss sich von seinem berechneten Wert unterscheiden. Wenn die direction
Eigenschaft des enthaltenden Blocks hat den Wert ltrder angegebene Wert von margin-right wird ignoriert und der Wert wird so berechnet, dass die Gleichheit wahr wird.
Wenn der Wert von direction ist rtldas passiert margin-left stattdessen

(Betonung hinzugefügt)

Also laut Visuelles CSS-FormatierungsmodellElemente können “überbeschränkt” sein und als Ergebnis wird ein rechter Rand weggeworfen.


Mögliche Problemumgehungen

Verwenden Sie anstelle von Rand oder Polsterung ein Recht Rand zum letzten Element:

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>

Eine andere Lösung verwendet a Pseudo-Elemente anstelle von Rändern oder Polsterung.

Pseudo-Elemente auf einem Flex-Container werden als Flex-Elemente gerendert. Das erste Element im Container ist ::before und letztes Element ist ::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>

  • Notiz: Wenn Sie definitiv verwenden width auf jedem Element und fügen Sie die hinzu border-right zum letzten Element, wirkt sich dies auf die sichtbare Breite dieses Elements aus, da der Rahmen im Falle von Teil des Elements ist border-box ist von der Boxgröße. Ändere das Box-Größe in Verzug bzw content-box.

    – Akansch

    30. Juli 2019 um 6:50 Uhr


  • border-left: 10vw solid transparent; hat alle meine Probleme gelöst, danke!

    – Alexandre Daubricourt

    14. Oktober 2019 um 13:10 Uhr

Ihr Problem ist nicht die Marge an sich. Es ist die Bildlaufleiste, die nur den sichtbaren Inhalt des Elements dimensioniert.

Ein Hack, um dies zu lösen, wäre, ein sichtbares Element zu erstellen, das den Rand einnimmt

Diese Lösung handhabt dies mit einem Pseudo für das letzte untergeordnete Element

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>

Sie können einstellen width und overflow auf der div Behälter und Set display: inline-flex eher, als flex auf der ulsodass die Größe der Flexbox basierend auf den darin enthaltenen Elementen berechnet wird und alle Polsterungen und Ränder ohne Probleme angewendet werden.

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

Sehen Sie sich die Lösung an. ich entferne white-space, flex-basis und marginum Ihnen eine reine Flexbox-Lösung anzubieten.

Es leitet weiter flex-flow: row(horizontal), justify-content: space-around (dein Rand) und nicht mehr!! Die width geändert wird 1200px da die Polsterung von 90px die Gesamtbreite der Boxen auf mehr als Ihre 600px (in Ihrem Snippet definiert) festlegt.

ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-flow: row ;
  justify-content: space-around;
  height: 300px;
  overflow: auto;
  width: 1200px;
  background: orange;
}
ul li {
  background: blue;
  color: #fff;
  padding: 90px;
}
<div class"container">
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
  </ul>
</div>
914850cookie-checkLetzter Rand / Padding kollabiert in Flexbox / Grid-Layout

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy