Flexbox items of same size - html

How can I force flexbox items to have same height.
In examples I found online, people are using align-items: stretch css property, but my example is more complex.
Here is a codepen example:
.container {
background-color: red;
display: flex;
align-items: stretch;
}
.boxes {
background-color: yellow;
margin: 5px;
display: flex;
}
.boxes-column {
flex-direction: column;
}
.box {
background-color: green;
width: 100px;
margin: 5px;
}
.heading {
background-color: pink;
}
<body>
<div class="container">
<div class="boxes boxes-column">
<div class="heading">This is heading</div>
<div class="boxes">
<div class="box">Content content content content content content content</div>
<div class="box">Content content</div>
<div class="box">Content</div>
<div class="box">Contento contento</div>
<div class="box">Cc</div>
<div class="box">Contetno contento contento</div>
</div>
</div>
<div class="boxes boxes-column">
<div class="heading">This is heading 2</div>
<div class="boxes">
<div class="box">Content</div>
<div class="box">Contentno Contetn</div>
<div class="box">C</div>
</div>
</div>
</div>
</body>
Height of items items below 'Heading' and height of items below 'Heading 2' should be equal.

Used this css and now the boxes have the same height:
.container > .boxes > .boxes {
flex: 1;
}
Take a look at the below snippet:
.container {
background-color: red;
display: flex;
align-items: stretch;
}
.boxes {
background-color: yellow;
margin: 5px;
display: flex;
}
.boxes-column {
flex-direction: column;
}
.box {
background-color: green;
width: 100px;
margin: 5px;
}
.heading {
background-color: pink;
}
.container > .boxes > .boxes {
flex: 1;
}
<body>
<div class="container">
<div class="boxes boxes-column">
<div class="heading">This is heading</div>
<div class="boxes">
<div class="box">Content content content content content content content</div>
<div class="box">Content content</div>
<div class="box">Content</div>
<div class="box">Contento contento</div>
<div class="box">Cc</div>
<div class="box">Contetno contento contento</div>
</div>
</div>
<div class="boxes boxes-column">
<div class="heading">This is heading 2</div>
<div class="boxes">
<div class="box">Content</div>
<div class="box">Contentno Contetn</div>
<div class="box">C</div>
</div>
</div>
</div>
</body>

Related

Properly calculating flex-basis taking into account gap and margins [duplicate]

I am currently learning Flexbox Layout and I can not find a solution to my problem.
I tried with justify-content and flex-basis but it does not work. Does anyone have the solution ?
The result I would like :
section {
display: flex;
margin: 0 auto;
justify-content: space-between;
}
.column {
width: 100%;
background-color: #e2e2e2;
padding: 1%;
margin: 1%;
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
#first {
flex-grow: 2;
flex-shrink: 2;
flex-basis: 0;
}
<section>
<div class="column" id="first">First</div>
<div class="column" id="second">Second</div>
<div class="column">Third</div>
</section>
<section>
<div class="column">First</div>
<div class="column">Second</div>
<div class="column">Third</div>
<div class="column">Fourth</div>
</section>
https://jsfiddle.net/qdsbacvn/
This is a perfect use case for CSS grid where you don't need a lot of complex code:
section {
display: grid;
margin: 2% auto;
grid-gap:2%;
grid-template-columns:repeat(4,1fr);
}
.column {
background-color: #e2e2e2;
padding: 5px;
}
#first {
grid-column:span 2;
}
<section>
<div class="column" id="first">First</div>
<div class="column" id="second">Second</div>
<div class="column">Third</div>
</section>
<section>
<div class="column">First</div>
<div class="column">Second</div>
<div class="column">Third</div>
<div class="column">Fourth</div>
</section>
With flexbox you can try the following:
section {
display: flex;
}
.column {
background-color: #e2e2e2;
padding: 1%;
margin: 1%;
flex-grow: 1;
flex-basis: 0;
}
#first {
flex-grow: 2;
flex-basis:4%; /*2 x (padding + margin)*/
}
<section>
<div class="column" id="first">First</div>
<div class="column" id="second">Second</div>
<div class="column">Third</div>
</section>
<section>
<div class="column">First</div>
<div class="column">Second</div>
<div class="column">Third</div>
<div class="column">Fourth</div>
</section>
Since your are using flex-basis:0 only padding/margin are considered before calculating the free space. The trick is to make sure we have the same free space in both situation thus we add to flex-basis of the big element the margin/padding that aren't present in the first case.
A bit overkill for your use case but a much more robust solution in case you need to add more rows or your margins need to change size.
.parent {
display: flex;
flex-direction:row;
}
.column {
flex:1;
display:flex;
flex-direction:column
}
.column:first-child {
flex:2;
}
.col-row {
flex:1;
display:flex;
flex-direction:row;
}
.col-row > div{
flex:1;
display:flex;
flex-direction:row;
margin:1vw;
padding:1vw;
background-color: #e2e2e2;
}
<div class="parent">
<div class="column">
<div class="col-row">
<div>First</div>
</div>
<div class="col-row">
<div>First</div>
<div>Second</div>
</div>
</div>
<div class="column">
<div class="col-row">
<div>Second</div>
</div>
<div class="col-row">
<div>Third</div>
</div>
</div>
<div class="column">
<div class="col-row">
<div>Third</div>
</div>
<div class="col-row">
<div>Fourth</div>
</div>
</div>
</div>
Check my code. I have increased slightly the flex box value.
section {
display: flex;
margin: 0 auto;
justify-content: space-between;
}
.column {
width: 100%;
background-color: #e2e2e2;
padding: 1%;
margin: 1%;
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
#first {
flex-grow: 2.2;
flex-shrink: 2;
flex-basis: 0;
}
<section>
<div class="column" id="first">First</div>
<div class="column">Second</div>
<div class="column">Third</div>
</section>
<section>
<div class="column">First</div>
<div class="column">Second</div>
<div class="column">Third</div>
<div class="column">Fourth</div>
</section>

