How to set equal width for flex elements? - css

Why blocks .b have different width? How to set it equal?
.parent {
display: flex;
}
.parent>div {
flex: 1 1 auto;
}
.parent .b {
display: flex;
}
<div class="parent">
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div>
Why blocks <div class="cell"> have different width?

Edit: use CSS grid and auto-fit:
.parent {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
}
.parent {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
}
.parent>div {
background-color: lightblue;
margin-left: 5px;
}
<div class="parent">
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
</div>

Second re-edit**
First choice you can do is just set a flex on the parent element as this will only effect the first element below that, which in this case is the cell class, i will add a border on the cell class so you can see this in effect
<div class="parent">
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">
<div class="b"></div>
</div>
<div>
.parent {
display: flex;
width: 70%;
}
.cell {
width: 20%;
height: 100px;
border: 1px solid orange;
}
here you can set the size of your parent width which will be the size across your screen, you can then set the width of the .cell childs and they will all then be the same, but only at a maximum of the parent
** second option you can do
Here is a simpler version, and i have added 3 different classes to show how you can choose the sizing you want
<div class="parent">
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
<div>
.parent {
display: flex;
width: 80%;
height: 100px;
}
.a {
flex: 40%;
border: 1px solid greenyellow;
}
.b {
flex: 20%;
border: 1px solid orange;
}
.c {
flex: 20%;
border: 1px solid blue;
}
Of course you can change them back and have them all be called the same class, and just assign one width and again they will all be the same... i hope this helps

I think they all are in same width. You need to use this css instead of the .parent>div selector
.cell {
flex: 1 1 auto;
}
.parent {
display: flex;
}
.cell {
flex: 1 1 auto;
}
.parent .b {
display: flex;
align-items: center;
justify-content: center;
}
.b {
height: 50px;
}
.cell:nth-child(1) {
background: red;
}
.cell:nth-child(2) {
background: yellow;
}
.cell:nth-child(3) {
background: green;
}
.cell:nth-child(4) {
background: teal;
}
<div class="parent">
<div class="cell">
<div class="b">hi</div>
</div>
<div class="cell">
<div class="b">hi</div>
</div>
<div class="cell">
<div class="b">hi</div>
</div>
<div class="cell">
<div class="b">hi</div>
</div>
<div>

Related

Balancing column width in flexbox and grid

I've got two columns in a parent container of 600px width. The children’s character length dictates the column width (weighted split). However, as both columns become increasingly similar in their width, a balanced (50/50 split) layout should be preferred, illustrated below.
Is it possible to achieve this kind of layout in flexbox or grid, without javascript? I imagine determining string length and switching css properties according to a threshold would be an option that I don't want to go down.
My intention isn't to create a single type of split but rather to make the layout respect both splits conditionally.
.container {
outline: 1px solid red;
width: 100%;
height: 60px;
display: flex;
}
.child {
padding: 0.5px;
outline: 1px solid black;
display: grid;
place-content: center;
}
.grow {
flex-grow: 1; /* flexible split */
}
.balanced {
width: 100%; /* 50-50 split */
}
<div class="container">
<div class="child grow">
asdasdasdasd
</div>
<div class="child grow">
asdaassdasdasdsdasdasd
</div>
</div>
<div class="container">
<div class="child balanced">
asdasdasdasd
</div>
<div class="child balanced">
asdaassdasdasdsdasdasd
</div>
</div>
Just add a maximum width?
.container {
outline: 1px solid red;
width: 100%;
height: 60px;
display: flex;
}
.child {
padding: 0.5px;
outline: 1px solid black;
display: grid;
place-content: center;
}
.grow {
flex-grow: 1;
max-width:50%;
}
.balanced {
width: 100%;
/* 50-50 split */
}
<div class="container">
<div class="child grow">
asdasdasdasd
</div>
<div class="child grow">
asdaassdasdasdsdasdasd
</div>
</div>
<div class="container">
<div class="child balanced">
asdasdasdasd
</div>
<div class="child balanced">
asdaassdasdasdsdasdasd
</div>
</div>
Isn't flex-grow alone solving directly your problem?
See the snippet:
.container {
outline: 1px solid red;
width: 100%;
height: 60px;
display: flex;
}
.child {
padding: 0.5px;
outline: 1px solid black;
display: grid;
flex-grow: 1; /* flexible split */
place-content: center;
}
<div class="container">
<div class="child">
asdasd
</div>
<div class="child">
asdaassdasdasdsdasdasd
</div>
</div>
<div class="container">
<div class="child">
asdasdasdasd
</div>
<div class="child">
asdaassdasdasdsdasdasd
</div>
</div>
<div class="container">
<div class="child">
asdaassdasdasdsdasdasd
</div>
<div class="child">
asdaassdasdasdsdasdasd
</div>
</div>
In the meantime I found the answer.
Setting flex-basis enforces a 50/50 split when column width is similar. The unequal split is respected by setting flex-grow and flex-shrink.
.parent {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 50%;
padding-right: 1em;
padding-left: 1em;
}

