显示:Flex在溢出时失去右填充?

52

我遇到了一个CSS3 flexbox的问题。

如果我将flexbox元素设置为overflow并为其子元素设置min-width值,则父级元素的右侧填充会丢失?这在所有支持的浏览器上都一致。

以下是错误示例。如果您向容器的右侧滚动,您将看到最后一个子元素紧贴着容器的右边缘,而不是遵守填充值。

.outer {
    display: flex;
    flex-direction: row;
    width: 300px;
    height: 80px;
    border:1px #ccc solid;
    overflow-x: auto;
    padding: 5px;
}
.outer > div {
    flex: 1 1 auto;
    border: 1px #ccc solid;
    text-align: center;
    min-width: 50px;
    margin: 5px;
}
<div class="outer">
    <div>text1</div>
    <div>text2</div>
    <div>text3</div>
    <div>text4</div>
    <div>text5</div>
    <div>text6</div>
    <div>text7</div>
    <div>text8</div>
    <div>text9</div>
    <div>text10</div>
</div>

有人知道为什么会出现这种情况吗?我已经尝试了不同组合的paddingmargin值,但都没有成功。请问应该如何改正呢?

有什么方法可以解决这个问题吗?我已经试过不同的paddingmargin值,但都没有成功。


2
至少在Firefox中,这不是flexbox特定的行为--它也会在块布局中发生,并且根据CSS规范是正确的。有关更多信息,请参见https://bugzilla.mozilla.org/show_bug.cgi?id=748518。 - dholbert
谢谢,我不确定这是否是Flex特定的问题。 - Chris Spittles
这个问题在当前的浏览器版本中似乎已经修复了(在Chrome 118中可以看到右填充)。问题已经确认存在于旧版本中(在BrowserStack中尝试了Chrome 80)。 - undefined
6个回答

44

如果想同时拥有"overflow-x:auto"和可滚动的末尾填充,则需要添加另一层包装。

可以像这样实现:

.scroll {
    overflow-x: auto;
    width: 300px;
    border:1px #ccc solid;
}
.outer {
    display: flex;
    flex-direction: row;
    box-sizing: border-box;
    min-width: 100%;
    height: 80px;
    padding: 5px;
    float: left; /* To size to content, & not be clamped to available width. (Vendor-prefixed intrinsic sizing keywords for "width" should work here, too.) */
}
.outer > div {
    flex: 1 1 auto;
    border: 1px #ccc solid;
    text-align: center;
    min-width: 50px;
    margin: 5px;
}
<div class="scroll">
  <div class="outer">
    <div>text1</div>
    <div>text2</div>
    <div>text3</div>
    <div>text4</div>
    <div>text5</div>
    <div>text6</div>
    <div>text7</div>
    <div>text8</div>
    <div>text9</div>
    <div>text10</div>
  </div>
</div>


3
谢谢!这是一个更简单的例子:https://jsfiddle.net/rckd/237dgLjj/ - rcd
为什么float:left能够工作?根据MDN文档,当应用于display:flex元素时,它不应该做任何事情。使用display:inline-flex是否更好?在我的测试中似乎可以工作,但我不确定是否存在任何缺点。 - xgrtl
float:left通常对于flex容器display:flex元素)有影响。没有效果的地方是在flex itemsdisplay:flex元素的子元素)上。我看到了您提到的MDN页面 -- 那似乎是 https://developer.mozilla.org/en-US/docs/Web/CSS/float,但是它是错误的。我会进行修复 -- 感谢您指出这个错误。 - dholbert
2
但是,回答你关于 inline-flex 的问题:看起来 display:inline-flex 也可以工作(而不是 float)。我忘记了细节,但根据我在文本片段中的 /**/ 代码注释,我只建议使用 float:left 来触发内在大小调整。而 inline-flex 也可以进行内在大小调整,所以在这里也可能很好地工作。 - dholbert
你的代码片段上的"text10"仍然没有填充吗? - James

19

或者,也可以使用伪元素创建边距:

.outer::before { content: ''; min-width: 5px; }
.outer::after { content: ''; min-width: 5px; }

