Pre Code Blocks Stretch the Content Beyond Screen Width in a Centered Flex Container

Pre code blocks stretch the content beyond screen width in a centered flex container

In addition to Michael_B's answer, if you need the flex column direction for i.e. multiple .Content elements, you can also simply set width: 100% on the .Content.

To adjust the width to your padding/border you can either use box-sizing: border-box;, which I did, or CSS Calc (width: calc(100% - 22px);)

Also, for the reason Michael gave, I removed the min-width: 0 as it has no effect

Updated codepen

Stack snippet

.Page {

border: 1px solid blue;

}

.Container {

display: flex;

flex-direction: column;

align-items: center;

}

.Content {

border: 1px solid red;

padding: 10px;

max-width: 700px;

width: 100%;

box-sizing: border-box;

}

pre {

overflow: auto;

background: #f2f2f2;

border: 1px solid #ccc;

border-radius: 4px;

padding: 20px;

}
<div class='Page'>

<div class='Container'>

<div class='Content'>

<h1>Hello</h1>

<p>Cras ac mauris purus. Phasellus at ligula condimentum, pretium nisi eget, aliquet enim. Sed at massa velit. Cras ac mi dolor. Nullam id felis sit amet neque tempus sodales. In ultricies et turpis in faucibus. Morbi fringilla metus pellentesque, varius enim a, dapibus ex. Sed aliquet urna nisi, eu fermentum diam pretium quis. Curabitur vel cursus turpis. Sed a varius leo, in viverra arcu. Donec porttitor, dolor vel laoreet iaculis, magna arcu tempus ex, at porttitor tellus nunc ultricies felis. Quisque congue sapien in quam tempor, non dapibus felis dignissim. Pellentesque ex eros, dignissim eget tortor non, aliquet ullamcorper nisi. Sed interdum non eros quis fringilla. Morbi condimentum tellus at blandit dignissim. Aenean metus elit, interdum et suscipit quis, ullamcorper sit amet risus.</p>

<pre>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse sapien magna, lacinia sit amet quam sed, dignissim tincidunt neque. Duis sed sapien hendrerit, consectetur neque quis, tempor nisl. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Praesent fringilla enim odio, sit amet venenatis ex commodo in. Pellentesque in enim in libero vulputate fermentum. Suspendisse elementum felis neque, in rhoncus diam hendrerit eget. Cras tempor porta bibendum. Fusce eget tellus a enim euismod lobortis in vitae nibh. Duis ornare turpis non ex consectetur, sit amet malesuada elit feugiat.</pre>

</div>

</div>

</div>

Horizontally scrolling a pre tag that is an auto flex-item (or in one)

You still suffer from the minimum size issue of flex items.

In a nested Flexbox structure, it can also affect flex item's being a flex container (or an ancestor being a flex item), and in this case your content is one, and also needs to have its min-width set to 0.

As a side note, in this case the min-width: 0 set on pre is not generally necessary when using overflow with a value other than visible, and could be removed (which I did in the Codepen).

Updated codepen

Stack snippet

* {

box-sizing: border-box;

}

body {

padding: 0;

margin: 0;

}

.outer {

display: flex;

padding: 20px;

background-color: #aaa;

width: 100vw;

height: 100vh;

overflow: hidden;

}

.nav {

flex: 0 0 200px;

background-color: blue;

color: white;

padding: 20px;

}

.content {

flex: 1;

min-width: 0; /* added */

margin-left: 20px;

background-color: green;

display: flex;

flex-direction: column;

}

.header {

flex: 0 auto;

background-color: purple;

padding: 20px;

margin-bottom: 20px;

}

.header h1 {

margin: 0;

}

.pre {

flex: 1;

background-color: red;

margin: 0;

overflow: auto;

min-width: 0;

}
<div class='outer'>

<div class='nav'>

sidebar

</div>

<div class='content'>

<div class='header'>

<h1>Horizontal problems</h1>

</div>

<pre class='pre'>

<span>this is a really, really, long piece of text

</span>

</span>

</pre>

</div>

</div>

Flexbox container with white-space pre not working