How to get nested css flex to have the right width after wrap in this setup?

I have this mockup, there are some nested containers. some of the link-class have multiple elements (par and ref) and I want them to display next to each other if there's space, but responsively move them below each other when total width gets smaller.
It works somewhat, but I expect (want) the link-element containing two childs to return to the same width as the link-element with one single child as it wraps.
For some reason, it remains wider than the single-child ones.
Any hints appreciated!
Code:
let name = 'world';
:global(body) {
margin: 0;
padding: 0
}
.main {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
background-color: gray;
}
.Container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: lightblue;
padding: 3px
}
.linkContainer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 3px;
background-color: salmon;
}
.par {
width: 80vw;
max-width: 300px;
background-color: red
}
.links {
display: flex;
flex-flow: row wrap;
padding: 3px;
background-color: orange
}
.ref {
background-color: olive;
width: 30vw;
max-width: 100px
}
.item {
width: 80vw;
max-width: 300px;
background-color: steelblue
}
<div class="main">
<div class="Container">
<div class="item">
header
</div>
<div class="linkContainer">
<div class="links">
<div class="par">
some text
</div>
</div>
<div class="links">
<div class="par">
some text
</div>
</div>
<div class="links">
<div class="par">
some text
</div>
</div>
<div class="Container">
<div class="item">
another header
</div>
<div class="linkContainer">
<div class="links">
<div class="par">
some text
</div>
<div class="ref">
a ref
</div>
</div>
<div class="links">
<div class="par">
some text
</div>
</div>
<div class="links">
<div class="par">
some text
</div>
<div class="ref">
a ref
</div>
</div>
</div>
</div>
</div>
</div>
</div>
you could simply add a max-width:300px; to .links and have the box in size but then you couldn't have the desired stacking effect you wanted so i went a bit further and with the help of css variables and media queries and adding a class .single to single .pars which didn't have a .ref after them, i came up with this:
:root {
--ref-size: 100px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.main {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
background-color: gray;
}
.Container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: lightblue;
padding: 3px
}
.links {
min-width: 300px;
display: flex;
flex-flow: row wrap;
padding: 3px;
background-color: orange;
}
.par {
width: calc(100% - var(--ref-size));
background-color: red;
}
.ref {
background-color: olive;
width: var(--ref-size);
}
.item {
width: 80vw;
max-width: 300px;
background-color: steelblue
}
#media all and (max-width:300px){
.par{
width: 100%;
}
}
#media all and (min-width: 300px){
.par.single{
width: 100%;
}
}
<div class="main">
<div class="Container">
<div class="item links">
header
</div>
<div class="links">
<div class="par single">
some text
</div>
</div>
<div class="links">
<div class="par single">
some text
</div>
</div>
<div class="links">
<div class="par single">
some text
</div>
</div>
<div class="item links">
another header
</div>
<div class="links">
<div class="par">
some text
</div>
<div class="ref">
a ref
</div>
</div>
<div class="links">
<div class="par single">
some text
</div>
</div>
<div class="links">
<div class="par">
some text
</div>
<div class="ref">
a ref
</div>
</div>
</div>
</div>

