11

I need to display several boxes next to each other. Each box has a variable number of child items. The parent should expand according to the space that the child items are taking up. It is important that the items have fixed width. I'm using flexbox for layout. It should look like this:

enter image description here

I wrote a Plunkr to illustrate.

The problem: Chrome does not expand the parent when the children take up more space. The child items are displayed beyond the parents' boundaries and appear in a neighbouring parent, resulting in this mess:

enter image description here

Ironically, if you open the Plunkr in IE 11 or Edge, it works fine.

What am I doing wrong?

Here's a code snippet:

body {
  display: flex;
  overflow: scroll;
}

.parent {
  border: 1px solid grey;
  padding: 0 20px;
  display: flex;
  flex-direction: column;
}

.items {
  display: flex;
}

.items span {
  flex-basis: 25px;
  flex-shrink: 0;
}
<div class="parent">
  <h4>Parent 1</h4>
  <div class="items">
    <span>i1</span>
    <span>i2</span>
    <span>i3</span>
    <span>i4</span>
    <span>i5</span>
  </div>
</div>
<div class="parent">
  <h4>Parent 2</h4>
  <div class="items">
    <span>i1</span>
    <span>i2</span>
    <span>i3</span>
    <span>i4</span>
    <span>i5</span>
  </div>
</div>
<div class="parent">
  <h4>Parent 3</h4>
  <div class="items">
    <span>i1</span>
    <span>i2</span>
    <span>i3</span>
    <span>i4</span>
    <span>i5</span>
  </div>
</div>
<div class="parent">
  <h4>Parent 4</h4>
  <div class="items">
    <span>i1</span>
    <span>i2</span>
    <span>i3</span>
    <span>i4</span>
    <span>i5</span>
  </div>
</div>
<div class="parent">
  <h4>Parent 5</h4>
  <div class="items">
    <span>i1</span>
    <span>i2</span>
    <span>i3</span>
    <span>i4</span>
    <span>i5</span>
  </div>
</div>
<div class="parent">
  <h4>Parent 6</h4>
  <div class="items">
    <span>i1</span>
    <span>i2</span>
    <span>i3</span>
    <span>i4</span>
    <span>i5</span>
  </div>
</div>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
fikkatra
  • 5,605
  • 4
  • 40
  • 66

3 Answers3

12

This appears to be a bug in Chrome.

In this section of code:

.items span {
  flex-basis: 25px;
  flex-shrink: 0;
}

... Chrome is not respecting the fixed 25px width. Or, at least, the container is not recognizing the space. It looks like the container is being sized before all item calculations are factored in.

The simple workaround is to use width instead of flex-basis.

.items span {
    flex-shrink: 0;
    width: 25px;
 }

revised demo


UPDATE

Bug Report

Flex-basis is being ignored when sizing nested flex containers.

"Yeah this is kind of a sucky consequence of a bug we have, perhaps combined with an unfortunate spec consequence..."

"When the outer flexbox finds the desired size of the inner flexbox, it asks for its max-content size (see LayoutFlexibleBox::computeInnerFlexBaseSizeForChild). But here's where the bug comes in, the max-content size does not take flex-basis into account, only width properties/actual content. That's why adding an explicit width fixes the bug."

Community
  • 1
  • 1
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • 2
    Then Firefox suffer from the same bug :) – Asons Aug 03 '17 at 12:04
  • 1
    Yes, this happens in chrome, firebox and safari... Beware: I believe the bug might not always happen and two identical elements with identical styles might end-up looking different. For instance, modifying the styles on chrome dev tools I ended up with a good looking element but when copying its style and content to the actual source the bug spoiled it. Even downloading the correct-looking source and opening it in a new tab would look incorrect. – raquelhortab Nov 10 '21 at 11:30
2

Try adding inline-flex instead of flex, also commented out some unwanted flex stylings please refer here,

/* Styles go here */
body {
  /* display: flex; */
  overflow: scroll;
}

.parent {
  border: 1px solid grey;
  padding: 0 20px;
  display: inline-flex;
  flex-direction: column;
}

.items {
  /* display: flex; */
}

