Nesting flexbox inside flexbox overflow. How to fix this? - html

So I was trying to get a header and some content to fit into the screen by having a div #main with height: 100% as a flexbox, just like this:
#main {
height: 150px; /* Using a fixed height here, otherwise the snippet wouldn't work */
}
.flexbox {
display: flex;
flex-direction: column;
}
.header {
flex: 0 1 auto;
border: 2px solid #aa0000;
}
.content {
flex: 1 1 auto;
border: 2px solid #00aa00;
}
.scrollable {
overflow-y: scroll;
}
<html>
<body>
<div id="main" class="flexbox">
<div class="header">
HEADER
</div>
<div class="content scrollable">
CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
</div>
</div>
</body>
</html>
So now if #content overflows the height of #main, #content's scrollbar will take over, and the header stays visible. Works like a charm so far.
My problem is now that I need to nest another combination of header and screen fitting content into the outer content, which I tried to solve with another nested flexbox:
#main {
height: 150px; /* Using a fixed height here, otherwise the snippet wouldn't work */
}
.flexbox {
display: flex;
flex-direction: column;
}
.header {
flex: 0 1 auto;
border: 2px solid #aa0000;
}
.content {
flex: 1 1 auto;
border: 2px solid #00aa00;
}
.scrollable {
overflow-y: scroll;
}
<html>
<body>
<div id="main" class="flexbox">
<div class="header">
HEADER
</div>
<div class="content flexbox">
<div class="header">
HEADER
</div>
<div class="content scrollable">
CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
</div>
</div>
</div>
</body>
</html>
So basically I want both headers to stay up top now, and have only the inner content box scroll once it overflows. But when it does, the content stretches beyond (?!) #main's height, triggering the browser pages's scrollbar instead of its own one. I suppose the problem may be caused by the outer content box, whose height is only defined by the outer flexbox.
I already had tried a solution where the headers would have absolute positions, but this doesn't quite work out for what I need it. Flexboxes would be just perfect if it wasn't for this problem.
Can anyone help me fix this?

What you ask for is already happening in Chrome. Which makes me think you're developing with FF.
As a side-note, I believe that's a mistake, simply because you're developing for less than 15% of your target audience to only fix browser differences for another 65% of your audience. Luckily for you, they both keep tight to standards and differences are quite few these days.
Another reason why you might prefer Chrome over FF as a development tool is that FF has consistently been 6 months behind regarding dev tools for at least 4 years now. Don't get me wrong, I'm not a big Chrome fan and I fully welcome using FF as browsing device of choice. But, as a development tool, it's just not the best available. And they're both free.
Back to your question, adding overflow-y:auto to .flexbox seems to fix it in FF, too:
#main {
height: 150px; /* Using a fixed height here, otherwise the snippet wouldn't work */
}
.flexbox {
display: flex;
flex-direction: column;
overflow-y: auto;
}
.header {
flex: 0 1 auto;
border: 2px solid #aa0000;
}
.content {
flex: 1 1 auto;
border: 2px solid #00aa00;
}
.scrollable {
overflow-y: scroll;
}
<html>
<body>
<div id="main" class="flexbox">
<div class="header">
HEADER
</div>
<div class="content flexbox">
<div class="header">
HEADER
</div>
<div class="content scrollable">
CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
</div>
</div>
</div>
</body>
</html>
Note: of course, you'd need to run your code through a prefixer for a wider browser coverage. Mind the "filter" box below it. Set to > 0% for maximum cross-browser compatibility.