How to equally space empty divs with CSS only in flex?

So I have a structure pretty similar to the snippet below.
The issue I have is that I am trying to make it so that the divs such as child always take the same height relative to the container even if they are empty. So if there are two children they have to be 50% of the parent if there are three children 33.3% of the parent and ec.
Did a lot of digging, tried usingflex-grow and setting it on the children, adding an after content on the childContent class if it was empty but the empty children still collapse.
Is it even possible to achieve equal heights on the children without using js and fixed heights and if yes how?
.container {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
overflow: auto;
}
.child {
height: 100%;
display: flex;
flex-direction: column;
}
.childHeader {
display: flex;
flex-direction: row;
}
.headerItem {
background-color: red;
}
.childContent {
background-color: white;
}
.childContent:empty:after {
content: '.';
visibility: hidden;
min-height: 300px;
}
.contentItem {
background-color: skyblue;
border: 3px solid black;
}
<div class="container">
<div class="child">
<div class="childHeader">
<div class="headerItem">1</div>
<div class="headerItem">2</div>
<div class="headerItem">3</div>
<div class="headerItem">4</div>
<div class="headerItem">5</div>
<div class="headerItem">6</div>
<div class="headerItem">7</div>
</div>
<div class="childContent">
<div class="contentItem">1</div>
<div class="contentItem">2</div>
<div class="contentItem">3</div>
<div class="contentItem">4</div>
<div class="contentItem">5</div>
<div class="contentItem">6</div>
<div class="contentItem">7</div>
</div>
</div>
<div class="child">
<div class="childHeader">
<div class="headerItem">1</div>
<div class="headerItem">2</div>
<div class="headerItem">3</div>
<div class="headerItem">4</div>
<div class="headerItem">5</div>
<div class="headerItem">6</div>
<div class="headerItem">7</div>
</div>
<div class="childContent">
</div>
</div>
<div class="child">
<div class="childHeader">
<div class="headerItem">1</div>
<div class="headerItem">2</div>
<div class="headerItem">3</div>
<div class="headerItem">4</div>
<div class="headerItem">5</div>
<div class="headerItem">6</div>
<div class="headerItem">7</div>
</div>
<div class="childContent">
</div>
</div>
</div>
Check this out, I'm not really sure if this is what you want to do.
I just added min-height: calc(100vh - 60px); in your .childContent
.container {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
overflow: auto;
}
.child {
display: flex;
flex-direction: column;
}
.childHeader {
display: flex;
flex-direction: row;
}
.headerItem {
display:flex;
flex-basis:100%;
background-color: red;
}
.childContent {
background-color: grey;
position: relative;
display: block;
min-height: calc(80vh - 60px);
}
.childContent:empty::after {
content: '.';
visibility: hidden;
}
.contentItem {
background-color: skyblue;
border: 3px solid black;
}
<div class="container">
<div class="child">
<div class="childHeader">
<div class="headerItem">1</div>
<div class="headerItem">2</div>
<div class="headerItem">3</div>
<div class="headerItem">4</div>
<div class="headerItem">5</div>
<div class="headerItem">6</div>
<div class="headerItem">7</div>
</div>
<div class="childContent">
<div class="contentItem">1</div>
<div class="contentItem">2</div>
<div class="contentItem">3</div>
<div class="contentItem">4</div>
<div class="contentItem">5</div>
<div class="contentItem">6</div>
<div class="contentItem">7</div>
</div>
</div>
<div class="child">
<div class="childHeader">
<div class="headerItem">1</div>
<div class="headerItem">2</div>
<div class="headerItem">3</div>
<div class="headerItem">4</div>
<div class="headerItem">5</div>
<div class="headerItem">6</div>
<div class="headerItem">7</div>
</div>
<div class="childContent">
</div>
</div>
<div class="child">
<div class="childHeader">
<div class="headerItem">1</div>
<div class="headerItem">2</div>
<div class="headerItem">3</div>
<div class="headerItem">4</div>
<div class="headerItem">5</div>
<div class="headerItem">6</div>
<div class="headerItem">7</div>
</div>
<div class="childContent">
</div>
</div>
</div>
Check this one out https://developer.mozilla.org/en-US/docs/Web/CSS/calc

overflow-y either auto or scroll bar does not allow showing all overflow content

