Can flexbox fill the entire screen without access to the 'body'? - html

In my situation I'm not able to apply flex to the body tag. Can I achieve the same effect (sticky header/footer with the flexbox taking up the full screen) without applying css to the body tag. Here is the relevant code. I commented out the body css that achieves the effect I want.
Thanks,
Matt
/*html {
height: 100%;
}
body {
min-height: 100%;
display: flex;
flex-direction: column;
}
*/
.flex-body {
min-height: 100%;
display: flex;
flex-direction:column;
}
.main {
display: flex;
flex: 1 0 auto;
}
.nav {
flex: 0 0 12em;
}
.content {
flex: 1 0 auto;
display: flex;
flex-direction: column;
}
.row {
display: flex;
flex: 1 0 auto;
flex-direction: row;
}
.col {
flex: 1 0 auto;
}
/* TEMP CODE FOR THIS TEST, REMOVE FOR ACTUAL USE
*/
body {
text-align: center;
}
*{
box-shadow:inset 0px 0px 0px 1px #f00;
}
<div class="flex-body">
<header class="header">
<section class="content">
<div class="row">
<div class="col">
Upper Left
</div>
<div class="col">
Upper Middle
</div>
<div class="col">
Upper Right
</div>
</div>
</section>
</header>
<main class="main">
<nav class="nav">
Nav
</nav>
<section class="content">
<div class="row">
<div class="col">
Upper Left
</div>
<div class="col">
Upper Middle
</div>
<div class="col">
Upper Right
</div>
</div>
<div class="row">
Middle
</div>
<div class="row">
Lower
</div>
</section>
</main>
<footer class="footer">Footer</footer>
</div>

you can also imbricate flex boxe and use flex shorthands to fill entire parent's height or width . But this means to include html & body .
This way you do need to deal with height/width and margins/paddings. The browser will deal with it itself.
html {
height: 100%;
display: flex;
flex-direction: column;
}
body,
.flex-body {
display: flex;
flex: 1;/* no need anymore to deal with height/width */
flex-direction: column;
}
.main {
display: flex;
flex: 1;
/* mind this */
/*overflow:auto; */ /* can come handy here if you want to keep footer in view */
}
.nav {
flex: 0 0 12em;
}
.content {
flex: 1 0 auto;
display: flex;
flex-direction: column;
}
.row {
display: flex;
flex: 1 0 auto;
flex-direction: row;
}
.col {
flex: 1 0 auto;
}
/* TEMP CODE FOR THIS TEST, REMOVE FOR ACTUAL USE
*/
body {
text-align: center;
}
* {
box-shadow: inset 0px 0px 0px 1px #f00;
}
<div class="flex-body">
<header class="header">
<section class="content">
<div class="row">
<div class="col">
Upper Left
</div>
<div class="col">
Upper Middle
</div>
<div class="col">
Upper Right
</div>
</div>
</section>
</header>
<main class="main">
<nav class="nav">
Nav
</nav>
<section class="content">
<div class="row">
<div class="col">
Upper Left
</div>
<div class="col">
Upper Middle
</div>
<div class="col">
Upper Right
</div>
</div>
<div class="row">
Middle
</div>
<div class="row">
Lower
</div>
</section>
</main>
<footer class="footer">Footer</footer>
</div>

Add a min-height of 100vh to the flex container:
.flex-body {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
}
Then it will be at least as tall as the browser’s viewport (but will be allowed to grow taller if necessary).

Related

Forcing sidebar scroll using flexbox layout

