I have setup the following layout. The content__item elements (which are commented below) are overflowing vertically outside main container.
.root {
display: flex;
height: 100vh;
background-color: gray;
}
.nav {
width: 16rem;
background-color: red;
}
.main {
flex-grow: 1;
background-color: green;
}
.menu {
height: 4rem;
background-color: blue;
}
.content {
display: flex;
height: 100%;
padding: 2rem;
}
.content__item {
flex: 1;
margin-left: 1rem;
background-color: white;
}
<div className="root">
<nav className="nav"></nav>
<main className="main">
<div className="menu"></div>
<div className="content">
<!-- Overflowing -->
<div className="content__item"></div>
<div className="content__item"></div>
<div className="content__item"></div>
</div>
</main>
</div>
I am pretty sure its a flexbox bug. I tried using min-height: 0 on the container but it still doesn't work. I setup an environment here for reference.
The reason the content_items are overflowing is because height: 100% causes problems with flex. However if you remove that, the elements don't appear to fill the available height. This is because their parent (the content div) is not the child of a flex element, so it is in fact this element and not the content__item that isn't taking up the available height.
We can fix this by adding display:flex to the main div (the parent of content)... however now we have another problem! This makes the other child of content (the nav element) appears to the side. To fix this, we can use flex-direction: column;
The main changes you need to make this work as as follows:
.main {
flex-grow: 1; /* you already have this to allow the children grow */
display: flex; /* Add this so the content element can use the full height */
flex-direction: column; /* Add this to make the children stack one below another */
}
.content {
display: flex; /* you already had this */
flex:1; /* Add this to make it take up the available height */
}
.content__item {
flex: 1; /* You don't actually need this now */
}
Working Example:
Also FYI, you need to set the body margin to 0 - otherwise the 100vh extends larger than the screen as it is getting added to the default margin.
body { margin:0; }
.root {
display: flex;
height: 100vh;
background-color: gray;
}
.nav {
width: 16rem;
background-color: red;
}
.main {
flex-grow: 1;
background-color: green;
display:flex;
flex-direction:column;
}
.menu {
height: 4rem;
background-color: blue;
}
.content {
display: flex;
padding: 2rem;
flex:1;
}
.content__item {
margin-left: 1rem;
background-color: white;
}
<div class="root">
<nav class="nav"></nav>
<main class="main">
<div class="menu"></div>
<div class="content">
<!-- Overflowing -->
<div class="content__item">some text here</div>
<div class="content__item">some text here</div>
<div class="content__item">some text here</div>
</div>
</main>
</div>
body, html {
margin: 0;
}
.root {
display: flex;
height: 100vh;
background-color: gray;
}
.nav {
width: 16rem;
background-color: red;
}
.main {
flex-grow: 1;
background-color: green;
display: flex;
flex-direction: column;
}
.menu {
height: 4rem;
background-color: blue;
}
.content {
display: flex;
padding: 2rem;
flex: 1;
}
.content__item {
flex: 1;
margin-left: 1rem;
background-color: white;
}
<div class="root">
<nav class="nav"></nav>
<main class="main">
<div class="menu"></div>
<div class="content">
<!-- Overflowing -->
<div class="content__item">a</div>
<div class="content__item">b</div>
<div class="content__item">c</div>
</div>
</main>
</div>
Related
I am working on a project which requires some basic HTML/CSS. I have a code pen which may be easier to visualize: https://codepen.io/Sean713/pen/yLEZVEe
My objective is to make the innerBottomHalf element expand to fully fill the bottomHalf element (barring any padding). I would also like the navbar + wholePage element to take up the full VH.
I currently have it set so that the wholePage takes up the full VH, I'm not sure how to subtract the navbar height from this.
I also see that my innerBottomHalf expands outside of my BottomHalf, I do not know why this is, because I've set its height to be 100%.
I tried a lot of solutions online, the GPT chatbot, and prodding around with the code, but have been unable to figure it out. I appreciate any help.
My code is as follows:
ul {
list-style-type: none;
display: flex;
align-items: center;
}
li a {
display: block;
text-align: center;
padding: 10px 15px;
text-decoration: none;
}
div {
padding: 10px;
}
.wholePage {
background-color: blue;
display: flex;
flex-direction: column;
height: 100vh;
}
.topHalf {
background-color: purple;
display: flex;
justify-content: space-between;
}
.bottomHalf {
background-color: grey;
height: 100%;
}
.innerBottomHalf {
background-color: brown;
height: 100%;
}
.topLeftHalf {
background-color: green;
flex: 1;
height: 50vh;
}
.topRightHalf {
background-color: orange;
flex: 1;
height: 50vh;
}
<ul>
<li><a>Solve</a></li>
<li><a>About</a></li>
<li><a>Other</a></li>
</ul>
<div class="wholePage">
<div class="topHalf">
<div class="topLeftHalf">
This is the top left
</div>
<div class="topRightHalf">
This is the top right
</div>
</div>
<div class="bottomHalf">
This is the bottom half
<div class="innerBottomHalf">
This is the inner bottom half
</div>
</div>
</div>
With height: 100% on nested elements you'll get an overflow because there are heights from other elements being added. Instead of percentage heights, just use flex properties all the way.
body {
display: flex;
flex-direction: column;
height: 100vh;
margin: 0; /* remove default margins */
}
.wholePage {
background-color: blue;
display: flex;
flex-direction: column;
/* height: 100vh; */
flex: 1; /* new */
}
.bottomHalf {
background-color: grey;
/* height: 100%; */
display: flex;
flex-direction: column;
flex: 1;
}
.innerBottomHalf {
background-color: brown;
/* height: 100%; */
flex: 1;
}
/* no adjustments below this line */
ul {
list-style-type: none;
display: flex;
align-items: center;
}
li a {
display: block;
text-align: center;
padding: 10px 15px;
text-decoration: none;
}
div {
padding: 10px;
}
.topHalf {
background-color: purple;
display: flex;
justify-content: space-between;
}
.topLeftHalf {
background-color: green;
flex: 1;
height: 50vh;
}
.topRightHalf {
background-color: orange;
flex: 1;
height: 50vh;
}
<ul>
<li><a>Solve</a></li>
<li><a>About</a></li>
<li><a>Other</a></li>
</ul>
<div class="wholePage">
<div class="topHalf">
<div class="topLeftHalf">
This is the top left
</div>
<div class="topRightHalf">
This is the top right
</div>
</div>
<div class="bottomHalf">
This is the bottom half
<div class="innerBottomHalf">
This is the inner bottom half
</div>
</div>
</div>
This question already has answers here:
Fill remaining vertical space with CSS using display:flex
(6 answers)
Closed last year.
I have the following markup:
.layout {
display: flex;
flex-direction: column;
background-color: gray;
height: 100vh;
}
.app-bar {
background-color: lightblue;
}
.app-drawer {
background-color: black;
color: white;
flex-grow: 1;
}
.app-sidebar-container {
}
<div class="layout">
<div id="app-bar-container">
<div class="app-bar">APP BAR</div>
</div>
<div id="app-sidebar-container" class="app-sidebar-container">
<div class="app-drawer">DRAWER AND CONTENT</div>
</div>
</div
How should I modify this in order to get the drawer and content black div to stretch the entire remaining layout element (gray)?
Thanks.
flex-grow only works for direct child.
.layout {
display: flex;
flex-direction: column;
background-color: gray;
height: 100vh;
}
.app-bar {
background-color: lightblue;
}
.app-drawer {
background-color: black;
color: white;
/* new line */
height: 100%;
}
.app-sidebar-container {
/* new line */
flex-grow: 1;
}
<div class="layout">
<div id="app-bar-container">
<div class="app-bar">APP BAR</div>
</div>
<div id="app-sidebar-container" class="app-sidebar-container">
<div class="app-drawer">DRAWER AND CONTENT</div>
</div>
</div
Give the background-color to the .app-sidebar-container class and give that height: 100%.
That will fill make the element stretch to the entire grey area.
Alternatively you could give both the .app-sidebar-container and the .app-drawer a height of 100%.
Both should work.
change your css like this:
.layout {
display: flex;
flex-direction: column;
background-color: gray;
height: 100vh;
}
#app-bar-container {
flex-grow: 0.1
}
.app-bar {
background-color: lightblue;
height: 100%;
}
.app-sidebar-container {
flex-grow: 1;
}
.app-drawer {
height: 100%;
background-color: black;
color: white;
flex-grow: 1;
}
I have a layout that is mainly divided into 3 parts and the middle one should take a full height. And it does.
However, I need an additional div which will play a role of the backdrop and here the problem comes. The child doesn't want to take 100% height.
Here .body is a div that is being stretched when there is not enough content and .bg-gray is the one I want to take its parent full height.
Is there a way achieve this without using relative + absolute positioning?
Also, I'm looking for the answer to my question: why is this happening that way.
html, body {
padding: 0;
margin: 0;
}
.container {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: stretch;
}
.header {
height: 50px;
background-color: #e6e6e6;
}
.footer {
height: 50px;
background-color: #aaa444;
}
.body {
flex: 1;
}
.bg-gray {
background-color: #eee;
min-height: 100%;
flex: 1;
}
<div class="container">
<div class="header">
</div>
<div class="body">
<div class="bg-gray">
<div>
asdasd
</div>
</div>
</div>
<div class="footer">
</div>
</div>
Apply flexbox to the .body div.
.body {
flex: 1;
display: flex;
flex-direction: column;
}
html,
body {
padding: 0;
margin: 0;
}
.container {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: stretch;
}
.header {
height: 50px;
background-color: #e6e6e6;
}
.footer {
height: 50px;
background-color: #aaa444;
}
.body {
flex: 1;
display: flex;
flex-direction: column;
}
.bg-gray {
background-color: darkgrey;
min-height: 100%;
flex: 1;
}
.bg-gray div {
background: lightblue;
}
<div class="container">
<div class="header">
</div>
<div class="body">
<div class="bg-gray">
<div>
asdasd
</div>
</div>
</div>
<div class="footer">
</div>
</div>
I want to make a vertical nav that say will be 50px and then I want to have a flex area that has my header, main content area and footer.
Right now when I use absolute the flexbox container gets covered over as absolute it doing it's own thing. I am wondering if I can tell my flex container to start 50px from the left so I don't have to worry about icons and such getting swallowed up by it.
Do I have to make the flex container absolute as well?
You don't need any positioning or margins, just make it natural with the additional flex wrapper:
body {margin: 0}
.outerFlex {
display: flex; /* displays flex-items (children) inline */
height: 100vh; /* 100% of the viewport height */
}
nav {
flex-basis: 50px; /* initial width */
background: lightblue;
}
.innerFlex {
flex: 1; /* takes the remaining width */
display: flex;
flex-direction: column; /* stacks flex-items vertically */
background: lightgreen;
}
main {
flex: 1; /* takes the remaining height */
}
<div class="outerFlex">
<nav>Nav</nav>
<div class="innerFlex">
<header>Header</header>
<main>Main</main>
<footer>Footer</footer>
</div>
</div>
You can use margin-left:50px on the flex area to make it start at 50px;
see code sample
body {
margin: 0;
height: 100vh;
}
.container {
height: 100%;
}
.nav {
position: absolute;
width: 50px;
background: green;
height: 100%;
}
.flex-container {
display: flex;
background: yellow;
height: 100%;
margin-left: 50px;
}
<div class="container">
<div class="nav"></div>
<div class="flex-container">text sample</div>
</div>
You just need to position your nav as absolute or fixed, then give padding/margin that equals the width of your nav to the main content.
Here's an example.
.container {
width: 100%;
}
.left-nav {
position: fixed;
width: 50px;
height: 100%;
background: black;
}
.main {
display: flex;
flex-direction: column;
justify-content: space-between;
padding-left: 50px;
background: rgba(255,0,0,0.1);
}
.main-header {
background: red;
}
.main-body {
background: green;
}
.main-footer {
background: blue;
}
<div class="container">
<div class="left-nav">Nav</div>
<div class="main">
<div class="main-header">Header</div>
<div class="main-body">Body</div>
<div class="main-footer">Footer</div>
</div>
</div>
I have two "Splits" that are using flex-grow to either be 100% if only one is present or a 50%/50% if both are present. The issue is I would like for this behavior to be dependent on the presence of content within the div.splits.
Through some fiddling I can either get it to do the proper expanded heights or the proper removal of content, but not both at the same time.
The content DOM structure really needs to remain the same. Maybe adding an additional wrapper would be ok if need be. I am trying to resolve this with a pure CSS solution if possible.
JS Bin Code Snippet
CSS:
body {
border: 1px solid black;
display: flex;
width: 100vw;
}
section {
display: flex;
flex-direction: column;
width: 100vw;
}
.split {
width: 100vw;
display: flex;
flex: 1;
}
.content {
/* probably something here? */
}
/*-------------- Non pertinent styles -----------------*/
.pink { text-align: center; background-color: pink; }
.blue { text-align: center; background-color: turquoise; }
nav { background-color: steelblue; }
HTML:
<body>
<section>
<div class="split pink">
<!-- If I remove this <h1> I would like for
the behavior to be the same as if I
removed this .pink.split div from the DOM -->
<h1 class="content">A</h1>
</div>
<nav> Some Nav </nav>
<div class="split blue">
<h2 class="content">B</h2>
</div>
</section>
</body>
As the JSBin demo fills the viewport, there is 2 solutions for solving this.
The solution to the inline code, where the section doesn't fill the viewport.
You should use flex-grow: 1;, not flex: 1, as with flex: 1, which is the same as flex: 1 1 0, the flex-basis is 0, and when, the flex items will flex-grow based on their content is 0, hence take equal space.
Alternatively you could use flex: 1 1 auto.
Src: https://www.w3.org/TR/css-flexbox-1/#flex-common
Stack snippet - with content
body {
border: 1px solid black;
box-sizing: border-box;
display: flex;
}
section {
display: flex;
flex-direction: column;
width: 100%;
}
.split {
display: flex;
flex-grow: 1; /* or "flex: 1 1 auto" */
}
/*-------------- Non pertinent styles -----------------*/
.pink { text-align: center; background-color: pink; }
.blue { text-align: center; background-color: turquoise; }
nav { background-color: steelblue; }
<section>
<div class="split pink">
<!-- If I remove this <h1> I would like for
the behavior to be the same as if I
removed this .pink.split div from the DOM -->
<h1 class="content">A</h1>
</div>
<nav> Some Nav </nav>
<div class="split blue">
<h2 class="content">B</h2>
</div>
</section>
Stack snippet - without content
body {
border: 1px solid black;
box-sizing: border-box;
display: flex;
}
section {
display: flex;
flex-direction: column;
width: 100%;
}
.split {
display: flex;
flex-grow: 1; /* or "flex: 1 1 auto" */
}
/*-------------- Non pertinent styles -----------------*/
.pink { text-align: center; background-color: pink; }
.blue { text-align: center; background-color: turquoise; }
nav { background-color: steelblue; }
<section>
<div class="split pink">
<!-- If I remove this <h1> I would like for
the behavior to be the same as if I
removed this .pink.split div from the DOM -->
</div>
<nav> Some Nav </nav>
<div class="split blue">
<h2 class="content">B</h2>
</div>
</section>
The solution for the JSBin, where the section fill the viewport
Use the :empty selector, and when the split is empty, change it to flex: 0.
Stack snippet - with content
body {
border: 1px solid black;
box-sizing: border-box;
display: flex;
margin: 0;
height: 100vh;
}
section {
display: flex;
flex-direction: column;
width: 100%;
}
.split {
display: flex;
flex: 1;
}
.split:empty {
flex: 0;
}
/*-------------- Non pertinent styles -----------------*/
.pink { text-align: center; background-color: pink; }
.blue { text-align: center; background-color: turquoise; }
nav { background-color: steelblue; }
<section>
<div class="split pink">
<!-- If I remove this <h1> I would like for
the behavior to be the same as if I
removed this .pink.split div from the DOM -->
<h1 class="content">A</h1>
</div>
<nav> Some Nav </nav>
<div class="split blue">
<h2 class="content">B</h2>
</div>
</section>
Stack snippet - without content
body {
border: 1px solid black;
box-sizing: border-box;
display: flex;
margin: 0;
height: 100vh;
}
section {
display: flex;
flex-direction: column;
width: 100%;
}
.split {
display: flex;
flex: 1;
}
.split:empty {
flex: 0;
}
/*-------------- Non pertinent styles -----------------*/
.pink { text-align: center; background-color: pink; }
.blue { text-align: center; background-color: turquoise; }
nav { background-color: steelblue; }
<section>
<div class="split pink"></div>
<nav> Some Nav </nav>
<div class="split blue">
<h2 class="content">B</h2>
</div>
</section>