I'm trying to do what I thought was a fairly standard sort of full-screen layout using flexbox, but it's not behaving the way I want. My goals are:
- Auto sizing of topbar/footer height and sidebar width (size to content, not fixed size)
- Topbar/footer take full width and never scroll
- Sidebar takes full height but if contents are larger can vertically scroll only
- Content takes leftover width/height but if contents are larger can scroll both ways
- Sidebar/Content scroll independently of each other (and hide scrollbars when not needed)
- Main content area will usually appear as regular doc with scrollbar, but sometimes I want it to also have some nested sidebars with a remaining-height scrolling subpanel.
* { box-sizing: border-box;}html, body { margin: 0;}.page { width: 100vw; height: 100vh; display: flex; flex-direction: column; overflow: hidden;}.topbar { background-color: lightgreen;}.vcontainer { flex-grow: 1; display: flex; flex-direction: row; min-height: 0;}.sidebar { overflow-y: auto; background-color: yellow;}.content { flex-grow: 1; overflow: auto; background-color: lightblue;}.footer { background-color: pink;}
<div class="page"><nav class="topbar"> top bar</nav><div class="vcontainer"><nav class="sidebar"> side<br/>side<br/>side</nav><main class="content"><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p></main></div><footer class="footer"> footer</footer></div>
The above works fine for the full doc scrolling variant (although the magic was adding the min-height
to vcontainer
; it didn't work prior to that) -- the blue area takes the remaining space and is scrollable if the content gets too long.
Without changing the outer styling (or at least not changing it in a way that breaks the above scenario), I want to be able to sometimes put in some content
that essentially has an additional dynamic-height topbar and a scrolling subsection that doesn't trigger the main content scrollbar.
* { box-sizing: border-box;}html, body { margin: 0;}.page { width: 100vw; height: 100vh; display: flex; flex-direction: column; overflow: hidden;}.topbar { background-color: lightgreen;}.vcontainer { flex-grow: 1; display: flex; flex-direction: row; min-height: 0;}.sidebar { overflow-y: auto; background-color: yellow;}.content { flex-grow: 1; overflow: auto; background-color: lightblue;}.footer { background-color: pink;}.contentcontainer { display: flex; flex-direction: column; min-height: 0;}.contentsub { margin: 1rem; overflow-y: scroll; flex-grow: 1; background-color: orange;}
<div class="page"><nav class="topbar"> top bar</nav><div class="vcontainer"><nav class="sidebar"> side<br/>side<br/>side</nav><main class="content"><div class="contentcontainer"><div> some additional heading content</div><div class="contentsub"><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p><p>some actual content</p></div><div> some additional footer content</div></div></main></div><footer class="footer"> footer</footer></div>
What I'm wanting is for the blue area to not have a scrollbar in this case, but instead for the orange area to be scrollable, surrounded by the extra header/footer and sized to fill the leftover space. Ideally, this should work even if contentsub
isn't a direct child of the contentcontainer
but there's more wrapping elements and borders etc before getting to the scrollable element. I would prefer a solution that's "pure flexbox", but if there's a better way to do it then I'm all ears. I do want to avoid using javascript, however.