How to position blocks within flex block? - html

I want to position two blocks in parent block - one in the top, another in the bottom. Parents are follow each other as in catalog for example. To reach my goal I'am using flexible layout
<div class="container">
<div class="item">
<div class="holder">
<div class="content">
First content block<br/>
First content block<br/>
First content block<br/>
</div>
<div class="bottom"></div>
</div>
</div>
<div class="item">
<div class="holder">
<div class="content">
Second content block<br/>
Second content block<br/>
Second content block<br/>
Second content block<br/>
Second content block<br/>
Second content block<br/>
</div>
<div class="bottom"></div>
</div>
</div>
</div>
CSS is (webkit prefixes are deleted from this, presence in jsfiddle)
.container{
display: flex;
flex-wrap: wrap;
align-content: stretch;
}
.item{
width: 50%;
background-color: #fff;
}
.holder{
display: flex;
flex-direction:column;
align-content:space-between;
height: 100%;
}
.content{
flex: 1; // Added
width: 100%;
background-color: #eee;
}
.bottom{
width: 100%;
height: 20px;
background-color: #f00;
}
Code in jsfiddle https://jsfiddle.net/2nowks6p/5/.
There is a problem in layout, because bottom block does not position in bottom.
Can anyone explain to me, why this happen?
As #ketan answear add flex: 1 to .content solve problem in Firefox but not in Chrome and Opera.

I updated your demo to make it work on chrome & Firefox.
I added a display: flex; on .item and flex: 1; on .holder
https://jsfiddle.net/2nowks6p/8/

Just give flex:1; to .content will make bottom div to position bottom.
.content{
width: 100%;
background-color: #eee;
flex:1;
}
Updated Fiddle

Related

Have flex children only use space if they need it to not scroll, but otherwise share space equally and scroll

I have two flex children that may either each be small or large, and I'm defining small as < 50% of the container's height and large as > 50% the container's height. The sum of the heights of the children may be larger than 100% of the container's height, in which case I'd want one or both to scroll.
If one child is small and the other is large, I'd like the small element to use exactly the space it needs: it should not shrink to accommodate the large element, nor grow to 50%, and it should not scroll its contents. I'd like the large element to use the rest of the space, and scroll its contents if necessary.
If both are large, I'd like them to each use 50% of the container's height and scroll their contents.
I have this Codepen started as an example to help illustrate what I'm trying to achieve, but unfortunately it currently does no amount of scrolling or resizing: https://codepen.io/joeysilva/pen/wvmPqLK. It has both a small-large and a large-large case.
.flex-container {
height: 100px;
width: 100px;
display: flex;
flex-direction: column;
display: inline-block;
overflow: hidden;
}
.child {
flex: 50%;
overflow: auto;
}
.small {
background: red;
height: 30px;
}
.large {
background: blue;
height: 110px;
}
<div class="flex-container">
<div class="child">
<div class="small">Small</div>
</div>
<div class="child">
<div class="large">Large</div>
</div>
</div>
<div class="flex-container">
<div class="child">
<div class="large">Large 1</div>
<div class="large">Large 2</div>
</div>
</div>
Note 1: Not use disply:inline-block and display:flex the same time. Simply add another wrapper to show elements inside a row or column.
Note 2: flex: 50%; is equivalent to flex: 1 1 50%; and this is the shorthand form of flex-grow: 1; flex-shrink: 1; flex-basis: 50%;. Here in your code no need to use them because you have strictly defined the height of elements and also the basis of 50% height is wrong since you'd like the small element to use exactly the space it needs; no grow & no shrink, so it should be omitted.
.wrapper {
display: flex;
flex-direction: row;
}
.flex-container {
height: 100px;
width: 100px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.child {
overflow: auto;
}
.small {
background: red;
height: 30px;
}
.large {
background: blue;
height: 110px;
}
<div class="wrapper">
<div class="flex-container">
<div class="child">
<div class="small">Small</div>
</div>
<div class="child">
<div class="large">Large</div>
</div>
</div>
<div class="flex-container">
<div class="child">
<div class="large">Large 1</div>
</div>
<div class="child">
<div class="large">Large 2</div>
</div>
</div>
</div>

justify-content space between

I'm working with formatting some divs with a flex box and thought that justify-content: space-between is the best way to do it. But, I'm running into an issue when the browser resolution changes the items become misaligned. For example if I shrink the browser size the items will wrap onto the next line which is fine since I have flex-wrap: wrap, but on the new line that is created the contents are spread between. Is it possible to remove the justify-content every time the items wrap? Sorry for the poor explanation, I'll provide a jsfiddle. Change the fiddle to 483px and the items will wrap and be placed on the next line, but instead of space between I want the items to be placed next to each other.
http://jsfiddle.net/xut5cqhw/46/
.container {
position: relative;
height: 150px;
width: 40%;
display: flex;
justify-content:space-between;
flex-wrap: wrap;
background-color: black;
}
.content {
height: 50px;
width: 50px;
margin-top: 10px;
background-color: yellow;
}
<div class = "container">
<div class="content">
</div>
<div class="content">
</div>
<div class="content">
</div>
<div class="content">
</div>
<div class="content">
</div>
</div>

How do I create this layout using CSS flexbox?

I'm trying to create the following basic layout:
And I'm currently using the following basic HTML markup (with slightly different class names and additional markup within each of the HTML elements):
<div class="siteContainer">
<div class="sidebar">
<div class="topGreenStrip">
</div>
<div class="sidebarContainer">
<div class="sidebarInnerContainer">
<div class="brownSection">
</div>
<div class="purpleSection">
</div>
<div class="pinkSection">
</div>
<div class="redSection">
</div>
</div>
<div class="rightOrangeStrip">
</div>
</div>
</div>
<div class="lightPurpleContent">
</div>
</div>
And then the following starting CSS for the markup above:
.sidebar {
bottom: 0;
display: flex;
flex-direction: column;
left: 0;
position: fixed;
top: 0;
width: 300px;
}
.topGreenStrip {
height: 5px;
justify-self: flex-start;
}
.sidebarContainer {
flex-grow: 1;
justify-self: stretch;
}
The problem I'm having though is that because I start by stretching everything vertically with flexbox, I don't know how to then stretch things horizontally but still keep everything 100% the height of the screen.
That is, minus the 5px green top strip, I want the rest of the sidebar to occupy 100% the height of the screen. The large pink section should fill in whatever the brown, purple and red sections don't naturally.
I was able to get that part working without the orange bar by using justify-self: flex-start;, justify-self: stretch; and justify-self: flex-end;. However, once I add the orange bar in, I don't know how to keep doing what I'm doing.
The orange bar has a bit of dynamic content in it, so I can't set a static width, and the brown, purple, pink and red sections should use whatever width is not taken up by the orange bar (I'm assuming with flex-grow: 1;).
Anyway, how do I get this layout where (within the sidebar), I'm trying to stretch things both to 100% the height and 100% the width? Can I do this with just flexbox, or am I going to have to used positioned/floated elements to get this all to work?
Sorry for the vagueness, but after trying several things and getting nowhere close, I'm not sure where to begin. Thank you.
You need to make use of flex-direction: column on certain elements to stack the children. Also, using flex: 1 will force that element to grow and fill available space in it's parent.
By setting height: 100% on the html and body you can stretch .siteContainer to be the full height of the window.
I've added the background colours so you can see the layout in action.
html,
body {
margin: 0;
height: 100%;
}
.siteContainer {
display: flex;
height: 100%;
}
.sidebar {
display: flex;
flex-direction: column;
width: 300px;
}
.topGreenStrip {
height: 5px;
}
.sidebarContainer {
flex: 1;
display: flex;
}
.sidebarInnerContainer {
display: flex;
flex-direction: column;
flex: 1;
}
.pinkSection,
.lightPurpleContent {
flex: 1;
}
.topGreenStrip { background: green; }
.brownSection { background: peru; }
.purpleSection { background: darkviolet ; }
.pinkSection { background: pink; }
.redSection { background: red; }
.rightOrangeStrip { background: orange; }
.lightPurpleContent { background: lavender; }
<div class="siteContainer">
<div class="sidebar">
<div class="topGreenStrip">green
</div>
<div class="sidebarContainer">
<div class="sidebarInnerContainer">
<div class="brownSection">brown
</div>
<div class="purpleSection">purple
</div>
<div class="pinkSection">pink
</div>
<div class="redSection">red
</div>
</div>
<div class="rightOrangeStrip">orange
</div>
</div>
</div>
<div class="lightPurpleContent">lightpurple
</div>
</div>