This issue affects not only Firefox, also Edge and IE11 overflow the parent.
It's caused by the fact that flex item's min-height* defaults to auto, and as such can't be smaller than its content. (Chrome tries to fix this by itself, hence it works on it, though, IMHO, it shouldn't)
* Very well explained here: The Implied Minimum Size of Flex Items
The affected element is the <div class="content flexbox">, which will overflow because if this.
The solution is to change its min-height to 0, and with that will allow it to shrink past content.
For IE11, see notes/sample below.
Stack snippet
#main {
height: 150px; /* Using a fixed height here, otherwise the snippet wouldn't work */
}
.flexbox {
display: flex;
flex-direction: column;
}
.header {
/*flex: 0 1 auto; default, so not needed */
border: 2px solid #aa0000;
}
.content {
flex: 1 1 auto;
border: 2px solid #00aa00;
min-height: 0; /* Firefox, Edge */
}
.scrollable {
overflow-y: scroll;
}
<div id="main" class="flexbox">
<div class="header">
HEADER
</div>
<div class="content flexbox">
<div class="header">
HEADER
</div>
<div class="content scrollable">
CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
<br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
<br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
<br>CONTENT<br>CONTENT<br>CONTENT<br>
</div>
</div>
</div>
As IE11 being a lot buggier, the above isn't enough, and there is 2 ways to fix it:
Using flex: 1 1 0%, which will make IE11 believe there is no content, hence will only grow as big as the available space in its parent.
#main {
height: 150px; /* Using a fixed height here, otherwise the snippet wouldn't work */
}
.flexbox {
display: flex;
flex-direction: column;
}
.header {
/*flex: 0 1 auto; default, so not needed */
border: 2px solid #aa0000;
}
.content {
flex: 1 1 0%; /* IE11, changed from "auto" to "0%" */
border: 2px solid #00aa00;
min-height: 0; /* Firefox, Edge */
}
.scrollable {
overflow-y: scroll;
}
<div id="main" class="flexbox">
<div class="header">
HEADER
</div>
<div class="content flexbox">
<div class="header">
HEADER
</div>
<div class="content scrollable">
CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
<br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
<br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
<br>CONTENT<br>CONTENT<br>CONTENT<br>
</div>
</div>
</div>
Using overflow: hidden (see note at the end)
#main {
height: 150px; /* Using a fixed height here, otherwise the snippet wouldn't work */
}
.flexbox {
display: flex;
flex-direction: column;
}
.header {
/*flex: 0 1 auto; default, so not needed */
border: 2px solid #aa0000;
}
.content {
flex: 1 1 auto;
border: 2px solid #00aa00;
/*min-height: 0; not needed, as overflow has same effect */
overflow: hidden; /* Firefox, Edge, IE11 */
}
.scrollable {
overflow-y: scroll;
}
<div id="main" class="flexbox">
<div class="header">
HEADER
</div>
<div class="content flexbox">
<div class="header">
HEADER
</div>
<div class="content scrollable">
CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
<br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
<br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
<br>CONTENT<br>CONTENT<br>CONTENT<br>
</div>
</div>
</div>
Note, using overflow with a value other than visible (its default), will have the same effect as min-height, where hidden is considered more safe than auto, avoiding future change in behavior to render a scrollbar.

You can fix this by using two height: 0 on the main box and the content box.
html,
body {
height: 100%;
}
.topheader {
background: orange;
width: 90%;
}
#container {
display: flex;
flex-direction: column;
height: 100%;
width: 50%;
background: red;
}
.subcontainer {
display: flex;
flex-direction: column;
flex: 1 1 auto;
height: 0;
width: 90%;
background: blue;
}
#container header {
background-color: gray;
}
#container article {
flex: 1 1 auto;
overflow-y: auto;
height: 0;
opacity: 0.5;
}
#container footer {
background-color: gray;
}
<section id="container">
<div class="topheader">
Top Header
</div>
<div class="subcontainer">
<header id="header">This is a header</header>
<article id="content">
This is the content that
<br />
With a lot of lines.
<br />
With a lot of lines.
<br />
This is the content that
<br />
With a lot of lines.
<br />
<br />
This is the content that
<br />
With a lot of lines.<br />
With a lot of lines.
<br />
This is the content that
<br />
With a lot of lines.
<br />
<br />
This is the content that
<br />
With a lot of lines<br />
With a lot of lines.
<br />
This is the content that
<br />
With a lot of lines.
<br />
<br />
This is the content that
<br />
With a lot of lines
<br />
<br />
This is the content that
<br />
With a lot of lines.
<br />
</article>
<footer id="footer">This is a footer</footer>
</div>
</section>

Related

Scroll Flexbox dashboard problem CSS HTML