The problem is that your elements are exceeding the width of the container. You have to make sure that the width of the sibling elements don't exceed 100%. Two of your three elements have a fixed width, so all you need to do is apply a calculated width of width: calc(100% - 120px) to .logviewer-container. 110px comes from the expanded menu, and the other 10px comes from the collapser.

Also be aware that you're missing your closing </head> tag, and have used a less-than sign (<) for your collapser. You'll want to use the HTML entity < instead. These can both be spotted by validating your markup through the W3C Markup Validation Service.

I've added the width calculation and fixed this in the following example:

.html,

.body {

width: 100%;

height: 100%;

position: fixed;

}

.main-container {

display: flex;

max-width: 100%;

flex-direction: row;

}

.menu {

display: flex;

flex: 0 0 auto;

overflow: hidden;

width: 0;

-webkit-transition: width 0.5s ease-in-out;

-moz-transition: width 0.5s ease-in-out;

-o-transition: width 0.5s ease-in-out;

transition: width 0.5s ease-in-out;

}

.menu.expanded {

width: 110px;

}

.collapser {

display: flex;

align-items: center;

flex: 0 0 auto;

width: 10px;

background-color: gray;

}

.collapser p {

cursor: pointer;

color: white;

margin: 0;

}

.logviewer-container {

display: flex;

flex: 1;

flex-direction: column;

border: 1px solid darkgray;

width: calc(100% - 120px);

}

.toolbar {

display: flex;

flex: 0 0 25px;

background-color: lightblue;

flex-direction: row;

}

.log-display {

display: flex;

flex: 1 1 auto;

overflow: auto;

flex-direction: column;

}

.line {

flex: 0 0 auto;

height: 16px;

font-size: 11px;

font-family: Monaco, monospace;

}

.row-number {

padding-right: 6px;

margin-right: 6px;

width: 50px;

color: #859900;

border-right: 1px dotted #859900;

text-align: end;

}

.row-content {

white-space: pre;

}
<!DOCTYPE html>

<html>

<head>

<title>Foo</title>

</head>

<body>

<div class="main-container">

<div class="menu expanded">

<ul>

<li>Item 1</li>

<li>Item 2</li>

<li>Item 3</li>

<li>Item 4</li>

<li>Item 5</li>

<li>Item 6</li>

</ul>

</div>

<div class="collapser">

<p>

<

</p>

</div>

<div class="logviewer-container">

<div class="toolbar"></div>

<div class="log-display">

<div class="line">

<div class="row-number">1</div>

<div class="row-content">22:21:18 | Lorem Ipsum | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo

consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum</div>

</div>

<div class="line">

<div class="row-number">2</div>

<div class="row-content">22:21:18 | Lorem Ipsum | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo

consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum</div>

</div>

<div class="line">

<div class="row-number">3</div>

<div class="row-content">22:21:18 | Lorem Ipsum | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo

consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum</div>

</div>

<div class="line">

<div class="row-number">4</div>

<div class="row-content">22:21:18 | Lorem Ipsum | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo

consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum</div>

</div>

<div class="line">

<div class="row-number">5</div>

<div class="row-content">22:21:18 | Lorem Ipsum | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo

consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum</div>

</div>

</div>

</div>

</div>

</body>

</html>

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

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>

Make flex items stretch full height and vertically center their content

Unfortunately, it is impossible to achieve the desired effect while using the exact markup posted in the question.

The solution involves:

  • Setting display: flex; on <li>.
  • Wrapping the <li> contents into another element.

    • This is required because <li> is now a flex container, so we need another element to prevent the actual contents from becoming flex items.
    • In this solution, I introduced a <div> element, but it could have been other element.
  • Now that <li> is a flex container and it contains only a single child, we can use align-items and/or justify-content to align this new and only child.

The DOM tree looks like this:

<ul> flex-parent, direction=row
├ <li> flex-item && flex-parent && background && JavaScript clickable area
│ └ <div> flex-item as a single transparent element
│ ├ Actual contents
│ └ Actual contents
├ …

Note: The solution in this answer uses 2 nested flex boxes. The solution by Michael_B uses 3 nested flex boxes, because it has the added challenge of expanding the <a> element to fill the entire <li>. Which one is preferred depends on each case. If I could, I would accept both answers.