I'm trying to build two column layout using flexbox css. Page should consist of header, sidebar, content area and footer.
One of the requirement is for a page to consume whole browser window space but not overflow it. Overflow could, however, happen in separate sections (like in this case - sidebar).
So I've decided to use flexbox for layout, however can't figure out how to make sidebar scrollable if it's content is bigger than place given to it by the layout engine.
I've built an example to better explain my problem. When there is not too much content (content size is smaller than the container), everything looks as expected:
html,
body {
height: 100%;
margin: 0;
}
.block {
border: 1px solid grey;
}
.container {
display: flex;
flex-flow: column;
height: 100%;
}
.container > .header {
flex: 0 1 auto;
height: 65px;
}
.container > .content {
display: flex;
flex: 1 1 auto;
flex-direction: row;
}
.container > .content > .page {
flex: 1 1 auto;
}
.container > .content > .sidebar {
flex: 0 1 auto;
width: 250px;
overflow: scroll;
}
.container > .footer {
flex: 0 1 auto;
height: 150px;
}
<body>
<div class="container">
<div class="block header">
<p>
<b>Header</b>
</p>
</div>
<div class="content">
<div class="block sidebar">
<p>
<b>Sidebar</b>
</p>
</div>
<div class="block page">
<p>
<b>Content</b>
</p>
</div>
</div>
<div class="block footer">
<p>
<b>Footer</b>
</p>
</div>
</div>
</body>
But if, for example, sidebar's content size is bigger than the sidebar itself, the footer gets pushed down and it causes the whole page to overflow the browser window size:
html,
body {
height: 100%;
margin: 0;
}
.block {
border: 1px solid grey;
}
.container {
display: flex;
flex-flow: column;
height: 100%;
}
.container > .header {
flex: 0 1 auto;
height: 65px;
}
.container > .content {
display: flex;
flex: 1 1 auto;
flex-direction: row;
}
.container > .content > .page {
flex: 1 1 auto;
}
.container > .content > .sidebar {
flex: 0 1 auto;
width: 250px;
overflow: scroll;
}
.container > .footer {
flex: 0 1 auto;
height: 150px;
}
<body>
<div class="container">
<div class="block header">
<p>
<b>Header</b>
</p>
</div>
<div class="content">
<div class="block sidebar">
<p>
<b>Sidebar</b>
</p>
<div style="background-color: blue; height: 800px;"></div>
</div>
<div class="block page">
<p>
<b>Content</b>
</p>
</div>
</div>
<div class="block footer">
<p>
<b>Footer</b>
</p>
</div>
</div>
</body>
How I could fix this problem and force sidebar to add scrolling behaviour when content doesn't fit the container rather than expand the container?
Add overflow-y: auto;, this will solve your problem.

Arranging flex-items in a particular way

I'd like to arrange flex-items in the following manner:
Using the following example:
.Container {
display: flex;
overflow: hidden;
height: 100vh;
margin-top: -100px;
padding-top: 100px;
position: relative;
width: 70vw;
}
<div class="Top">Top Content</div>
<div class="Container">
<div class="Left">Left Content</div>
<div class="Middle">Middle Content</div>
<div class="Right">Right Content</div>
</div>
I can make it so there is a horizontal bar and vertical columns under it. However, I cannot figure out how to make another vertical column; one consisting of the above code, and the other a different div.
Thanks!
You can use flex. For each "direction" use a container. To divide ratio 1:2 use flex-grow: 1 and flex-grow: 2;.
It's also important to use
flex-shrink: 0;
flex-basis: 0;
if you want to keep the ratio regardless of the content inside, otherwise, the browser will resize the divs according to the content inside them.
There is a shorter way of writing all the 3:
flex: [flex-grow], [flex-shrink], [flex-basis];
but IE doesn't support it, so I prefer using the long way
.out-container {
display: flex;
flex-direction: row;
}
.inner-cont {
display: flex;
flex-direction: row;
flex-grow: 2;
}
.container {
flex-grow: 2;
flex-shrink: 0;
flex-basis: 0;
}
.container {
display: flex;
flex-direction: column;
height: 100vh;
width: 70vw;
}
.left,
.right,
.middle,
.top {
padding: 10px;
border: 1px solid black;
}
.left {
flex-grow: 1;
flex-shrink: 0;
flex-basis: 0;
background-color: #aaeffe;
}
.top {
flex-basis: 0;
flex-grow: 1;
flex-shrink: 0;
background-color: #69e2fd;
}
.middle{
flex-basis: 0;
flex-grow: 1;
flex-shrink: 0;
background-color: #38d0fd;
}
.right{
flex-basis: 0;
flex-grow: 1;
flex-shrink: 0;
background-color: #1fbbfb;
}
<div class="out-container">
<div class="left">Left Content</div>
<div class="container">
<div class="top">Top content</div>
<div class="inner-cont">
<div class="middle">Middle Content</div>
<div class="right">Right Content</div>
</div>
</div>
</div>
<html>
<head>
<title>Page Title</title>
<style>
body{display:table}
.row{display:table-row}
.cell{display:table-cell}
.floatLeft{float:left}
.box1{background-color:#f00;width:100px;height:400px}
.box2{background-color:#0f0;width:400px;height:100px}
.box3{background-color:#00f;width:200px;height:300px}
.box4{background-color:#f0f;width:200px;height:300px}
</style>
</head>
<body>
<div class="row">
<div class="cell box1"></div>
<div class="cell">
<div class="row">
<div class="cell box2 "></div>
</div>
<div class="row">
<div class="cell box3 floatLeft"></div>
<div class="cell box4 floatLeft"></div>
</div>
</div>
</div>
</body>
</html>

Flexbox wrap does not work properly in firefox

Compare example below on chrome and firefox.
It wraps properly on chrome for me, but firefox instead of wrapping, stretches flexbox and overflows parent. So who is right here, chrome or firefox? And how can I achieve same effect as on chrome on both?
html,
body,
#app {
margin: 0;
padding: 0;
}
#app {
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
}
#top {
flex: 0 0 40px;
background-color: #ff0000;
}
#content {
flex: 1;
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.item {
height: 200px;
}
<div id="app">
<div id="top">
</div>
<div id="content">
<div class="item">
1
</div>
<div class="item">
2
</div>
<div class="item">
3
</div>
<div class="item">
4
</div>
<div class="item">
5
</div>
<div class="item">
6
</div>
</div>
</div>
Try setting a min-height and min-width on parent like so
#content {
min-height: 0;
min-width: 0; }

