Thoronwen Thoronwen - 10 months ago 42
CSS Question

Force flex element not to grow in cross-axis direction

I'm making a page with a vertical menu using

display: flex;
. I want the menu's width to fit snuggly around a few buttons, without having to use a fixed width.

However, I also want the menu box to have a status message, which can have quite a long text. I'd like this status-div to have the width of the menu, while not forcing the menu container to grow its width. Instead, the status-div should grow its height and wrap the text.

Explaining this in words is pretty difficult, so I suggest you checkout out this fiddle:

Note the difference when setting
display: none;

Any ideas, or is what I'm trying to do not feasible? ..should it be?

What I've tried:

  • width: 100%
    fails, obviously it just assumes the parent width

  • width: -webkit-min-content
    sort of works, but it makes the element too narrow

  • flex-basis
    affect the height of the element, and do nothing to affect the width

  • position: absolute
    will solve the width issues, but now I have no way to define the height of the status-div.. (for the purpose of forcing a scroll bar in windows with small height - instead it will just flow over the button elements)

Code in the fiddle


<div class=menu>
<div class=somechildren>I'd like the menu's</div>
<div class=somechildren>width to fit nicely</div>
<div class=somechildren>around these children</div>

<div class=separate></div>

<div class=statusmessage>
While forcing this status message to wrap and grow its height, without affecting the width of the container.
<div class=page>
The page


body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: flex;
flex-flow: row nowrap;
align-items: stretch;
.page {
flex-grow: 1;
background-color: yellow;
.menu {
background-color: red;
height: 100%;
display: flex;
flex-flow: column nowrap;
.somechildren {
white-space: nowrap;
background-color: green;
border: 1px solid black;
.menu > * {
flex-shrink: 0;
.separate {
flex-grow: 1;
.statusmessage {
background-color: magenta;
align-self: flex-end;
/*display: none;*/

Answer Source

You were almost there with width. What you need to do is set width and min-width (demo):

.statusmessage {
 width:0; /* Collapses .statusmessage so it doesn't affect column width */
 min-width:100%; /* Expands .statusmessage to width of column */

The width can be (and probably should be) set to a value other than 0. It should just be the minimum width of the column or smaller. So use a value that works for you.

I've tested this on Chrome and Firefox and seems to work in both. Now, is it supposed to work? I'm not sure, I haven't read into the spec that much (it could be undefined). Make sure to test in all browsers you need it to work in. (And check the spec to see if this behavior is undefined/incorrect.)