/* New code: this is the solution. */

ul > li {

display: flex;

flex-direction: column;

justify-content: center;

align-items: center;

}

/* Old code below. */

ul {

display: flex;

flex-direction: row;

align-items: stretch;

}

ul > li {

flex-grow: 1;

flex-shrink: 0;

flex-basis: 5em;

text-align: center;

}

ul > li:nth-child(2) {

background: #CFC;

}

/* Visual styles, just ignore. */

html, body { font-family: sans-serif; font-size: 25px; }

ul, li { list-style: none; margin: 0; padding: 0; }

ul { background: #CCF; width: 25em; }

button:focus + ul {

font-size: 14px;

width: auto;

}
<button>Click here to set <code>width: auto</code> and reduce the font size.</button>

<!-- New code: there is a single <div> between each <li> and their contents. -->

<ul>

<li><div>Sample</div></li>

<li><div><span>span</span></div></li>

<li><div><span>multiple</span> <span>span</span></div></li>

<li><div>text <span>span</span></div></li>

<li><div>multi<br>line</div></li>

</ul>

Why don't flex items shrink past content size?

The Automatic Minimum Size of Flex Items

You're encountering a flexbox default setting.

A flex item cannot be smaller than the size of its content along the main axis.

The defaults are...

  • min-width: auto
  • min-height: auto

...for flex items in row-direction and column-direction, respectively.

You can override these defaults by setting flex items to:

  • min-width: 0
  • min-height: 0
  • overflow: hidden (or any other value, except visible)

Flexbox Specification

4.5. Automatic Minimum Size of Flex
Items

To provide a more reasonable default minimum size for flex items, this
specification introduces a new auto value as the initial value of
the min-width and min-height properties defined in CSS 2.1.

With regard to the auto value...

On a flex item whose overflow is visible in the main axis, when specified on the flex item’s main-axis min-size property, specifies an automatic minimum size. It otherwise computes to 0.

In other words:

  • The min-width: auto and min-height: auto defaults apply only when overflow is visible.
  • If the overflow value is not visible, the value of the min-size property is 0.
  • Hence, overflow: hidden can be a substitute for min-width: 0 and min-height: 0.

and...

  • The minimum sizing algorithm applies only on the main axis.
  • For example, a flex item in a row-direction container does not get min-height: auto by default.
  • For a more detailed explanation see this post:

    • min-width rendering differently in flex-direction: row and flex-direction: column

You've applied min-width: 0 and the item still doesn't shrink?

Nested Flex Containers

If you're dealing with flex items on multiple levels of the HTML structure, it may be necessary to override the default min-width: auto / min-height: auto on items at higher levels.

Basically, a higher level flex item with min-width: auto can prevent shrinking on items nested below with min-width: 0.

Examples:

  • Flex item is not shrinking smaller than its content
  • Fitting child into parent
  • white-space css property is creating issues with flex

Browser Rendering Notes

  • Chrome vs. Firefox / Edge

    Since at least 2017, it appears that Chrome is either (1) reverting back to the min-width: 0 / min-height: 0 defaults, or (2) automatically applying the 0 defaults in certain situations based on a mystery algorithm. (This could be what they call an intervention.) As a result, many people are seeing their layout (especially desired scrollbars) work as expected in Chrome, but not in Firefox / Edge. This issue is covered in more detail here: flex-shrink discrepancy between Firefox and Chrome

  • IE11

    As noted in the spec, the auto value for the min-width and min-height properties is "new". This means that some browsers may still render a 0 value by default, because they implemented flex layout before the value was updated and because 0 is the initial value for min-width and min-height in CSS 2.1. One such browser is IE11. Other browsers have updated to the newer auto value as defined in the flexbox spec.


Revised Demo

.container {

display: flex;

}

.col {

min-height: 200px;

padding: 30px;

word-break: break-word

}

.col1 {

flex: 1;

background: orange;

font-size: 80px;

min-width: 0; /* NEW */

}

.col2 {

flex: 3;

background: yellow

}

.col3 {

flex: 4;

background: skyblue

}

.col4 {

flex: 4;

background: red

}
<div class="container">

<div class="col col1">Lorem ipsum dolor</div>

<div class="col col2">Lorem ipsum dolor</div>

<div class="col col3">Lorem ipsum dolor</div>

<div class="col col4">Lorem ipsum dolor</div>

</div>

Text inside a div positioned with flex linebreaks before and after certain tags

Why it break line is because of the display: flex; flex-direction: column on the pagetitleleft/center/right elements, which make the span a flex column item and take 100% width.

By dropping the display: flex on the pagetitleleft/center/right elements and set align-items: center to their parent, their text will center vertically

.pagetitlewrapper {

width: 99%;

background-color: #c1dbff;

border-radius: 25px 25px 0px 0px;

padding: 10px;

display: flex;

align-items: center;

}

.pagetitleleft,.pagetitlecenter,.pagetitleright {

width: 33%;

}

.pagetitleleft {

text-align: left;

font-size: 9;

}

.pagetitlecenter {

text-align: center;

}

.pagetitleright {

text-align: right;

font-size: 9;

resize: vertical;

}
<div class='pagetitlewrapper'>

<div class='pagetitleleft'>Welkom, FNAME LNAME</div>

<div class='pagetitlecenter'><h1>Nexus Consult DMS</h1></div>

<div class='pagetitleright'>

Licensed to <span>DON'T WRAP</span> - License valid until xx/xx/xxxx.

</div>

</div>

white-space: nowrap breaks flexbox layout

This is caused by the default flex-box behaviour, which prevents flex-boxes of becoming smaller than it's contents.

The solution to this issue is setting min-width: 0 (or min-height: 0 for columns) to all parent flex-boxes.
In this specific case (and in the fiddle):

#shell{
flex: 1 1 auto;
display:flex;
flex-flow:row nowrap;
position:relative;
width:100%;
min-height:100%;
min-width: 0; /* this one right here does it!*/
}