Style one single column with flexbox

Maybe I want something impossible.
I want a website with only a single column styled with flexbox. The purpose is that only one column stretches its height to the footer regardless the size of the content of the column. Something like below structure:
I try to reach that with this code (I am using bootstrap):
<div class="container-fluid">
<div class="row">
<header class="col-md-12">
stuff...
</header>
<div class="col-md-1 col-a">
stuff...
</div>
<div class="col-md-10 col-b">
Stuff...
</div>
<div class="col-md-1 col-c">
<div class="col-c-child">
Stuff..
</div>
</div>
<footer class="col-md-12">
Stuff
</footer>
</div>
</div>
And then adding in the CSS this specific for the col-c and col-c-child:
.col-c {
display: flex;
flex-direction: column;
height: 100%;
}
.col-c-child {
flex: 1;
}
But is not working.
Any idea?
THE SOLUTION:
Create a row for the header, other for the content and other for the footer, that is - don't have everything in the same row.
Build a div-wrapper englobing col-a, col-b and col-c with display:flex and flex-direction: row;
get rid of col-c-child
col-c with flex: 1;
Thanks to #jelleB who elucidated me for part of it.
Put the header and the footer in different rows.
You should build a div below col-a (without content)
Use min-height: 100% on the row where you put col-a/col-b/col-c in
Give this a shot
I suspect your problem lies in the height:100%
If I am not mistaken, you cannot do that unless the parent container has its height defined. If the parent container's height is also defined as a percentage then the parent's parent container's height must also be defined. This hierarchy continues up to the body tag.
If you are able to wrap your middle divs, you can do the following:
html,
body {
height: 100%;
padding: 0;
margin: 0;
}
.container {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
}
.container #body {
display: flex;
flex-direction: row;
flex-grow: 1;
}
header,
footer {
width: 100%;
}
.left,
.right {
width: 100px; /*change to whatever width you want*/
}
.center {
flex-grow: 1;
}
/*styles for demo*/
header,
footer {
height: 50px;
background: blue;
}
.left,
.right {
background: green;
}
.center {
background: red
}
<div class="container">
<header></header>
<div id="body">
<div class="left"></div>
<div class="center"></div>
<div class="right"></div>
</div>
<footer></footer>
</div>

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>