I have a dummy screen with background image. The background image correctly expands or contracts with the size of the viewport. I have dummy flexbox content that I intentionally make overflow the bottom of the page.
The scrollbar correctly appears, but it will not scroll far enough to show all the content that overflowed.
Apologies: the content is varied so I can tell what IS NOT showing.
Dummy header menu bar is fine.. it is supposed to scroll up - and it does.
CSS:
html {
box-sizing: border-box;
}
body {
box-sizing: border-box;
overflow-y: auto;
min-height: 100vh;
width: 100%;
margin: 0; padding: 0; border: 0; cursor: default
}
ul {
list-style: none;
li {
display: inline;
margin-left: 50px;
margin-top: 50px;
}
}
.blockStyleEven {
display: flex;
flex-direction: row;
color: white;
justify-content: space-evenly;
}
.blockSpaceAround {
display: flex;
flex-direction: row;
color: white;
justify-content: space-around;
}
.blockSpaceBetween {
display: flex;
flex-direction: row;
color: white;
justify-content: space-between;
}
.blockStart {
display: flex;
flex-direction: row;
color: white;
justify-content: flex-start;
}
.blockEnd {
display: flex;
flex-direction: row;
color: white;
justify-content: flex-end;
}
.blockCenter {
display: flex;
flex-direction: row;
color: white;
justify-content: center;
}
.maroon {
width: 100px;
height: 100px;
background-color: maroon;
}
.red {
width: 100px;
height: 100px;
background-color: red;
}
.green {
width: 100px;
height: 100px;
background-color: green;
}
.blue {
width: 100px;
height: 100px;
background-color: blue;
}
.workspace {
background: url("././Features.jpg") no-repeat center center fixed;
background-size: cover;
height: 100vh;
width: 100vw;
overflow: hidden;
h1 {
color: #E0B228;
}
h2 {
color: #2856E0;
}
}
HTML:
<div [ngStyle]="{'width': '100vw', 'height': '100vh'}">
<div [ngStyle]="{'display': 'flex', 'flex-direction': 'column'}">
<div [ngStyle]="{'background-color': 'beige'}">
<ul>
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
</div>
<div class="workspace">
<div class="blockStyleEven">
<div class="maroon">space-evenly</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockSpaceAround">
<div class="maroon">space-around</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockSpaceBetween">
<div class="maroon">space-between</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockStart">
<div class="maroon">start</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockEnd">
<div class="maroon">end</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockCenter">
<div class="maroon">center</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockStyleEven">
<div class="maroon">space-evenly</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockSpaceAround">
<div class="maroon">space-around</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockSpaceBetween">
<div class="maroon">space-between</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockStart">
<div class="maroon">start</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockEnd">
<div class="maroon">end</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockCenter">
<div class="maroon">center</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
</div>
</div>
</div>
Thanks in advance.
Yogi
Finally figured it out. The problem was the scrollbar was "too short" to show all the content. This was because my workspace class was on a div below the dummy menu bar. When I put the workspace (containing Margin: auto) on the outer move div, it worked perfectly.
Thanks for all your help.
Apologies for the earlier poor formatting, which has now been cleaned up.
Yogi

adding border to flex items in a row aligned to baseline

