11

In my flexbox based layout, I may have a <pre><code></code></pre> element (among other elements). As its content might be wider than the container, I made it overflow-x:auto.

It works perfectly on Chrome:

enter image description here

But it's broken on Firefox:

enter image description here

How can I fix that without hard-coded dimensions ?

div,pre {
  padding: 5px;
  color: white;
}
.m {
  background: #222;
  display: flex;
}
.l, .r {
  background: #143;
  flex: 0 0 100px;
}
.c {
  background: #971;
  flex: 1;
}
pre {
  white-space: pre;
  word-wrap: normal;
  overflow-x: auto;
}
 <div class=m>
    <div class=l>this must be 100px wide</div>
    <div class=c>this must take the remaining space</div>
    <div class=r>this must be 100px wide</div>
  </div>
  <div class=m>
    <div class=l>this must be 100px wide</div>
    <div class=c>
      <pre><code>The following line of code is long:
      This is the long line of code the previous line of code was referring to (no, it can't be 72 col, sorry for the inconvenience)</code></pre>
    Some other content in the c column.</div>
    <div class=r>this must be 100px wide</div>
  </div>
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • 1
    Not sure why Chrome and Firefox behave differently, but if it is possible to apply `overflow-x: auto; overflow-y: hidden;` to the middle column (having `.c` class) instead, the issue could be fixed. – Hashem Qolami Mar 06 '15 at 10:31
  • @HashemQolami This isn't exactly what I want (the middle column may contain other elements). But it might help making a workaround for firefox. – Denys Séguret Mar 06 '15 at 10:34
  • 1
    This is really strange, if you see here: http://jsfiddle.net/roj0a54k/1/ the `` element is a inline element. If you set it to be block and set a bizarr `max-width` like 10px it seems to work in Firefox. – Nico O Mar 06 '15 at 10:41

2 Answers2

16

You just need to set min-width:0 on your flex item, .c. See my answer on this similar question for more.

Backstory: The flexbox spec introduces a new sizing feature, min-width: auto, which forces flex items to be at least as large as their min-content width -- the minimum width that their contents need, to avoid overflow. Right now, Firefox is the only browser to have implemented this, which is why you only see it there.

If you want to disable this behavior, just give the flex item min-width:0.

(You could also set overflow:hidden on the flex item, as described in the other answer here, but that's overkill. That only benefits you by forcing min-width:auto to resolve to 0, via a special case in the min-width:auto definition. The downside is that overflow:hidden also forces the browser to do extra work to manage an invisible scrollable area for the flex item, and that's got a nonzero cost in terms of memory & performance, so better to avoid it unless you actually are using overflow:hidden on the flex item. And you aren't, so it's better to avoid it.)

div,pre {
  padding: 5px;
  color: white;
}
.m {
  background: #222;
  display: flex;
}
.l, .r {
  background: #143;
  flex: 0 0 100px;
}
.c {
  background: #971;
  flex: 1;
  min-width: 0;
}
pre {
  white-space: pre;
  word-wrap: normal;
  overflow-x: auto;
}
 <div class=m>
    <div class=l>this must be 100px wide</div>
    <div class=c>this must take the remaining space</div>
    <div class=r>this must be 100px wide</div>
  </div>
  <div class=m>
    <div class=l>this must be 100px wide</div>
    <div class=c>
      <pre><code>The following line of code is long:
      This is the long line of code the previous line of code was referring to (no, it can't be 72 col, sorry for the inconvenience)</code></pre>
    Some other content in the c column.</div>
    <div class=r>this must be 100px wide</div>
  </div>
Community
  • 1
  • 1
dholbert
  • 11,386
  • 3
  • 42
  • 31
  • 2
    BTW, somebody should make a good page explaining the real flex model, in the spirit of the css-tricks one but complete and correct enough... – Denys Séguret Mar 07 '15 at 07:51
8

All you need to do here, is set the parent element of your code-block <pre>, in this case <div class="c"> to overflow: hidden

.c {
  background: #971;
  flex: 1;
  overflow: hidden;
}

.c is a block element, that is taking up all the space it gets here without allowing an overflow with this rule set.

pre as the child is overflowing its parent as it takes up more space because of its content, so overflow: auto will be set to scroll here, resulting in the scroll area appearing on the inner pre - element.

Demonstration :

div,pre {
  padding: 5px;
  color: white;
}
.m {
  background: #222;
  display: flex;
}
.l, .r {
  background: #143;
  flex: 0 0 100px;
}
.c {
  background: #971;
  flex: 1;
  overflow: hidden;
}
pre {
  white-space: pre;
  word-wrap: normal;
  overflow-x: auto;
}
 <div class=m>
    <div class=l>this must be 100px wide</div>
    <div class=c>this must take the remaining space</div>
    <div class=r>this must be 100px wide</div>
  </div>
  <div class=m>
    <div class=l>this must be 100px wide</div>
    <div class=c>
      <pre><code>The following line of code is long:
      This is the long line of code the previous line of code was referring to (no, it can't be 72 col, sorry for the inconvenience)</code></pre>
    Some other content in the c column.</div>
    <div class=r>this must be 100px wide</div>
  </div>
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
GNi33
  • 4,459
  • 2
  • 31
  • 44
  • 2
    Note to other users facing the same problem : if your flex based layout is deeper, you might have to apply `overflow:hidden` to other parent elements. – Denys Séguret Mar 06 '15 at 11:35
  • 1
    `overflow:hidden` is overkill -- you really just want `min-width: 0`. The problem here is with the new default `min-width:auto`, which is a bit magical on flex items (and which Chrome hasn't implemented yet). `overflow:hidden` happens to work because it makes `min-width:auto` resolve to 0; but it has other side effects as well. All you want here is just `min-width:0`, not the other side effects. – dholbert Mar 06 '15 at 23:57
  • Please, this answer should not be downvoted. That's the best solution we could find until somebody with inside knowledge from Mozilla came in. – Denys Séguret Mar 07 '15 at 12:12
  • @dholbert very interesting, didn't know about this. I was already thinking that `overflow: hidden` was achieving the solution as "side effect" while doing more unnecessary stuff in this case. Thanks for clearing this up – GNi33 Mar 07 '15 at 16:38