How to have make a div take a minumum of 50% space but if no sibling is present take 100%

Simply put I have:
#Container {
display:'flex';
flex-wrap:'wrap';
}
.item {
flex-basis: '50%'
}
Scenario one:
<div id=Container>
<div class="item"></div> 33 %
<div class="item"></div> 33 %
<div class="item"></div> 33%
</div>
Scenario 2
<div id=Container>
<div class="item"></div> 50 %
<div class="item"></div> 50 %
</div>
scenario 3:
<div id=Container>
<div class="item"></div> 100 %
</div>
What I want in general tems is this to be fluid, the more items I put in the less space each item will have but if there is only 1 then I want it to take full space.
First you have to add display: flex; to #Container
#Container{
display: flex;
}
If you want to equally distribute the space between children then you can use flex property as
.item{
flex: 1;
}
Above CSS is minimum required styles, rest is for demo
#Container {
display: flex;
margin-top: 1rem;
}
.item {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
padding: 1rem;
}
.item:nth-child(1) {
background-color: red;
}
.item:nth-child(2) {
background-color: blueviolet;
}
.item:nth-child(3) {
background-color: aquamarine;
}
<div id="Container">
<div class="item">33 %</div>
<div class="item">33 %</div>
<div class="item">33 %</div>
</div>
<div id=Container>
<div class="item"> 50 % </div>
<div class="item"> 50 % </div>
</div>
<div id=Container>
<div class="item">100 %</div>
</div>
I think that this example could give you an idea of how to achieve what you want:
https://codepen.io/Eylen/pen/vYJBpMQ
.Container {
display: flex;
flex-wrap: wrap;
margin-bottom: 8px;
}
.item {
flex-grow: 1;
margin: 0 12px;
background: #f1f1f1;
}
Your main issue in the code that you gave, is that you're missing the flex item behaviour. I have just set that the item can grow to fill the space with the flex-grow:1.
You can make sure a flex child covers up the space if it can, you can provide flex-grow: 1
#Container {
display:flex;
}
.item {
width: 100%;
flex-grow: 1;
border: 1px solid;
text-align: center;
}
<h1> Scenario 1 </h1>
<div id=Container>
<div class="item">33 %</div>
<div class="item">33 %</div>
<div class="item">33%</div>
</div>
<h1> Scenario 2 </h1>
<div id=Container>
<div class="item">50 %</div>
<div class="item">50 %</div>
</div>
<h1> Scenario 3 </h1>
<div id=Container>
<div class="item">100 %</div>
</div>
Added a demo below.
$( document ).ready(function() {
$( "#add" ).click(function() {
$('#container').append('<div class="item"></div>');
});
$( "#remove" ).click(function() {
$('#container').children().last().remove();
});
});
#container {
width:100%;
height:500px;
background-color:#ebebeb;
display:flex;
flex-direction: column;
}
.item {
width:100%;
display: flex;
flex: 1;
border-bottom:1px solid #007cbe;
}
.item1 {
background:#007cbe;
}
.item2 {
background: #d60000;
}
.item3 {
background: #938412
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
<div class="item item1">1</div>
<div class="item item2">2</div>
<div class="item item3">3</div>
</div>
<button id="add"> Add </div>
<button id="remove"> Remove </div>
Apply to the below CSS to fulfill your requirement.
#Container {
display: flex;
}
.item {
width: 100%;
min-height: 100px;
border: 1px solid;
}

