Arranging flex-items in a particular way - html

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>

Related

Create a circle that fills up the remaining space in a flexbox cell

I have a 2-cell flexbox with a fixed-height (mobile screen), and one cell stacked on top of the other. I need all of the content of the top-cell to be displayed.. the bottom-cell should yield as much space as possible to allow this. This part was easy.
.main-container {
height: 400px;
width: 200px;
display: flex;
flex-direction: column;
}
.content-container {
flex-grow: 1;
flex-shrink: 0;
background-color: green;
}
.content {
height: 100px;
}
.remaining-space {
flex-grow: 0;
flex-shrink: 1;
height: 100%;
background-color: lightgrey;
}
<div class="main-container">
<div class="content-container">
<div class="content"></div>
</div>
<div class="remaining-space"></div>
</div>
... with that the content-container will grow as needed (in this example it's 100px) and the rest is taken up by the remaining-space cell.
What I need to do is fill the remaining-space cell with a circle that is as big as it can be, but doesn't force the remaining-space cell to grow in height/width... and I need to do it with just html/css.
The only way I've seen to enforce a 1:1 ratio (square/circle) is by using the padding-bottom trick where the padding is calculated using the element's width. This doesn't work for me because remaining-space cell might have a larger width than it's height.. which will cause the cell to grow in height. This is especially difficult in that the container is responsive so the actual width in pixels is never known.
A simple gradient can do it:
.main-container {
height: 400px;
width: 200px;
display: inline-flex;
vertical-align: top;
flex-direction: column;
}
.content-container {
flex-grow: 1;
flex-shrink: 0;
background-color: green;
}
.content {
height: 100px;
}
.remaining-space {
flex-grow: 0;
flex-shrink: 1;
height: 100%;
background:
radial-gradient(circle closest-side, red 98%, transparent)
lightgrey;
}
<div class="main-container">
<div class="content-container">
<div class="content"></div>
</div>
<div class="remaining-space"></div>
</div>
<div class="main-container" style="height:200px;">
<div class="content-container">
<div class="content"></div>
</div>
<div class="remaining-space"></div>
</div>
Clip-path can also do it:
.main-container {
height: 400px;
width: 200px;
display: inline-flex;
vertical-align: top;
flex-direction: column;
}
.content-container {
flex-grow: 1;
flex-shrink: 0;
background-color: green;
}
.content {
height: 100px;
}
.remaining-space {
flex-grow: 0;
flex-shrink: 1;
height: 100%;
background: lightgrey;
}
.remaining-space>div {
height: 100%;
background: red;
clip-path: circle(closest-side)
}
<div class="main-container">
<div class="content-container">
<div class="content"></div>
</div>
<div class="remaining-space">
<div></div>
</div>
</div>
<div class="main-container" style="height:200px;">
<div class="content-container">
<div class="content"></div>
</div>
<div class="remaining-space">
<div></div>
</div>
</div>
Where you can also have content inside
.main-container {
height: 400px;
width: 200px;
display: inline-flex;
vertical-align: top;
flex-direction: column;
}
.content-container {
flex-grow: 1;
flex-shrink: 0;
background-color: green;
}
.content {
height: 100px;
}
.remaining-space {
flex-grow: 0;
flex-shrink: 1;
height: 100%;
background: lightgrey;
}
.remaining-space>div {
height: 100%;
background: red;
clip-path: circle(closest-side);
display:flex;
align-items:center;
justify-content:center;
font-size:30px;
}
<div class="main-container">
<div class="content-container">
<div class="content"></div>
</div>
<div class="remaining-space">
<div> text </div>
</div>
</div>
<div class="main-container" style="height:200px;">
<div class="content-container">
<div class="content"></div>
</div>
<div class="remaining-space">
<div> text </div>
</div>
</div>

Flex - make parent width of children?

I have a flex box layout. I want the width of .outer-2 to be the width of its children, with .outer-1 and outer-3 taking up the rest of the space.
How can I achieve this?
JSFiddle
.container {
display: flex;
}
.outer-1 {
background: red;
height: 100px;
flex: 1;
}
.outer-2 {
display: flex;
flex: 1;
}
.outer-3 {
background: blue;
height: 100px;
flex: 1;
}
.inner {
flex-basis: 30px;
background: green;
height: 100px;
margin: 0 3px;
}
<div class="container">
<div class="outer-1">
</div>
<div class="outer-2">
<div class="inner">
</div>
<div class="inner">
</div>
<div class="inner">
</div>
</div>
<div class="outer-3">
</div>
</div>
You need to change the flex properties for the second child of container preventing it from growing to fit it's parent. That, and adding a width or min-width to each .inner element will prevent their parent from collapsing them down.
.container{
display: flex;
}
.outer-1{
background: red;
height: 100px;
flex: 1;
}
.outer-2{
display: flex;
flex: 1;
}
.outer-3{
background: blue;
height: 100px;
flex: 1;
}
.inner{
width: 30px;
flex: 1 0 30px;
background: green;
height: 100px;
margin: 0 3px;
}
<div class="container">
<div class="outer-1">
</div>
<div class="outer-2">
<div class="inner">
</div>
<div class="inner">
</div>
<div class="inner">
</div>
</div>
<div class="outer-3">
</div>
</div>

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>

When rows added to a flexbox, box's height increases

When I add more inbox1 class divs into the div with class box1, the height of box1 increases. You can observe this in jsfiddle with red background never disappearing, however many inbox1's are added. What is the reason of this?
.outer {
position: relative;
width: 400px;
height: 600px;
background-color: black;
display: flex;
flex-flow: row wrap;
}
.container {
position: relative;
flex: 1;
display: flex;
flex-direction: column;
}
d1 {
flex: 1;
background-color: yellow;
}
.d2 {
flex: 1;
background-color: green;
}
.box1 {
display: flex;
flex-flow: row wrap;
align-content: flex-start;
color: white;
flex: 1;
background-color: red;
overflow: scroll;
}
.box2 {
color: white;
flex: 12;
background-color: blue;
}
.inbox1 {
flex: 1 100%;
background-color: purple;
}
<div class="outer">
<div class="container">
<div class="box1">
<div class="inbox1">inbox1</div>
<div class="inbox1">inbox1</div>
<div class="inbox1">inbox1</div>
<div class="inbox1">inbox1</div>
<div class="inbox1">inbox1</div>
</div>
<div class="box2"></div>
</div>
<div class="d1"></div>
<div class="d2"></div>
</div>
Edit :
The purpose of this structure is that, container div is the content of a website, and d1 and d2 divs represent sidebars. However their order is not set in the example because they are needed for the sake of the result.
Container div has two parts, upper(red background) and lower. In my structure this upper and lower are set as flex boxes in container which is display flex with column direction. Upper is also display flex with row direction. However in this set up, as new items are added into the upper, the height of the upper increases. I dont want it enlarge with added childrens.
Note that, if I remove d1 and d2 divs and remove display:flex and related css attributes from outer div, and add container in it as a classic relative element, and change NOTHING else, this problem magically disappears.
Edit 2:
Thanks to oriol, i confirmed this only occurs with chrome.
If I understand you right, here is 3 ways to accomplish that
By giving flex: 0 to your box1, you tell it to only be as big as its content, and by adding max-height: 80px you say "start scroll" when content gets higher than 80px
.outer {
position:relative;
width:400px;
height:600px;
background-color:black;
display: flex;
flex-flow: row wrap;
}
.container {
position:relative;
flex: 1;
display: flex;
flex-direction: column;
}
.d1 {
flex: 1;
background-color: yellow;
}
.d2 {
flex: 1;
background-color: green;
}
.box1 {
display: flex;
flex-flow: row wrap;
align-content: flex-start;
color: white;
flex: 0; /* changed from 1 to 0 */
background-color: red;
overflow: scroll;
max-height: 80px; /* added */
}
.box2 {
color: white;
flex: 12;
background-color: blue;
}
.inbox1 {
flex: 1 100%;
background-color: purple;
}
<div class="outer">
<div class="container">
<div class="box1">
<div class="inbox1">
inbox1
</div>
<div class="inbox1">
inbox1
</div>
<div class="inbox1">
inbox1
</div>
<div class="inbox1">
inbox1
</div>
<div class="inbox1">
inbox1
</div>
</div>
<div class="box2">
</div>
</div>
<div class="d1">
</div>
<div class="d2">
</div>
</div>
Set the flex-basis to 8% (box1 has flex 1 and box2 has flex 12, 100 / 12+1 = 7.69) and when content grow beyond that, it starts to scroll.
Note that the container needs height:100%, so flex-basis: 8% have where to get its value.
.outer {
position:relative;
width:400px;
height:600px;
background-color:black;
display: flex;
flex-flow: row wrap;
}
.container {
position:relative;
height: 100%; /* added */
flex: 1;
display: flex;
flex-direction: column;
}
.d1 {
flex: 1;
background-color: yellow;
}
.d2 {
flex: 1;
background-color: green;
}
.box1 {
display: flex;
flex-flow: row wrap;
align-content: flex-start;
color: white;
flex: 1;
flex-basis: 8%; /* added */
background-color: red;
overflow: scroll;
}
.box2 {
color: white;
flex: 12;
background-color: blue;
}
.inbox1 {
flex: 1 100%;
background-color: purple;
}
<div class="outer">
<div class="container">
<div class="box1">
<div class="inbox1">
inbox1
</div>
<div class="inbox1">
inbox1
</div>
<div class="inbox1">
inbox1
</div>
<div class="inbox1">
inbox1
</div>
<div class="inbox1">
inbox1
</div>
</div>
<div class="box2">
</div>
</div>
<div class="d1">
</div>
<div class="d2">
</div>
</div>
Use an inner div with position: absolute (since flex has some issues to force scroll, this one make it happen)
.outer {
position:relative;
width:400px;
height:600px;
background-color:black;
display: flex;
flex-flow: row wrap;
}
.container {
position:relative;
flex: 1;
display: flex;
flex-direction: column;
}
.d1 {
flex: 1;
background-color: yellow;
}
.d2 {
flex: 1;
background-color: green;
}
.box1 {
display: flex;
flex-flow: row wrap;
align-content: flex-start;
flex: 2; /* temp. adjusted to make it slightly bigger */
position: relative; /* added to make position: absolute relate to this */
}
.box1 .inner { /* added rule to make box1 content scroll */
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
overflow: scroll;
color: white;
background-color: red;
}
.box2 {
color: white;
flex: 12;
background-color: blue;
}
.inbox1 {
flex: 1 100%;
background-color: purple;
}
<div class="outer">
<div class="container">
<div class="box1">
<div class="inner">
<div class="inbox1">
inbox1
</div>
<div class="inbox1">
inbox1
</div>
<div class="inbox1">
inbox1
</div>
<div class="inbox1">
inbox1
</div>
<div class="inbox1">
inbox1
</div>
</div>
</div>
<div class="box2">
</div>
</div>
<div class="d1">
</div>
<div class="d2">
</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