CSS Flex Layout: 2 columns out of non-hierarchal elements - css

I want to display the "right" and "left" elements in 2 columns. The right element should stretch vertically to the full height of the parent. Standard solutions use an extra container for each column. However, in my situation, the columns have no semantic meaning, they are just for display. Further, since my project will have many instances of this structure, adding container elements would introduce a lot of mess.
<div class='container'>
<div class='right'>
<div class='left'>
<div class='left'>
<div class='left'>
<div class='left'>
</div>
The under-appreciated "display:table-cell" almost works, but has some limitations, so that option is out. CSS "display:flex" is the only other potential solution that I can think of. I cannot find a working example, and my attempts have failed, so I hope that you can help me out. Thanks in advanced, -T

display:flex is awesome, but browser support could be an issue. Flex guide.
What's wrong with something like the below?
Fiddle Link!
HTML
<div class="left">
</div><!--
--><div class="right">
</div>
CSS
*, *:before, *:after {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
margin: 0;
padding: 0;
}
html, body {
height: 100%;
width: 100%;
max-width: 500px;
min-width: 200px;
margin: 0 auto;
}
div {
display: inline-block;
height: 100%;
}
.left {
background: #F00;
width: 50%;
}
.right {
background: #000;
width: 50%;
}

Within a flexible container, its children can be stacked vertically or horizontally (not both) via flex-direction. This is why if you want to use flexbox the .left divs should be wrapped in a containing parent. The .container children are stacked horizontally and the .left children are stacked vertically.
Here's fiddle: http://jsfiddle.net/7aK9f/1/.
Here's HTML:
<div class = "container">
<div class= "right">right</div>
<div class = "left">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
CSS:
* {
margin: 0;
padding: 0;
border: 0;
}
html, body {
height: 100%;
}
.container {
height: 100%;
display: -webkit-flex;
display: flex;
-webkit-flex-direction: row;
flex-direction: row;
}
.container > .right {
order: 2;
background-color: #ccc;
-webkit-flex: 3 0 0;
flex: 3 0 0;
}
.container > .left {
order: 1;
background-color: #eee;
-webkit-flex: 7 0 0;
flex: 7 0 0;
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
}
.container > .left > * {
-webkit-flex: 1 0 0;
flex: 1 0 0;
}
.container > .left > div + div {
box-shadow: inset 0 1px 0 0px #000;
}

Related

How to apply scorlbar to a section inside a flexbox?

Consider the following:
* {padding: 0; margin: 0; }
body {
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
}
header {
flex: 0 0 50px;
background-color: lightgray;
}
div#wrapper {
flex: 1 0 0px;
display: flex;
flex-direction: row;
}
aside {
background-color: darkgray;
flex: 0 0 50px;
}
main {
display: block;
flex: 1 1 0px;
background-color: aliceblue;
}
div#content {
width: 60px;
height: 2000px;
margin: 10px;
background-color: red;
}
div#content-wrap {
width: 100%;
height: 100%;
}
div#content-container {
height: 100%;
overflow-y: scroll;
}
<html>
<head></head>
<body>
<header></header>
<div id="wrapper">
<aside></aside>
<main>
<div id="content-wrap">
<div id="content-container">
<div id="content"></div>
</div>
</div>
</main>
</div>
</body>
</html>
In the snippet above, the <body> fills all the available space, it's consisted of a <header> which takes an arbitrary height and a <div id="wrapper"> that takes the rest of available height. The aforementioned "#wrapper" has a "sidebar" that has an arbitrary width and a "<main>" section to take the rest of the width. I want only the "main" section to be scrollable, but applying a long enough "#content" causes the "body" to get the scrollbar, instead! (while I've enforced the heights to be 100%) So, how to fix this?
here only remove same height according to <header></header> from <div id="wrapper"> bcz of normaly it will take 100% height #wrapper so only add height: calc(100% - 50px);
div#wrapper {
flex: 1 0 0px;
display: flex;
flex-direction: row;
height: calc(100% - 50px);
}
and it will be working like below ss

How do I make parent container and other child in Flex to grow as one of the longest child

I need to the container and the green div to grow as the same size as blue whenever things inside the blue div grow.
.container {
background: grey;
height: 200px;
flex-direction: column;
padding: 10px;
display: flex;
}
.normal {
background: green;
}
.wide {
width: 2500px;
background: blue;
flex: 1 0 auto;
}
<div class="container">
<div class="normal">Normal</div>
<div class="wide">Wide</div>
</div>
CodePen
consider inline-flex instead
.container {
background: grey;
height: 200px;
flex-direction: column;
padding: 10px;
display: inline-flex;
min-width:100%; /*to make sure it behave like flex if the content is small*/
box-sizing:border-box;
}
.normal {
background: green;
}
.wide {
width: 2500px;
background: blue;
flex: 1 0 auto;
}
<div class="container">
<div class="normal">Normal</div>
<div class="wide">Wide</div>
</div>
Related: Why does the outer <div> here not completely surround the inner <div>?

