Display: Flex loses right padding when overflowing?
Asked Answered
R

6

53

I have an issue with a CSS3 flexbox.

If I set the flexbox element to overflow and set a min-width value for the children, the right padding on the parent is lost? This is consistent on all supporting browsers.

Here is an example of the error. If you scroll to the right of the container you will see the last child is hard up against the right edge of the container instead of honoring the padding value.

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

Does anyone know why this is and how I would go about correcting it? I've messed around with padding and margin values in different combinations without success.

Reuter answered 12/11, 2014 at 13:42 Comment(3)
At least in Firefox, this is not a flexbox-specific behavior -- it happens with block layout as well, and is correct according to the CSS spec. See bugzilla.mozilla.org/show_bug.cgi?id=748518 for more.Virgil
Thanks for that I wasnt sure if it was something specific to flex.Reuter
this seems to have been fixed in current browser versions (right padding is visible in chrome 118). problem is confirmed to exist in older versions (tried chrome 80 in browserstack)Peace
P
4

Update 2023

This seems to have been fixed in recent browser versions, as right padding is clearly visible here:

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

The problem still exists though in cases where the overflow is applied to a wrapping element (note also how the gray background doesn't expand to fill the wrapper when scrolled to the right side):

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

But this can be fixed by adding width:fit-content to the outer element:

.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>
Peace answered 15/10, 2023 at 10:41 Comment(0)
V
45

You need to add another layer of wrapping, if you want to have both "overflow-x:auto" with scrollable padding at the end.

Something like this:

.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>
Virgil answered 12/11, 2014 at 17:28 Comment(5)
Thansk! Made a bit simpler example: jsfiddle.net/rckd/237dgLjjMaihem
Why does float: left work? According to documentation in MDN, it's not supposed to do anything when applied to display: flex elements. Would it be better to use display: inline-flex instead? It seems to work in my tests, but I'm not sure if it has any drawbacksFastigiate
float:left absolutely has an effect on flex containers (display:flex elements), in general. The spot where float has no effect is on flex items (children of display:flex elements). I see the MDN page that you mentioned -- that seems to be developer.mozilla.org/en-US/docs/Web/CSS/float and it's wrong. I'll fix it up -- thanks for the heads-up about that wrongness.Virgil
But, answering your question about inline-flex: it looks like display:inline-flex would work too (instead of float). I forget the details here, but based on my /**/ code-comment in the text snippet, I had only suggested float:left in order to trigger intrinsic sizing. And inline-flex also does intrinsic sizing, so that probably works well here too.Virgil
Your code snippet still has no padding on the "text10"?Rhiannonrhianon
W
19

Alternatively it's possible to create the margins with pseudo-elements:

.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>
Willodeanwilloughby answered 30/8, 2018 at 9:40 Comment(4)
This one does work, unless you use a align-items: center; because then it breaks again. Do you know any solution for that?Cienfuegos
After trying several methods from stack, this was the closest to working for my situation. I had to add border-top: 1px solid transparent; to the ::after to make the padding show up.Uncut
Just found this answer today! Very useful. If you use right margin to space your elements in a flex container, you need to make sure you remove it from the last child as you will end up with the pseudo content as well as the margin. Good fix.Amyl
man, briliant!!Flagler
P
4

Update 2023

This seems to have been fixed in recent browser versions, as right padding is clearly visible here:

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

The problem still exists though in cases where the overflow is applied to a wrapping element (note also how the gray background doesn't expand to fill the wrapper when scrolled to the right side):

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

But this can be fixed by adding width:fit-content to the outer element:

.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>
Peace answered 15/10, 2023 at 10:41 Comment(0)
C
1

Both solutions from Arthur Käpp and dholbert are working. However, if you choose to use any 'align-items' (accept for stretch) in the main flex box it will break again. It took me a while but eventually I cooked up a solution which works fine.

This solution is using the pseudo elements:

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

Be aware that in some cases the margin-left: 10px in the psuedo-element does not work. You can use a right: -10px which would also work.

Cienfuegos answered 11/6, 2019 at 15:21 Comment(0)
E
1

There is another way: You can have another DIV item-flex -> TEXT_11, then set MarginLeft = PaddingRight, you want

<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>
Elsie answered 12/4, 2020 at 10:49 Comment(0)
P
0

The best way I've found to handle this is using ::after (and ::before) pseudo-elements.

.parent::after {
  content: "";
  padding: 10px;
}

Apply this also to .parent::before for consistent spacing at the beginning and end of the scrolled container.

Plumule answered 3/11, 2022 at 19:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.