[html] Shrink to fit content in flexbox, or flex-basis: content workaround?

I have a webapp with which I'm using flexbox for layout.

I'm trying to both fill the screen (it's an app, not a document), and as far as possible to not specify any fixed widths or heights as the content could be all sorts of things (Full fluid layout! The dream!)

So I need fluid height, full width headers and footers, and then a main panel in the middle filling the remaining vertical space, divided into columns, each of which scrolls when too high, and where the width of each non-primary column should shrink to fit its content, and a primary column which uses up the remaining space.

I am so close, but have had to resort to explicitly sizing the non-main columns - I believe that flex-basis: content; is supposed to do this but isn't supported by browsers yet.

Here's a minimal demo showing fixed size columns:

_x000D_
_x000D_
var list = document.querySelector('ul')_x000D_
_x000D_
for (var i = 0; i < 100; i++) {_x000D_
  var li = document.createElement('li')_x000D_
  li.textContent = i_x000D_
  list.appendChild(li)_x000D_
}
_x000D_
html,_x000D_
body {_x000D_
  height: 100%;_x000D_
  width: 100%;_x000D_
  margin: 0;_x000D_
}_x000D_
body {_x000D_
  display: flex;_x000D_
  flex-direction: column;_x000D_
}_x000D_
main {_x000D_
  display: flex;_x000D_
  flex-direction: row;_x000D_
  overflow: hidden;_x000D_
}_x000D_
main > section {_x000D_
  overflow-y: auto;_x000D_
  flex-basis: 10em;_x000D_
  /* Would be better if it were fluid width/shrink to fit, unsupported: */_x000D_
  /* flex-basis: content; */_x000D_
}_x000D_
main > section:last-child {_x000D_
  display: flex;_x000D_
  flex: auto;_x000D_
  flex-direction: column;_x000D_
}_x000D_
main > section:last-child > textarea {_x000D_
  flex: auto;_x000D_
}
_x000D_
<header>_x000D_
  <h1>Heading</h1>_x000D_
</header>_x000D_
_x000D_
<main>_x000D_
  <section>_x000D_
    <h1>One</h1>_x000D_
    <ul>_x000D_
    </ul>_x000D_
  </section>_x000D_
_x000D_
  <section>_x000D_
    <h1>Two</h1>_x000D_
  </section>_x000D_
_x000D_
  <section>_x000D_
    <header>_x000D_
      <h1>Three</h1>_x000D_
    </header>_x000D_
    <textarea></textarea>_x000D_
    <footer>_x000D_
      <p>Footer</p>_x000D_
    </footer>_x000D_
  </section>_x000D_
</main>_x000D_
_x000D_
<footer>_x000D_
  <p>Footer</p>_x000D_
</footer>
_x000D_
_x000D_
_x000D_

Which looks like this - I want columns One and Two to shrink/grow to fit rather than being fixed:

enter image description here

My question is, is there a CSS-only workaround for flex-basis: content, or an alternative way to realise this goal?

I can possibly live with fixing the column sizes as above, or using javascript, but I HAVE A DREAM DAMN IT.

This question is related to html css flexbox

The answer is


It turns out that it was shrinking and growing correctly, providing the desired behaviour all along; except that in all current browsers flexbox wasn't accounting for the vertical scrollbar! Which is why the content appears to be getting cut off.

You can see here, which is the original code I was using before I added the fixed widths, that it looks like the column isn't growing to accomodate the text:

http://jsfiddle.net/2w157dyL/1/

However if you make the content in that column wider, you'll see that it always cuts it off by the same amount, which is the width of the scrollbar.

So the fix is very, very simple - add enough right padding to account for the scrollbar:

http://jsfiddle.net/2w157dyL/2/

_x000D_
_x000D_
  main > section {_x000D_
    overflow-y: auto;_x000D_
    padding-right: 2em;_x000D_
  }
_x000D_
_x000D_
_x000D_

It was when I was trying some things suggested by Michael_B (specifically adding a padding buffer) that I discovered this, thanks so much!

Edit: I see that he also posted a fiddle which does the same thing - again, thanks so much for all your help


I want columns One and Two to shrink/grow to fit rather than being fixed.

Have you tried: flex-basis: auto

or this:

flex: 1 1 auto, which is short for:

  • flex-grow: 1 (grow proportionally)
  • flex-shrink: 1 (shrink proportionally)
  • flex-basis: auto (initial size based on content size)

or this:

main > section:first-child {
    flex: 1 1 auto;
    overflow-y: auto;
}

main > section:nth-child(2) {
    flex: 1 1 auto;
    overflow-y: auto;
}

main > section:last-child {
    flex: 20 1 auto;
    display: flex;
    flex-direction: column;  
}

revised demo

Related:


Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width

Examples related to flexbox

Force flex item to span full row width vuetify center items into v-flex Equal height rows in CSS Grid Layout display: flex not working on Internet Explorer Center the content inside a column in Bootstrap 4 Vertical Align Center in Bootstrap 4 How to use zIndex in react-native Bootstrap 4 align navbar items to the right Does 'position: absolute' conflict with Flexbox? Make flex items take content width, not width of parent container