When creating my dashboard with flexbox css html, I have a scroll problem for example:
In the middle red container if I make it vertical the horizontal one does not work well for me opteniendo results like it expands the container descuadrando the design.
If I work the horizontal scroll does not work the vertical scroll expanding this.
I want it to work like this in the following image:
Desired result
I have tried many things with the flexbox like setting the height or width to 100% and even forcing the scroll, but I can't get the expected effect.
Your question is a bit broad, you should post your current solution next time to see which part is not working. For example, I couldn't really tell if the vertical scrollbar in the middle region is supposed to scroll the top or the middle part. Anyways, if you're set on using flexboxes, here's a way to do it:
body {
margin: 0;
}
main {
display: flex;
width: 100vw;
height: 100vh;
}
.left {
width: 20%;
background-color: cornflowerblue;
}
.left__header {
background-color: lightblue;
}
.middle {
display: flex;
flex-direction: column;
width: 40%;
background-color: salmon;
}
.middle__header {
flex-shrink: 0;
overflow-y: auto;
background-color: lightpink;
}
.middle__body {
overflow-x: auto;
}
.middle__footer {
margin-top: auto;
background-color: white;
}
.right {
width: 40%;
background-color: lightgreen;
}
<main>
<div class="left">
<div class="left__header">1</div>
<div class="left__body"></div>
</div>
<div class="middle">
<div class="middle__header">
<!-- Fixed width to simulate overflowing content -->
<div style="min-width: 2000px">1 2 3 4 5</div>
</div>
<div class="middle__body">
<!-- Fixed height to simulate overflowing content -->
<div style="min-height: 2000px">Content</div>
</div>
<div class="middle__footer">
Pia de Pagina
</div>
</div>
<div class="right">
SideBar Right
</div>
</main>
But if you don't plan on dynamically adding/removing elements or moving stuff around in the base layout (i.e. these regions stay the same during the use of the application) I'd recommend using CSS grid instead:
body {
margin: 0;
}
main {
display: grid;
grid-template:
"left-header middle-header right" min-content
"left-body middle-body right"
"left-body middle-footer right" min-content / 2fr 4fr 4fr;
width: 100vw;
height: 100vh;
}
.left__header {
grid-area: left-header;
background-color: lightblue;
}
.left__body {
grid-area: left-body;
background-color: cornflowerblue;
}
.middle__header {
grid-area: middle-header;
overflow-x: auto;
background-color: lightpink;
}
.middle__body {
grid-area: middle-body;
overflow-y: auto;
background-color: salmon;
}
.middle__footer {
grid-area: middle-footer;
background-color: white;
}
.right {
grid-area: right;
background-color: lightgreen;
}
<main>
<div class="left__header">1</div>
<div class="left__body"></div>
<div class="middle__header">
<!-- Fixed width to simulate overflowing content -->
<div style="min-width: 2000px">1 2 3 4 5</div>
</div>
<div class="middle__body">
<!-- Fixed height to simulate overflowing content -->
<div style="min-height: 2000px">Content</div>
</div>
<div class="middle__footer">
Pia de Pagina
</div>
<div class="right">
SideBar right
</div>
</main>
This results in the same output, but the HTML/CSS is much more readable IMO. It uses the grid-template property, which is fairly new, but should be available in most browsers.

Flex header/content/footer causes unneeded scrollbar in IE but not other browsers