flexbox grid under centered flex item

I would like an intro section on the left side of a .container and a side bar on the right.
On the left side underneath the .intro section I want there to be four divs equally spaced like a grid.
I'm having problems with getting the "grid set up". I think part of the problem is that the parent has some flexbox attribute effecting the children.
Requirement : The intro section should be centered in the .left-side and the "grid" should not be centered the boxes should take up as much space as necessary to fit 2 on a row with margins in between. The .intro should be 80 percent of the width of the leftside.
I don't want to do any major changes to the structure this is just a small sample of how my project is set up.
.container{
width: 80%;
margin: 0 auto;
display: flex;
}
.left-side{
flex:8;
display: flex;
justify-content:center;
flex-wrap: wrap;
}
.side-bar{
flex: 2;
height: 100vh;
background: powderblue;
}
.intro{
flex:3;
width:80%;
height: 300px;
background: skyblue;
}
.box{
background: red;
width: 45%;
height: 100px;
flex:4;
border:1px solid orange;
}
<div class="container">
<div class="left-side">
<div class="intro">
intro
</div>
<div class="recent">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
</div>
</div>
<div class="side-bar">
sidebar
</div>
Flex items can also be flex containers. This enables you to nest multiple containers, with flex-direction: row or column, in a larger container.
For your layout, you can build a column consisting of two flex items. The first item (.intro) has 80% width and can be centered horizontally. The second item (.recent) can be a flex container with four items arranged in a 2x2 grid.
.container {
width: 80%;
margin: 0 auto;
display: flex;
justify-content: center;
height: 100vh;
}
.left-side {
flex: 4;
display: flex;
flex-direction: column;
}
.side-bar {
flex: 1;
background: powderblue;
}
.intro {
flex: 3;
height: 300px;
width: 80%;
margin: 0 auto;
background: skyblue;
}
.recent {
display: flex;
flex-wrap: wrap;
background-image: url("http://i.imgur.com/60PVLis.png");
background-size: contain;
}
.box {
margin: 5px;
flex-basis: calc(50% - 10px);
height: 100px;
box-sizing: border-box;
background: red;
}
body { margin: 0; }
<div class="container">
<div class="left-side">
<div class="intro">intro</div>
<div class="recent">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
</div>
</div>
<div class="side-bar">
sidebar
</div>
</div>

Set flex item height to size of content

I have three divs in a column. Each div has content that should scroll if it overflows. I would like each div to have the same height, with the max height of each div to be the height of its content. Is this possible to implement using flexbox?
Jsfiddle: http://jsfiddle.net/x6puccbh/2/
As you can see in the fiddle, all three sections are the same height, but I would like the middle section to be only as tall as its content.
<div class="container">
<div class="panel">
<div class="section">
<div class="header">HEADER</div>
<div class="content">content<br>content<br>content<br>content
<br>content<br>content<br>content<br>content
<br>content<br>content<br>content<br>content</div>
</div>
<div class="section">
<div class="header">HEADER</div>
<div class="content">content</div>
</div>
<div class="section">
<div class="header">HEADER</div>
<div class="content">content<br>content<br>content<br>content
<br>content<br>content<br>content<br>content
<br>content<br>content<br>content<br>content
</div>
</div>
</div>
.container {
height: 300px;
}
.panel {
display:flex;
flex-direction: column;
height: 100%;
}
.header {
height: 15px;
text-align: center;
flex-shrink: 0;
}
.section {
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
height: 100%;
border: 1px solid red;
display: flex;
flex-direction: column;
}
.content {
overflow-y: auto;
height: 100%;
}
does this work for you?
<div class="section">
<div class="header">HEADER</div>
<p>content sjkdkjasdn asjn dvas jkdb ajd avsd</p>
</div>
css
.section:nth-child(2) {
height:unset;
}
p {
padding-bottom: 5em;
}
here's a fork of the fiddle
Use this:
height: fit-content;
Can you use link:
https://caniuse.com/?search=fit-content