5

I'm trying to compose a header with month names and all days in that month right below the name.

Days items have fixed width so I thought: why not use flexbox?

For some reasons .day elements are falling of their parent and parent does not grow.

Could you please give me a hint why flex-basis: auto doesn't make month-slot grow after days' slot overflow it?

As for implementation I've already found workaround with using float: left instead of using flexbox. But I cannot understand why it works this way.

.main {
  display: flex;
}

.month {
  flex: 0 0 auto;
}

.days {
  display: flex;
}

.day {
  flex: 0 0 2em;
}
<div class='main'>
  <div class='month'>
    <div class='name'>Jan</div>
    <div class='days'>
      <div class='day'>1</div>
      <div class='day'>2</div>
      <div class='day'>3</div>
      <div class='day'>4</div>
      <div class='day'>5</div>
      <div class='day'>6</div>
    </div>
  </div>
  <div class='month'>
    <div class='name'>Feb</div>
    <div class='days'>
      <div class='day'>1</div>
      <div class='day'>2</div>
      <div class='day'>3</div>
      <div class='day'>4</div>
      <div class='day'>5</div>
      <div class='day'>6</div>
      <div class='day'>7</div>
      <div class='day'>8</div>
      <div class='day'>9</div>
      <div class='day'>10</div>
    </div>
  </div>
  <div class='month'>
    <div class='name'>Mar</div>
    <div class='days'>
      <div class='day'>1</div>
      <div class='day'>2</div>
    </div>
  </div>
</div>

codepen: http://codepen.io/skyboyer/pen/MyzeLW

jsFiddle: https://jsfiddle.net/azizn/ytt7jb85/

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
skyboyer
  • 22,209
  • 7
  • 57
  • 64

1 Answers1

4

Use width: 2em instead of flex: 0 0 2em.

.main {
  display: flex;
}
.month {
  flex: 0 0 auto;
}
.days {
  display: flex;
}
.day {
  width: 2em;
}
<div class='main'>
  <div class='month'>
    <div class='name'>Jan</div>
    <div class='days'>
      <div class='day'>1</div>
      <div class='day'>2</div>
      <div class='day'>3</div>
      <div class='day'>4</div>
      <div class='day'>5</div>
      <div class='day'>6</div>
    </div>
  </div>
  <div class='month'>
    <div class='name'>Feb</div>
    <div class='days'>
      <div class='day'>1</div>
      <div class='day'>2</div>
      <div class='day'>3</div>
      <div class='day'>4</div>
      <div class='day'>5</div>
      <div class='day'>6</div>
      <div class='day'>7</div>
      <div class='day'>8</div>
      <div class='day'>9</div>
      <div class='day'>10</div>
    </div>
  </div>
  <div class='month'>
    <div class='name'>Mar</div>
    <div class='days'>
      <div class='day'>1</div>
      <div class='day'>2</div>
    </div>
  </div>
</div>

The problem with your code is that Firefox and Chrome size .month taking the width of the contents into account, but not flex-basis.

.main {
  display: flex;
}
.month {
  flex: 0 0 auto;
}
.days {
  display: flex;
  overflow: hidden;
}
.main.big .day {
  flex: 0 0 2em;
}
.main.big > .month:after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  border: 1px solid red;
}
<div class='main grow'>
  <div class='month'>
    <div class='name'>Jan</div>
    <div class='days'>
      <div class='day'>1</div>
      <div class='day'>2</div>
      <div class='day'>3</div>
      <div class='day'>4</div>
      <div class='day'>5</div>
      <div class='day'>6</div>
    </div>
  </div>
  <div class='month'>
    <div class='name'>Feb</div>
    <div class='days'>
      <div class='day'>1</div>
      <div class='day'>2</div>
      <div class='day'>3</div>
      <div class='day'>4</div>
      <div class='day'>5</div>
      <div class='day'>6</div>
      <div class='day'>7</div>
      <div class='day'>8</div>
      <div class='day'>9</div>
      <div class='day'>10</div>
    </div>
  </div>
  <div class='month'>
    <div class='name'>Mar</div>
    <div class='days'>
      <div class='day'>1</div>
      <div class='day'>2</div>
    </div>
  </div>
</div>
<hr />
<div class='main big'>
  <div class='month'>
    <div class='name'>Jan</div>
    <div class='days'>
      <div class='day'>1</div>
      <div class='day'>2</div>
      <div class='day'>3</div>
      <div class='day'>4</div>
      <div class='day'>5</div>
      <div class='day'>6</div>
    </div>
  </div>
  <div class='month'>
    <div class='name'>Feb</div>
    <div class='days'>
      <div class='day'>1</div>
      <div class='day'>2</div>
      <div class='day'>3</div>
      <div class='day'>4</div>
      <div class='day'>5</div>
      <div class='day'>6</div>
      <div class='day'>7</div>
      <div class='day'>8</div>
      <div class='day'>9</div>
      <div class='day'>10</div>
    </div>
  </div>
  <div class='month'>
    <div class='name'>Mar</div>
    <div class='days'>
      <div class='day'>1</div>
      <div class='day'>2</div>
    </div>
  </div>
</div>

This is a bug. According to Line Length Determination, when determining the flex base size of .month case E applies:

size the item into the available space using its used flex basis in place of its main size, treating a value of content as max-content.

The intricacies of calculating a max-content size were moved to CSS Sizing 4:

max-content inline size: The box’s “ideal” size in the inline axis. Usually the narrowest inline size it could take while fitting around its contents if none of the soft wrap opportunities within the box were taken. (See §4 Intrinsic Size Determination.)

In case of a non-replaced block,

The max-content inline size of a block container box is the inline-size of the box after layout, if all children are sized under a max-content constraint.

It explicitly says "after layout". It doesn't say something like "before flex layout". So flex-basis: 2em shouldn't be ignored, and should contribute to a bigger max-content size of the container.

Oriol
  • 274,082
  • 63
  • 437
  • 513
  • so `width: 2em` + `flex-basis: auto` works differently from `flex-basis: 2em` but why? – skyboyer May 01 '16 at 15:22
  • @Oriol yeah, I figured it out too but any idea why flex-basis doesn't work properly? Does `flex-basis` behave as width at all? – Aziz May 01 '16 at 15:23
  • 3
    I'm starting to think this is a bug. According to [Intrinsic Sizes of Non-Replaced Blocks](https://drafts.csswg.org/css-sizing-4/#block-intrinsic), the max-content contribution should be calculated after layout. But `flex-basis` is ignored and the width of the text is used instead, that seems "before layout" instead. – Oriol May 01 '16 at 15:44
  • 1
    @Aziz, there's really no difference (as far as I can tell) between using `flex-basis` and `width` in this case. The code should work as-is. In fact, it works on IE11. But it fails in Chrome and FF. – Michael Benjamin May 01 '16 at 15:47
  • If there is something in the spec describing this behavior @Oriol will find it :-) Here's what I found: http://stackoverflow.com/q/34352140/3597276 – Michael Benjamin May 01 '16 at 15:47
  • 2
    @Oriol, I don't think we even need to go that deep. The spec is pretty clear on `flex-basis` vis-a-vis `width` and `height`. In this particular situation, there should be no rendering difference. I agree with you that this may be a bug. – Michael Benjamin May 01 '16 at 15:49