$('#nav-toggle').on('click',function(){

$(this).parent().toggleClass('collapsed');

});

$('#help-toggle').on('click',function(){

$('#help-pane').toggleClass('visible');

});

$('#list-toggle').on('click',function(){

$('#list').toggleClass('nowrap');

});
body,html{width:100%;height:100%;overflow:hidden;}

#body{

display:flex;

flex-flow:row nowrap;

position:absolute;

top:0;

left:0;

margin:0;

padding:0;

width:100%;

height:100%;

background-color:#abc;

overflow:hidden;

}

#shell{

flex: 1 1 auto;

display:flex;

flex-flow:row nowrap;

position:relative;

width:100%;

min-height:100%;

min-width: 0;

}

#left{

flex: 0 0 180px;

min-height:100%;

min-width: 0;

background:lightblue;

}

#left.collapsed{

flex: 0 0 80px;

}



#mid{

flex: 1 1 auto;

min-height:100%;

min-width: 0;

display:flex;

flex-flow:column nowrap;

align-items:stretch;

align-content:stretch;

position:relative;

width:100%;

min-height:100vh;

min-width: 0;

background:purple;

}

#mid-top{

flex: 0 0 auto;

min-height:100px;

background:green;

}

#mid-bottom{

min-height:calc(100% - 100px);

flex: 1 1 auto;

background:lightgreen;

}

#list{

overflow: auto;

width: 100%;

max-width: 100%;

}

#list.nowrap{

white-space: nowrap;

}

#secondlist{

overflow: auto;

max-width: 250px;

white-space: nowrap;

}

.list-item{

display: inline-block;

width: 50px;

height: 50px;

margin: 2px;

background: purple;

}

.list-item.odd{

background: violet;

}



#help-pane{

display:none;

flex: 0 0 0px;

background:red;

}

#help-pane.visible{

display:inherit;

flex:0 0 180px;

}

<div id="body">

<div id="shell">

<div id="left">

<div id="nav">

- menu -

</div>

<div id="help-toggle">

help toggle

</div>

<div id="nav-toggle">

nav toggle

</div>

<div id="list-toggle">

list whitespace toggle

</div>


Related Topics



Leave a reply



Submit