Hello I have this single .html file. When I open it in Chrome/Firefox/etc it works as expected, but when I open it with IE there is a unneeded vertical scrollbar that has very little "play". What is causing this and how can I fix it? Is there a better way to set headers/content/footers with css?
Thanks here's a screencap.
html,
body {
height: 100%;
margin: 0;
}
.box {
display: flex;
flex-flow: column;
height: 100%;
}
.box .row {
border: 1px dotted grey;
}
.box .row.header {
flex: 0 1 auto;
/* The above is shorthand for:
flex-grow: 0,
flex-shrink: 1,
flex-basis: auto
*/
}
.box .row.content {
flex: 1 1 auto;
}
.box .row.footer {
flex: 0 1 40px;
}
</style>
<div class="box">
<div class="row header">
<p><b>header</b>
<br />
<br />(sized to content)</p>
</div>
<div class="row content">
<p>
<b>content</b>
(fills remaining space)
</p>
</div>
<div class="row footer">
<p><b>footer</b> (fixed height)</p>
</div>
</div>
There are several ways to do this.
Method 1: The simplest way would be to hide the scrollbars under a <style> tag as shown:
body {
overflow-y: hidden;
}
Likewise, overflow-x: hidden will hide the horizontal scrollbar, and overflow: hidden will hide both horizontal and vertical scrollbars. Beware, however, that this not only hides the scrollbars, but removes its functionality. Therefore, if you add more content that exceeds the display of your page, it will just be cut off.
Method 2: If you want to hide the scrollbar but keep its functionality, then replace the above code with:
<style>
body::-webkit-scrollbar {
display: none;
}
</style>
This should occur across all browsers, in case your issue persists elsewhere.
Method 3: If you want this to specifically happen only for Internet Explorer, try the following:
<style>
.container {
-ms-overflow-style: none;
overflow: auto;
}
</style>

How to have one React component take up entire screen (on all devices) until you scroll down?

So lets say I have 3 components: Header, Intro, and MainContent
if I have something like:
<div className='homepage'>
<div id='top'>
<Header />
<Intro />
</div>
<div id='bottom'>
<MainContent />
</div>
</div>
How would I be able to style this so that the header and the intro take up the entirety of the screen on load, and then you have to scroll to reach the MainContent component?
I could I just set bottom padding of the #top to a percentage but that doesn't work for every device, correct?
We can use vh units with Flexbox to easily achieve this. The basic idea is to give the #top a height of 100vh (the full height of the viewport), and then use Flexbox to have the <Intro /> fill the remaining space not taken up by the <Header />. Like this:
#top {
height: 100vh;
display: flex;
flex-direction: column;
}
.intro {
flex-grow: 1;
}
/* Styling CSS - not relevant to solving the issue */
html,
body {
margin: 0;
font-family: Arial;
}
.header {
background-color: black;
color: white;
}
.intro {
background-color: lightgray;
}
.header,
.intro,
.main {
padding: 0.5rem;
}
#bottom {
min-height: 400px;
}
<div className='homepage'>
<div id='top'>
<div class="header">Header</div>
<div class="intro">Intro</div>
</div>
<div id='bottom'>
<div class="main">Main Content</div>
</div>
</div>

I need scrollbar on inner element, not browser window (viewport)