.outer {
    display: flex;
    flex-direction: row;
    width: 300px;
    height: 80px;
    border:1px #ccc solid;
    overflow-x: auto;
    padding: 5px;
}
.outer::after { content: ''; min-width: 5px; }
.outer > div {
    flex: 1 1 auto;
    border: 1px #ccc solid;
    text-align: center;
    min-width: 50px;
    margin: 5px;
}
<div class="outer">
    <div>text1</div>
    <div>text2</div>
    <div>text3</div>
    <div>text4</div>
    <div>text5</div>
    <div>text6</div>
    <div>text7</div>
    <div>text8</div>
    <div>text9</div>
    <div>text10</div>
</div>


这个代码本来是可以正常工作的,但如果你使用了 align-items: center; 属性,它就会再次出现问题。你知道有什么解决办法吗? - BonifatiusK
1
在尝试了堆栈中的几种方法后,这是最接近适用于我的情况的方法。我不得不添加 border-top: 1px solid transparent;::after 中以使填充显示出来。 - OXiGEN
今天刚发现这个答案!非常有用。如果您使用右边距来对 flex 容器中的元素进行间距处理,则需要确保从最后一个子元素中删除它,否则您将会得到伪内容以及边距。好的解决方法。 - John E
男人,太棒了! - yzfdjzwl

1

2023年更新

最近的浏览器版本似乎已经修复了这个问题,因为右填充在这里清晰可见:

.outer{width:500px; display:flex; padding:20px; overflow:auto; background:#ccc;}
.inner{width:600px; height:50px; flex-shrink:0; background:darkblue;}
<div class="outer">
  <div class="inner"></div>
</div>

问题仍然存在,尤其是在应用于包裹元素的溢出情况下(请注意,当向右滚动时,灰色背景不会扩展到填充包装器):

.wrapper{width:500px; overflow:auto; border:1px solid red;}
.outer{display:flex; padding:20px; background:#ccc;}
.inner{width:600px; height:50px; flex-shrink:0; background:darkblue;}
<div class="wrapper">
  <div class="outer">
    <div class="inner"></div>
  </div>
</div>

但是这可以通过在outer元素中添加width:fit-content来解决:

.wrapper{width:500px; overflow:auto; border:1px solid red;}
.outer{width:fit-content; display:flex; padding:20px; background:#ccc;}
.inner{width:600px; height:50px; flex-shrink:0; background:darkblue;}
<div class="wrapper">
  <div class="outer">
    <div class="inner"></div>
  </div>
</div>


1

Arthur Käpp和dholbert的两种解决方案都有效。然而,如果您选择在主要的flex box中使用任何'align-items'(除了stretch),它会再次中断。我花了一些时间,最终想出了一个可行的解决方案。

这个解决方案使用伪元素:

.outer {
    display: flex;
    flex-direction: row;
    width: 300px;
    height: 80px;
    border:1px #ccc solid;
    overflow-x: auto;
    padding: 5px;
    align-items: center;
    position: relative;
}
.outer > div {
    flex: 1 1 auto;
    border: 1px #ccc solid;
    text-align: center;
    min-width: 50px;
    margin: 5px;
}

.outer > div:last-child::after {
    content: '';
    position: absolute;
    height: 100%;
    width: 10px;
    display: inline-block;
    margin-left: 10px;
}
<div class="outer">
    <div>text1</div>
    <div>text2</div>
    <div>text3</div>
    <div>text4</div>
    <div>text5</div>
    <div>text6</div>
    <div>text7</div>
    <div>text8</div>
    <div>text9</div>
    <div>text10</div>
</div>

请注意,在某些情况下,伪元素中的 margin-left: 10px 可能不起作用。您可以使用 right: -10px,这也可以起到同样的效果。

1
有另一种方法: 你可以再添加一个DIV元素,命名为item-flex -> TEXT_11,然后设置MarginLeft等于PaddingRight,就可以实现你想要的效果。
<div class="outer">
    <div>text1</div>
    <div>text2</div>
    <div>text3</div>
    <div>text4</div>
    <div>text5</div>
    <div>text6</div>
    <div>text7</div>
    <div>text8</div>
    <div>text9</div>
    <div>text10</div>

    <div style="margin-left: 5px" class="TEXT_11">&nbsp;</div>

</div>

0
我发现处理这个问题最好的方式是使用::after(和::before)伪元素。
.parent::after {
  content: "";
  padding: 10px;
}

同样也要应用到.parent::before,以保持滚动容器开头和结尾的一致间距。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接