Question: How can I get a border to stretch to the height of the parent and surround child cell. Given I am using flexbox and aligning to baseline.
Can this be done with all css?
More Details:
I am using flex box to align my items in each row to a certain baseline. It is centered on each cell under "center here" in the following picture:
When I hover currently on each item it hovers with a solid line with a 10px margin around each cell:
I want the on hover border to stretch to the top and bottom of the row on hover like this:
That way when I hover on each item, their hover border boxes would line up like this:
^ this is what I would like it to look like if I turn hover on, on each cell.
codepen
/* on hover i want this to be a box around the item, and to have the top and the bottom of the border be touching the top/bottom of the row it is on */
.flex-item:hover {
border: 1px solid darkred;
}
/* so item doesn't move when not hovering */
.flex-item {
border: 1px solid lightblue;
}
.flex-container {
overflow: hidden; position: relative;
display: -webkit-flex;
display: flex;
-webkit-align-items: baseline;
align-items: baseline;
width: 400px;
height: 350px;
background-color: lightblue;
flex-wrap: wrap;
padding: 10px;
}
.inner-wrapper {
display: inline-block;
text-align: center;
width: 100px;
margin: 10px;
background-color: cornflowerblue;
}
.flex-body {
border-bottom: 1px solid #fff;
}
.flex-body-more {
float: left;
clear: left;
width: 100%;
}
.flex-img {
justify-content: center;
align-items: center;
}
<div class="flex-container">
<div class="flex-item">
<div class="inner-wrapper">
<div class="flex-title">flex title1</div>
<div class="flex-img">
<img src='http://dummyimage.com/90x40/000/ffffff&text=hi'>
</div>
<div class="flex-body">center here</div>
<div class="flex-body-more">more text</div>
</div>
</div>
<div class="flex-item">
<div class="inner-wrapper">
<div class="flex-title">flex title1 longer title</div>
<div class="flex-img">
<img src='http://dummyimage.com/40x40/000/ffffff&text=hi'>
</div>
<div class="flex-body">center here</div>
<div class="flex-body-more">more text</div>
</div>
</div>
<div class="flex-item">
<div class="inner-wrapper">
<div class="flex-title">flex title1</div>
<div class="flex-img">
<img src='http://dummyimage.com/40x90/000/ffffff&text=hi'>
</div>
<div class="flex-body">center here</div>
<div class="flex-body-more">more text more text more text</div>
</div>
</div>
<div class="flex-item">
<div class="inner-wrapper">
<div class="flex-title">flex title1</div>
<div class="flex-img">
<img src='http://dummyimage.com/90x40/000/ffffff&text=hi'>
</div>
<div class="flex-body">center here</div>
<div class="flex-body-more">more text</div>
</div>
</div>
<div class="flex-item">
<div class="inner-wrapper">
<div class="flex-title">flex title1</div>
<div class="flex-img">
<img src='http://dummyimage.com/40x50/000/ffffff&text=hi'>
</div>
<div class="flex-body">center here</div>
<div class="flex-body-more">more text</div>
</div>
</div>
</div>
Just a few rules that you'll need to adjust to your flex items:
.flex-item {
border: 1px solid lightblue;
transition: .7s;
display: flex;
align-items: flex-end;
}
.flex-container {
overflow: hidden;
position: relative;
display: -webkit-flex;
display: flex;
width: 400px;
height: 350px;
background-color: lightblue;
flex-wrap: wrap;
padding: 10px;
justify-content: flex-start;
}
See code snippet below:
/* on hover i want this to be a box around the item, and to have the top and the bottom of the border be touching the top/bottom of the row it is on */
.flex-item:hover {
border: 1px solid darkred;
}
/* so item doesn't move when not hovering */
.flex-item {
border: 1px solid lightblue;
transition: .7s;
display: flex;
align-items: flex-end;
}
.flex-container {
overflow: hidden;
position: relative;
display: -webkit-flex;
display: flex;
width: 400px;
height: 350px;
background-color: lightblue;
flex-wrap: wrap;
padding: 10px;
justify-content: flex-start;
}
.inner-wrapper {
display: inline-block;
text-align: center;
width: 100px;
margin: 10px;
background-color: cornflowerblue;
}
.flex-body {
border-bottom: 1px solid #fff;
}
.flex-body-more {
float: left;
clear: left;
width: 100%;
}
.flex-img {
justify-content: center;
align-items: center;
}
<div class="flex-container">
<div class="flex-item">
<div class="inner-wrapper">
<div class="flex-title">flex title1</div>
<div class="flex-img">
<img src='http://dummyimage.com/90x40/000/ffffff&text=hi'>
</div>
<div class="flex-body">center here</div>
<div class="flex-body-more">more text</div>
</div>
</div>
<div class="flex-item">
<div class="inner-wrapper">
<div class="flex-title">flex title1 longer title</div>
<div class="flex-img">
<img src='http://dummyimage.com/40x40/000/ffffff&text=hi'>
</div>
<div class="flex-body">center here</div>
<div class="flex-body-more">more text</div>
</div>
</div>
<div class="flex-item">
<div class="inner-wrapper">
<div class="flex-title">flex title1</div>
<div class="flex-img">
<img src='http://dummyimage.com/40x90/000/ffffff&text=hi'>
</div>
<div class="flex-body">center here</div>
<div class="flex-body-more">more text more text more text</div>
</div>
</div>
<div class="flex-item">
<div class="inner-wrapper">
<div class="flex-title">flex title1</div>
<div class="flex-img">
<img src='http://dummyimage.com/90x40/000/ffffff&text=hi'>
</div>
<div class="flex-body">center here</div>
<div class="flex-body-more">more text</div>
</div>
</div>
<div class="flex-item">
<div class="inner-wrapper">
<div class="flex-title">flex title1</div>
<div class="flex-img">
<img src='http://dummyimage.com/40x50/000/ffffff&text=hi'>
</div>
<div class="flex-body">center here</div>
<div class="flex-body-more">more text</div>
</div>
</div>
</div>