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

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 ltr
der angegebene Wert von margin-right
wird ignoriert und der Wert wird so berechnet, dass die Gleichheit wahr wird. Wenn der Wert von direction
ist rtl
das 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>
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 ul
sodass 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 margin
um 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>