How do I mimic floats with flexbox?

I am trying to use flexbox like floats. I would like 1 child to form a column on the right and the remaining children to form another column on the left. I can't add in additional HTML -- I can only work with CSS.
I've figured out how to do this, but I just need both columns to align at the top. My current code has the left column slightly below the right column.
https://jsfiddle.net/o2fbtuLc/
.parent {
display: flex;
flex-wrap: wrap;
flex-direction: column;
}
.child {
max-width: 48%;
}
.right {
margin-left: auto;
}
<div class="parent">
<div class="child right">Right</div>
<div class="child">Left</div>
<div class="child">Left</div>
<div class="child">Left</div>
</div>
You can use order. Also I removed flex-direction: column and added max-width: 100% for elements after second element.
.parent {
display: flex;
flex-wrap: wrap;
}
.child {
width: 100%;
max-width: 48%;
}
.child:nth-child(2) {
order: 1;
}
.child:nth-child(3) {
order: 3;
}
.child:nth-child(4) {
order: 4;
}
.right {
order: 2;
}
.child:nth-child(n + 3) {
max-width: 100%;
}
<div class="parent">
<div class="child right">Right</div>
<div class="child">Left</div>
<div class="child">Left</div>
<div class="child">Left</div>
</div>
If .right is taller, we can consider using grid-area.
.parent {
display: grid;
grid-template-areas: "left1 right"
"left2 right"
"left3 right";
}
.child {
width: 100%;
background: blue;
height: 30px;
}
.child:nth-child(2) {
grid-area: left1;
}
.child:nth-child(3) {
grid-area: left2;
}
.child:nth-child(4) {
grid-area: left3;
}
.right {
background: red;
height: 80px;
grid-area: right;
}
<div class="parent">
<div class="child right">Right</div>
<div class="child">Left</div>
<div class="child">Left</div>
<div class="child">Left</div>
</div>
CSS-Grid can do that:
.parent {
display: grid;
grid-template-columns: auto auto;
grid-auto-flow: column;
}
.child {
max-width: 48%;
grid-column: 1;
border: 1px solid green;
}
.right {
grid-column: 2;
}
<div class="parent">
<div class="child right">Right</div>
<div class="child">Left</div>
<div class="child">Left</div>
<div class="child">Left</div>
<div class="child right">Right</div>
</div>
If you want to avoid grid (IE 11 involved maybe ?) , the old way via the table-display, can do too :
.parent {
display: table;
width: 100%;
direction: rtl;/* alike a flow column reverse here */
text-align: left;
border: solid;
}
.child {
direction: ltr;/* ! reset flow direction ;)*/
border: solid;
}
.right {/* i will also expand if first col is longer than myself */
display: table-cell;
width: 50%;/* set column width here ! left over will be for the other one(s). */
}
/* margins ? */
.bis {border-spacing:2px;}
.bis .child {margin-right:2px;}
.bis .right + .child ~ .child {margin-top:2px;}
.bis .right{text-align:center;vertical-align:middle;
<div class="parent">
<div class="child right">Right</div>
<div class="child">Left</div>
<div class="child">Left</div>
<div class="child">Left</div>
</div>
<hr>
<div class="parent bis">
<div class="child right">possible gaps / VH-align</div>
<div class="child">Left</div>
<div class="child">two<br>lines</div>
<div class="child">Left</div>
</div>
just use flexbox as it was intended!
.parent {
display: flex;
justify-content:space-between;
}
<div class="parent">
<div>
<div class="child">Left</div>
<div class="child">Left</div>
<div class="child">Left</div></div>
<div class="child right">Right</div>
</div>

Vertical scroll bar in div which is a child of css grid column

I am new to CSS grid, I have a nested grid layout page. I could not get a scroll bar for grid child div.fieldsContainer.
html,body,
.wrapper{
height: 100%;
width: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
.wrapper{
display: grid;
grid-template-rows: 50px 1fr 50px;
}
.header{
border: 1px solid #ddd;
background: lightyellow;
}
.footer{
background: lightpink;
}
.content{
display: grid;
grid-template-columns: 250px 1fr 300px;
grid-gap: 10px;
overflow: hidden;
}
.fieldTypes{
display: grid;
grid-template-rows: 40px 1fr;
}
.fieldTypes .search{
border: 1px solid red;
}
.fieldTypes .fieldsContainer{
display: grid;
grid-template-columns: repeat(3, minmax(70px,1fr));
grid-auto-rows: 50px;
grid-gap: 10px;
}
.card{
padding: 10px;
background: #ddd;
}
<div class="wrapper">
<div class="header">
Header
</div>
<div class="content">
<div class="fieldTypes">
<div class="search">search</div>
<div class="fieldsContainer">
<div class="card">1</div>
<div class="card">2</div>
<div class="card">3</div>
<div class="card">4</div>
<div class="card">5</div>
<div class="card">6</div>
<div class="card">7</div>
<div class="card">8</div>
<div class="card">9</div>
<div class="card">10</div>
<div class="card">11</div>
<div class="card">12</div>
<div class="card">10</div>
<div class="card">11</div>
<div class="card">12</div>
<div class="card">10</div>
<div class="card">11</div>
<div class="card">12</div>
</div>
</div>
<div class="inndercontent">
innder content
</div>
<div class="graphs">
graphs
</div>
</div>
<div class="footer">
Footer
</div>
</div>
One solution would be to set overflow-y:auto on the parent ( .fieldTypes ) and overflow-y:scroll on .fieldsContainer
There is no ' story ' behind this. Just that you have to set a default overflow for the parent to accept it, and then specify overflow-y:scroll( as you want vertical scroll ) on the child.
html,body,
.wrapper{
height: 100%;
width: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
.wrapper{
display: grid;
grid-template-rows: 50px 1fr 50px;
}
.header{
border: 1px solid #ddd;
background: lightyellow;
}
.footer{
background: lightpink;
}
.content{
display: grid;
grid-template-columns: 250px 1fr 300px;
grid-gap: 10px;
overflow: hidden;
}
.fieldTypes{
display: grid;
grid-template-rows: 40px 1fr;
overflow-y:auto;/*added*/
}
.fieldTypes .search{
border: 1px solid red;
}
.fieldTypes .fieldsContainer{
display: grid;
grid-template-columns: repeat(3, minmax(70px,1fr));
grid-auto-rows: 50px;
grid-gap: 10px;
overflow-y:scroll;/*added*/
}
.card{
padding: 10px;
background: #ddd;
}
<div class="wrapper">
<div class="header">
Header
</div>
<div class="content">
<div class="fieldTypes">
<div class="search">search</div>
<div class="fieldsContainer">
<div class="card">1</div>
<div class="card">2</div>
<div class="card">3</div>
<div class="card">4</div>
<div class="card">5</div>
<div class="card">6</div>
<div class="card">7</div>
<div class="card">8</div>
<div class="card">9</div>
<div class="card">10</div>
<div class="card">11</div>
<div class="card">12</div>
<div class="card">10</div>
<div class="card">11</div>
<div class="card">12</div>
<div class="card">10</div>
<div class="card">11</div>
<div class="card">12</div>
</div>
</div>
<div class="inndercontent">
innder content
</div>
<div class="graphs">
graphs
</div>
</div>
<div class="footer">
Footer
</div>
</div>
Here's a more reduced case (to cut through the irrelevant parts)
html, body, .A {
height: 100%; /* matters */
width: 100%;
margin: 0;
padding: 0;
}
.A {
max-height: 300px; /* matters */
display: grid; /* matters */
overflow: hidden; /* matters */
}
.B {
display: grid; /* matters */
overflow-y: auto; /* matters */
}
.D {
overflow-y: scroll; /* matters */
}
.C {
padding: 10px;
background-color: #07f;
}
.E {
padding: 10px;
background-color: #eee;
}
<div class="A">
<div class="B">
<div class="C">search</div>
<div class="D">
<div class="E">1</div>
<div class="E">2</div>
<div class="E">3</div>
<div class="E">4</div>
<div class="E">5</div>
<div class="E">6</div>
<div class="E">7</div>
<div class="E">8</div>
<div class="E">9</div>
<div class="E">10</div>
<div class="E">11</div>
<div class="E">12</div>
<div class="E">10</div>
<div class="E">11</div>
<div class="E">12</div>
<div class="E">10</div>
<div class="E">11</div>
<div class="E">12</div>
</div>
</div>
</div>
Set the parent's height to 100vh. Then overflow-y: scroll will work on the children.
See this example (based on the reduced case answer).
html, body, .A {
margin: 0;
padding: 0;
}
.A {
height: 100vh; /* matters */
display: grid; /* matters */
}
.B {
padding: 10px;
background-color: #07f;
}
.C {
overflow-y: scroll; /* matters */
}
.D {
padding: 10px;
background-color: #eee;
}
<div class="A">
<div class="B">search</div>
<div class="C">
<div class="D">1</div>
<div class="D">2</div>
<div class="D">3</div>
<div class="D">4</div>
<div class="D">5</div>
<div class="D">6</div>
<div class="D">7</div>
<div class="D">8</div>
<div class="D">9</div>
<div class="D">10</div>
<div class="D">11</div>
<div class="D">12</div>
<div class="D">10</div>
<div class="D">11</div>
<div class="D">12</div>
<div class="D">10</div>
<div class="D">11</div>
<div class="D">12</div>
</div>
</div>

Verticaly centered equal height columns when some divs are nested?

I need equal height columns which vertically centre there content. When each column div is a direct descendant of a container this is easy to do with display table: http://codepen.io/anon/pen/XKzOrv
However I have nested divs. Is it still possible to achieve this layout without modifying my markup?
UPDATE - As I'm supporting IE9+ I cant use flexbox.
.cont {
width: 500px;
}
.depth1 {
width: 50%;
float: left;
display: table;
}
.depth2 {
display: table-cell;
width: 50%;
vertical-align: middle;
}
.a {
background: blue;
}
.b {
background: green;
}
.c {
background: orange;
}
.d {
background: grey;
}
<div class="cont">
<div class="depth1">
<div class="depth2 a">
A
</div>
<div class="depth2 b">
B
<br>Wrap
</div>
</div>
<div class="depth1">
<div class="depth2 c">
C
<br>
<br>
<br>Wrap
</div>
<div class="depth2 d">
D
</div>
</div>
</div>
Yes it is possible with Flexbox, just use display: flex on all child div elements except on .c and add align-items: center on .depth2
.cont {
width: 500px;
display: flex;
}
.depth1 {
width: 50%;
display: flex;
}
.depth2 {
width: 50%;
}
.depth2:not(.c) {
display: flex;
align-items: center;
}
.a {
background: blue;
}
.b {
background: green;
}
.c {
background: orange;
}
.d {
background: grey;
}
<div class="cont">
<div class="depth1">
<div class="depth2 a">
A
</div>
<div class="depth2 b">
B
<br>Wrap
</div>
</div>
<div class="depth1">
<div class="depth2 c">
C
<br>
<br>
<br>Wrap
</div>
<div class="depth2 d">
D
</div>
</div>
</div>

Resources