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.
- This is required because
- Now that
<li>
is a flex container and it contains only a single child, we can usealign-items
and/orjustify-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, exceptvisible
)
Flexbox Specification
4.5. Automatic Minimum Size of Flex
ItemsTo provide a more reasonable default minimum size for flex items, this
specification introduces a newauto
value as the initial value of
themin-width
andmin-height
properties defined in CSS 2.1.
With regard to the auto
value...
On a flex item whose
overflow
isvisible
in the main axis, when specified on the flex item’s main-axis min-size property, specifies an automatic minimum size. It otherwise computes to0
.
In other words:
- The
min-width: auto
andmin-height: auto
defaults apply only whenoverflow
isvisible
. - If the
overflow
value is notvisible
, the value of the min-size property is0
. - Hence,
overflow: hidden
can be a substitute formin-width: 0
andmin-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 the0
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 ChromeIE11
As noted in the spec, the
auto
value for themin-width
andmin-height
properties is "new". This means that some browsers may still render a0
value by default, because they implemented flex layout before the value was updated and because0
is the initial value formin-width
andmin-height
in CSS 2.1. One such browser is IE11. Other browsers have updated to the newerauto
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
Border with a Transparent Centred Arrow
CSS Wrong Appearance of Border-Radius on a Nested Div
Restoring the Value of a Input Type=File After Failed Validation
Can Xhtml and HTML Class Attributes Value Start with a Number
How to Cut a Circular Part from an Image
How to Implement Curve Background in CSS
Floating Elements Are Outside of Containing Blocks
Flexbox Resize and Scrollable Overflow
Chrome: Automatic Shift of Web Elements
Use Fieldset Legend with Bootstrap
How to Center Div Vertically Inside of Absolutely Positioned Parent Div