Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pre/code element with horizontal scrollbar breaks the flex layout on Firefox

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>
like image 308
Denys Séguret Avatar asked Mar 06 '15 10:03

Denys Séguret


Video Answer


2 Answers

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>
like image 51
dholbert Avatar answered Oct 20 '22 00:10

dholbert


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>
like image 26
GNi33 Avatar answered Oct 20 '22 01:10

GNi33