Why isn't `height: 100%` and absolute positioning working in flexbox?

I'm trying to make a child div of a flexbox layout fill its parent. In any other context setting the width/height to 100% causes a div to fill its parent... I only wish to use flexbox for my top level layout.
Problems
#map-container div will not fill #col1 even though it has height 100% set.
#controls div appears outside #col1 completely. I've previously used absolute layout to align boxes to corners without problems. Being inside a flexbox grand-parent seems to cause issues.
What I'm expecting is #map-container and #map to fill #col1 and #controls to align to bottom right-hand corner of #map.
.wrapper, html, body {
height:100%;
margin:0;
}
#col1 {
display: flex;
}
#map-container {
background-color: yellow;
width: 100%;
height: 100%;
}
#map {
background-color: purple;
width: 100%;
height: 100%;
}
#controls {
background-color: orange;
position: absolute;
right: 3px;
bottom: 3px;
width: 100px;
height: 20px;
}
.wrapper {
display: flex;
flex-direction: column;
}
#row1 {
background-color: red;
}
#row2 {
flex:2;
display: flex;
}
#col1 {
background-color: green;
flex: 1 1;
}
#col2 {
background-color: blue;
flex :0 0 240px;
}
<div class="wrapper">
<div id="row1">Header</div>
<div id="row2">
<div id="col1">
<div id="map-container">
<div id="map">
Map
</div>
<div id="controls">Controls</div>
</div>
</div>
<div id="col2">Sidebar</div>
</div>
</div>
#map-container div will not fill #col1 even though it has height 100% set.
It won't work that way, because for a percentage unit to work, it needs to have height set on its parent all the way up. This fights against the flex model, where the flex-items are distributed and arranged by the flex-box layout and have no dimensions set. Why use a flex layout when all your elements are 100%? Either do a 100% on all your element all the way up, or do a flex on all containers.
If you stick to flex layout, then you will have to get into nested flex. Otherwise, you will get #map-container to fill-up, but not the #map.
This fiddle http://jsfiddle.net/abhitalks/sztcb0me illustrates that problem.
#controls div appears outside #col1 completely. I've previously used absolute layout to align boxes to corners without problems. Being
inside a flex-box grand-parent seems to cause issues.
The only issue is that you are positioning it absolutely, but in relation to what? You need to position your #map-container relatively for that to work.
Here is how:
Fiddle: http://jsfiddle.net/abhitalks/sztcb0me/1/
Snippet:
* { box-sizing: border-box; padding: 0; margin: 0; }
html, body, .wrapper { height:100%; width: 100%; }
.wrapper { display: flex; flex-direction: column; }
#row1 { flex: 0 1 auto; background-color: red; }
#row2 { flex: 2 0 auto; display: flex; }
#col1 { flex: 1 0 auto; display: flex; background-color: green; }
#col2 { flex: 0 0 240px; background-color: blue; }
#map-container {
flex: 1 0 auto; display: flex;
position: relative; background-color: yellow;
}
#map { flex: 1 0 auto; background-color: purple; }
#controls {
background-color: orange;
position: absolute;
right: 3px; bottom: 3px;
width: 100px; height: 20px;
}
<div class="wrapper">
<div id="row1">Header</div>
<div id="row2">
<div id="col1">
<div id="map-container">
<div id="map">
Map
</div>
<div id="controls">Controls</div>
</div>
</div>
<div id="col2">Sidebar</div>
</div>
</div>
the problem is that it's wrapped in #map-container
.wrapper, html, body {
height:100%;
margin:0;
}
#col1 {
display: flex;
}
#map-container {
background-color: yellow;
width: 100%;
height: 100%;
}
#map {
background-color: purple;
width: 100%;
/* height: 100%; */
display: flex;
flex-wrap: wrap-reverse;
justify-content: space-between;
}
#controls {
background-color: orange;
position: relative;
/*right: 3px;
bottom: 3px;*/
width: 100px;
height: 20px;
}
.wrapper {
display: flex;
flex-direction: column;
}
#row1 {
background-color: red;
}
#row2 {
flex:2;
display: flex;
}
#col1 {
background-color: green;
flex: 1 1;
}
#col2 {
background-color: blue;
flex :0 0 240px;
}
<div class="wrapper">
<div id="row1">Header</div>
<div id="row2">
<div id="col1">
<!-- <div id="map-container"> -->
<div id="map">
Map
<div id="controls">Controls</div> <!-- add it here -->
</div>
<!-- <div id="controls">Controls</div> -->
<!--</div> -->
</div>
<div id="col2">Sidebar</div>
</div>
</div>
adding an absolute position controls in that way is not optimal (in the snippet I commented it out) ; you can place the controlsnested in #map (and use flex properties for correcting placement)