In the code below, how do I make the article container auto grow to consume the remaining vertical space below it, but the scroll bar to remain only for that element.
In other words, I want only the inside of article to scroll and not the entire browser window.
Is there a pure css solution? Or do I need javascript to detect the size of the browser window and adjust the height property of article dynamically?
html, body {
//height: 100%;
}
#outer_container {
display: flex;
flex-direction: row;
}
#outer2 {
flex: 1 0 auto;
}
#outer2 {
flex: 1 0 auto;
}
#container {
display: flex;
flex-direction: column;
height: 100%;
width: 50%;
background-color: red;
}
#container header {
background-color: gray;
}
#container article {
flex: 1 1 auto;
overflow-y: auto;
height: 0px;
}
#container footer {
background-color: gray;
}
<div id="outer_container">
<div id="outer1">
<h2>Outer 1</h2>
</div>
<section id="container">
<header id="header">This is a header</header>
<article id="content">
This is the content that
<br />With a lot of lines.
<br />With a lot of lines.
<br />This is the content that
<br />With a lot of lines.
<br />
<br />This is the content that
<br />With a lot of lines.
<br />
<br />This is the content that
<br />With a lot of lines.
<br />
</article>
<footer id="footer">This is a footer</footer>
</section>
<div id="outer2">
<h2>Outer 2</h2>
</div>
</div>
http://jsfiddle.net/ch7n6/907/
It was originally based on the answer to this question:
Flexbox and vertical scroll in a full-height app using NEWER flexbox api
You can try setting position:fixed to your outer container (http://jsfiddle.net/ch7n6/909/):
#outer_container{
display:flex;
flex-direction:row;
top:0;
bottom:0;
position:fixed;
}
If it doesn't work for your design, you can change the container dimensions using window.onresize event.
In your code you commented out:
html, body {
//height: 100%;
}
But I think you were on the right track.
By uncommenting that rule, and adding height: 100% to .outer_container, your layout may be complete.
Try this:
html, body {
height: 100%; /* uncommented */
margin: 0; /* removes default margin */
}
#outer_container {
height: 100%; /* new; see details below */
display: flex;
flex-direction: row;
}
#outer2 {
flex: 1 0 auto;
background-color: lightblue; /* just for demo */
}
#outer1 { /* correction to duplicate ID */
flex: 1 0 auto;
background-color: lightgreen; /* just for demo */
}
#container {
display: flex;
flex-direction: column;
height: 100%;
width: 50%;
background-color: red;
}
#container header {
background-color: gray;
}
#container article {
flex: 1 1 auto;
overflow-y: auto;
height: 0px;
}
#container footer {
background-color: gray;
}
<div id="outer_container">
<div id="outer1">
<h2>Outer 1</h2>
</div>
<section id="container">
<header id="header">This is a header</header>
<article id="content">
This is the content that
<br />With a lot of lines.
<br />With a lot of lines.
<br />This is the content that
<br />With a lot of lines.
<br />
<br />This is the content that
<br />With a lot of lines.
<br />
<br />This is the content that
<br />With a lot of lines.
<br />
</article>
<footer id="footer">This is a footer</footer>
</section>
<div id="outer2">
<h2>Outer 2</h2>
</div>
</div>
jsFiddle
To understand how this solution works, and what may have held you up, take a look at these posts:
Working with the CSS height property and percentage values
Chrome / Safari not filling 100% height of flex parent

Flexbox many nested children

I've read many posts on flexbox but still have an issue that bugs me.
I want to have a sticky footer using flexbox as per this guide.
But then, inside my page content I would like to have as many nested divs I like and have them taking the same height of the parent.
The problem is, setting height: 100% on each child (as I would do in a non-flexbox scenario) works differently when flexbox is enabled. This results in the children getting more height (overflow the parent).
To make this more clear here's a codepen without flexbox
and a codepen with flexbox
You can see in the flexbox scenario the footer gets the green bakground even if I don't want that.
HTML:
<div class="sticky-footer-container">
<div class="sticky-footer-content">
<div class="page-container">
<div class="main-menu">
<div class="main-menu-selection">
<div class="main-menu-selection-text">
<div class="some-other-class">
Some text
</div>
</div>
</div>
<div class="main-menu-selection">
<div class="main-menu-selection-text">
<div class="some-other-class">
Some text
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sticky-footer">
Some footer content
</div>
</div>
SCSS:
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
background: silver;
padding: 0;
margin: 0;
}
.sticky-footer-container {
height: 100%;
display: flex;
flex-direction: column;
.sticky-footer-content {
height: 100%;
background: blue;
flex: 1;
div {
height: 100%;
}
.main-menu-selection {
height: 50%;
}
}
}
.some-other-class {
background: green;
}
In order to solve this, ANY nested div has to become a flex-container ?
In other words, is there any way to "stop the flex propagation" at some point of the tree, so all the divs gets the parent height without overflow?
display:flexbox is not really a valid value :)
you need to set height as well and eventually inherit it from html :
.sticky-footer-container {
display: flex;
flex-direction: column;
}
.sticky-footer-content {
flex: 1;
}
/* let's inherit some height to pull the footer down */
html,
body,
.sticky-footer-container {
height: 100%;
margin: 0;
}
.sticky-footer {
display: flex;/* flex item can be flexboxes as well */
background: turquoise;
align-items: center;
justify-content: center;
min-height: 3em;
}
<div class="sticky-footer-container">
<div class="sticky-footer-content">
<div class="page-container">
<div class="main-menu">
<div class="main-menu-selection">
<div class="main-menu-selection-text">
<div class="some-other-class">
Some text
</div>
</div>
</div>
<div class="main-menu-selection">
<div class="main-menu-selection-text">
<div class="some-other-class">
Some text
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sticky-footer">
Here my footer
</div>
</div>