.items span {
  flex-basis: 25px;
  flex-shrink: 0;
}
<div class="parent">
  <h4>Parent 1</h4>
  <div class="items">
    <span>i1</span>
    <span>i2</span>
    <span>i3</span>
    <span>i4</span>
    <span>i5</span>
  </div>
</div>
<div class="parent">
  <h4>Parent 2</h4>
  <div class="items">
    <span>i1</span>
    <span>i2</span>
    <span>i3</span>
    <span>i4</span>
    <span>i5</span>
  </div>
</div>
<div class="parent">
  <h4>Parent 3</h4>
  <div class="items">
    <span>i1</span>
    <span>i2</span>
    <span>i3</span>
    <span>i4</span>
    <span>i5</span>
  </div>
</div>
<div class="parent">
  <h4>Parent 4</h4>
  <div class="items">
    <span>i1</span>
    <span>i2</span>
    <span>i3</span>
    <span>i4</span>
    <span>i5</span>
  </div>
</div>
<div class="parent">
  <h4>Parent 5</h4>
  <div class="items">
    <span>i1</span>
    <span>i2</span>
    <span>i3</span>
    <span>i4</span>
    <span>i5</span>
  </div>
</div>
Vadim Ovchinnikov
  • 13,327
  • 5
  • 62
  • 90
Saravanan I
  • 1,229
  • 6
  • 9
-1

Please check this out

Use box-sizing : border-box; for parent element and using width to maintain the width of each element

https://plnkr.co/edit/3p8PwmLtHYozEFveRvTX

/* Styles go here */

body {
  display: flex;
  overflow: scroll;
}

.parent {
  border: 1px solid grey;
  padding: 0 20px;
  display: flex;
  flex-direction: column;
  box-sizing : border-box;
}

.items {
  display: flex;
}

.items span {
  width: 25px;
}

HTML:

<!DOCTYPE html>
<html>

<head>
  <link rel="stylesheet" href="style.css">
  <script src="script.js"></script>
</head>

<body>
  <div class="parent">
    <h4>Parent 1</h4>
    <div class="items">
      <span>i1</span>
      <span>i2</span>
      <span>i3</span>
      <span>i4</span>
      <span>i5</span>
      <span>i1</span>
      <span>i2</span>
      <span>i3</span>
      <span>i4</span>
      <span>i5</span>
    </div>
  </div>
  <div class="parent">
    <h4>Parent 2</h4>
    <div class="items">
      <span>i1</span>
      <span>i2</span>
      <span>i3</span>
      <span>i4</span>
      <span>i5</span>
    </div>
  </div>
  <div class="parent">
    <h4>Parent 3</h4>
    <div class="items">
      <span>i1</span>
      <span>i2</span>
      <span>i3</span>
      <span>i4</span>
      <span>i5</span>
    </div>
  </div>
  <div class="parent">
    <h4>Parent 4</h4>
    <div class="items">
      <span>i1</span>
      <span>i2</span>
      <span>i3</span>
      <span>i4</span>
      <span>i5</span>
    </div>
  </div>
  <div class="parent">
    <h4>Parent 5</h4>
    <div class="items">
      <span>i1</span>
      <span>i2</span>
      <span>i3</span>
      <span>i4</span>
      <span>i5</span>
    </div>
  </div>
  <div class="parent">
    <h4>Parent 6</h4>
    <div class="items">
      <span>i1</span>
      <span>i2</span>
      <span>i3</span>
      <span>i4</span>
      <span>i5</span>
    </div>
  </div>
</body>

</html>
Younis Ar M
  • 913
  • 6
  • 15
  • Yes! That works! Could you please update your answer with what changed (i.e. apply `box-sizing: border box;` to flex parent and remove `flex-shrink: 0;` from child)? It's easier for other to see the fix this way, without comparing every line of code. – fikkatra Aug 03 '17 at 11:37
  • On closer look, it breaks the fixed width of 25px for each item... Any clue? – fikkatra Aug 03 '17 at 11:42
  • .items span { width : 25px; } using width:25px maintains the width of each item. I will update the answer with what solved the issue – Younis Ar M Aug 03 '17 at 11:54
  • 2
    `box-sizing` has nothing to do with this – Asons Aug 03 '17 at 12:03