Make flex child element occupy 100% height of parent flex [duplicate]

This question already has answers here:
HTML5 flexible box model height calculation
(2 answers)
Closed 4 years ago.
I have a container flex with content flexes. How do i make content flex occupy full width and height of container flex.
<div id="main">
<div id="main-nav">
</div>
<div class="container">
<div class="content"></div>
<div class="content"></div>
</div>
</div>
#main{
display: flex;
flex-direction: column;
height: 100vh;
width: 100vw;
}
#main-nav{
width: 100%
height: 50px;
}
.container{
display: flex;
flex-direction: row;
flex-wrap: wrap;
flex: 1;
}
.content{
display: flex;
width: 100%;
height: 100%;
}
The above code makes content to occupy 100% width of container but height is based on the text within the content. I tried the solutions mentioned from similar questions but had no luck and it was still the same.
Basically, I want each of the content to occupy the same height as occupied by the container in the viewport height. I also tried jQuery,
var rht = $("#container").height();
$(".content").height(rht);
It changes the height properly but adds a horizontal scroll bar with increase in width.
After several updates to the original question:
* {
box-sizing: borderbox;
margin: 0;
padding: 0;
}
#main {
display: flex;
flex-direction: column;
border: 1px solid red;
min-height: 100vh;
}
#main-nav {
flex: 0 0 50px;
}
.container {
display: flex;
flex-direction: column;
flex: 1;
border: 1px solid green;
}
.content {
flex: 1;
border: 1px solid orange;
}
<div id="main">
<div id="main-nav"></div>
<div class="container">
<div class="content"></div>
<div class="content"></div>
</div>
</div>
JSfiddle Demo
You cannot set width or height of flex's child is bigger (size of flex)/(number of flex's childs) but you can add position: absolute into .content and position: relative into .container then set width and height for .content. First .content is under second .content, you can use propety z-index or display: none to control.
* {
box-sizing: borderbox;
margin: 0;
padding: 0;
}
#main {
display: flex;
flex-direction: column;
background: red;
min-height: 100vh;
}
#main-nav {
flex: 0 0 50px;
}
.container {
position: relative;
display: flex;
flex: 1;
background: green;
}
.content {
position: absolute;
left: 0px;
top: 0px;
height: 100%;
width: 100%;
flex: 1;
background: orange;
}
<div id="main">
<div id="main-nav"></div>
<div class="container">
<div class="content">left</div>
<div class="content">right</div>
</div>
</div>

Flexbox - can't keep divs in content area from overlapping footer

I have a web page using a column flexbox, with fixed size header and footer, and a content area which takes up the remaining space. This works fine.
The content area is a row flexbox, and I have 2 square divs side by side. I am making them square by using padding-bottom. This works fine, unless the window is >2x the content area height. Then my squares start bleeding into the footer, because padding is based on element width.
I would like the squares to never overlap the footer. I'm ok with there just being dead space to the right of the squares. I would like to stick with flexbox and avoid floats if possible. Only modern browsers need be supported.
Is this possible with only CSS? Or is this a job for JS.
Fiddle
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#box {
display: flex;
flex-flow: column;
height: 100%;
}
div {
border: 1px solid tomato;
box-sizing: border-box;
margin: 0;
padding: 2px;
}
#header {
flex: 0 0 5em;
}
#footer {
flex: 0 0 5em;
}
#content {
background: blue;
display: flex;
flex: 1 1 auto;
flex-flow: row wrap;
min-height: 30%;
}
#content > div {
background: tomato;
border-color: black;
flex: 1 0 auto;
max-height: 50%;
padding-bottom: 50%;
}
<div id="box">
<div id="header">
<p><b>header</b>
</p>
</div>
<div id="content">
<div id='am'></div>
<div id='pm'></div>
</div>
<div id="footer">
<p><b>footer</b>
</p>
</div>
</div>
TIA!
Simple soluton:
#box
{
display: flex;
flex-flow: column;
min-height: 100%; /* this*/
}
JSfiddle Demo
Note: This assumes you want the page to overflow...but I didn't see any reference to containing the page height to the viewport.

Resources