I need columns that will have the same height, so I used flex (I use bootstrap framework).
I know that flex work can be seen in the attached picture, but the height of the boxes is not the same, by the fact that one is less text than the other.
I want class inner-div to match to the height of col-md-4.
Can someone help me adjust the height so that it is always the same?
.col-md-4 {
border: 1px solid black;
}
.row-eq-height {
display: flex;
}
.inner-div {
border: 1px solid red;
}
<div class="container">
<div class="row row-eq-height">
<div class="col-md-4">
ddddddsadddddddsadddddddsadddddddsa
<br>ddddddsadddddddsadddddddsadddddddsa
<br>ddddddsadddddddsadddddddsadddddddsa
<br>
<div class="inner-div">
adsadadadada
</div>
</div>
<div class="col-md-4">
ddddddsadddddddsadddddddsadddddddsa
<div class="inner-div">
asdadadaada
</div>
</div>
<div class="col-md-4">
ddddddsadddddddsadddddddsadddddddsa
<br>ddddddsadddddddsadddddddsadddddddsa
<br>ddddddsadddddddsadddddddsadddddddsa
<br>
<div class="inner-div">
asdadaadas
</div>
</div>
</div>
</div>
The problem is that .inner-div is not a flex item, so it doesn't accept flex properties.
Flex layout works only within a parent-child relationship. .row-eq-height is a flex container because you've given it display: flex. This means that .col-md-4 is a flex item, because it's the child of .row-eq-height.
Looking at your images (the highlighted section), you'll see that flex equal height columns are actually working. Each .col-md-4 container is the same height.
However, the children of .col-md-4 are not flex items. They are normal elements in a block, not flex, formatting context.
The solution is to make .col-md-4 a flex container so flex properties can be applied to .inner-div.
.row-eq-height {
display: flex;
}
.col-md-4 {
display: flex;
flex-direction: column;
border: 1px solid black;
}
.inner-div {
flex: 1;
border: 1px solid red;
}
<div class="row row-eq-height">
<div class="col-md-4">
ddddddsadddddddsadddddddsadddddddsa
<br>ddddddsadddddddsadddddddsadddddddsa
<br>ddddddsadddddddsadddddddsadddddddsa
<br>
<div class="inner-div">
adsadadadada
</div>
</div>
<div class="col-md-4">
ddddddsadddddddsadddddddsadddddddsa
<div class="inner-div">
asdadadaada
</div>
</div>
<div class="col-md-4">
ddddddsadddddddsadddddddsadddddddsa
<br>ddddddsadddddddsadddddddsadddddddsa
<br>ddddddsadddddddsadddddddsadddddddsa
<br>
<div class="inner-div">
asdadaadas
</div>
</div>
</div>
It's simple.
When you want to set the inner-div's height to it's parent's height, set the inner-div to display:flex and flex-grow:1. It will take up the height of the parent.
Additionally you can set align-items: stretch to the parent div. This makes all the inner divs to stretch out to what the parent has.
Hope it works for you.
I think you are looking for a solution like this: https://jsfiddle.net/Lddyn573/4/
I set the height of the box-header to calc(100% -24px), 24px is the height of the bottom div.
/* CSS used here will be applied after bootstrap.css */
.col-md-4 {
border: 1px solid black;
padding: 10px;
}
.row-eq-height {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.box-header{
height: calc(100% - 24px);
border: 1px solid green;
}
.box-content {
border: 1px solid red;
}
Related
In CSS, if a child of a child is set to width: 100% and the wrapping div has display: flex set, the content does not expand to 100% it only uses the space of the content.
How would one make it expand to the size the grandchild sets itself but still use flex?
flex-grow is probably not the answer since this will always expand to take up the full space and not respect the size the grandchild sets itself.
See following example:
.wrapperFlex, .wrapperBlock{
border: 1px solid silver;
}
.wrapperFlex {
display: flex;
}
.levelOne {
}
.levelOneGrow {
flex-grow: 1;
}
.levelTwo, .levelTwoFullWidth {
color: white;
background-color: blue;
}
.levelTwoFullWidth {
width: 100%;
}
.levelOnePassthrough{
display: contents;
}
<!-- Premise -->
<div class="wrapperFlex">
<div>PRE</div>
<div class="levelOne">
<div class="levelTwoFullWidth">
WRAPPER FLEX
</div>
</div>
<div>AFTER</div>
</div>
<br/>
<!-- Not what is wanted, the grandchild here does not actually expand to 100%
it should be only as wide as the content here -->
<div class="wrapperFlex">
<div>PRE</div>
<div class="levelOneGrow">
<div class="levelTwo">
WRAPPER FLEX GROW
</div>
</div>
<div>AFTER</div>
</div>
<br/>
<!-- What is wanted but not possible, display: contents is not commonly available -->
<div class="wrapperFlex">
<div>PRE</div>
<div class="levelOnePassthrough">
<div class="levelTwoFullWidth ">
WRAPPER FLEX PASSTHROUGH
</div>
</div>
<div>AFTER</div>
</div>
Can you set flex-basis to the child?
.wrapperFlex, .wrapperBlock{
border: 1px solid silver;
}
.wrapperFlex {
display: flex;
}
.wrapperBlock {
display: block;
}
.levelOne {
flex-basis: 100%; /* Set flex-basis to 100% */
}
.levelTwo {
color: white;
width: 100%;
background-color: blue;
}
<div class="wrapperFlex">
<div class="levelOne">
<div class="levelTwo">
WRAPPER FLEX
</div>
</div>
</div>
<br/>
<div class="wrapperBlock">
<div class="levelOne">
<div class="levelTwo">
WRAPPER BLOCK
</div>
</div>
</div>
set .levelOne {width:100%} ,if im not misunderstanding you.
You need to add the flex property as one to the child i.e levelOne like this flex:1;.
It will work properly as you check here.
.wrapperFlex, .wrapperBlock{
border: 1px solid silver;
}
.wrapperFlex {
display: flex;
}
.wrapperBlock {
display: block;
}
.levelOne {
flex:1;
}
.levelTwo {
color: white;
width: 100%;
background-color: blue;
}
<div class="wrapperFlex">
<div class="levelOne">
<div class="levelTwo">
WRAPPER FLEX
</div>
</div>
</div>
<br/>
<div class="wrapperBlock">
<div class="levelOne">
<div class="levelTwo">
WRAPPER BLOCK
</div>
</div>
</div>
I need my two blocks to go in a row one after another, but when the screen resolution decreases, they are placed under each other, that is, in the column
<div>
<div>
<h1>Block1</h1>
</div>
<div>
<h1>Block2</h1>
</div>
</div>
We can use flex (by default flex-direction is row so we don't need any other styling in css) -:
<div class="container">
<div>
<h1>Block1</h1>
</div>
<div>
<h1>Block2</h1>
</div>
</div>
.container{
display: flex;
}
Also this is one way of doing things, flex is not supported everywhere so you can go for inline-block also -:
<div>
<div class="inline">
<h1>Block1</h1>
</div>
<div class="inline">
<h1>Block2</h1>
</div>
</div>
.inline{
display: inline-block;
}
As the div element is known as a block element, you need to use display:inline-block. This means 'if there is space next to the element, place the next inline block element next to it' (in essence).
div {
display: inline-block;
background:tomato;
}
#media only screen and (max-width: 600px) {
div{
display:block;
background:green;
}
<div>
<div>1
</div>
<div>2
</div>
</div>
For your width to then turn back into a block element, you will need to use the media query - something like above.
You should use CSS grid:
<div class="wrapper">
<div>
<h1>Block1</h1>
</div>
<div>
<h1>Block2</h1>
</div>
</div>
Css:
.wrapper{
diplay: grid;
grid-template-columns: 1fr;
}
Try using display:flex and use flexbox to place next to each other when the width is high. When the width reduces the div cols will go down.
.row {
width: 100vw;
display: flex;
flex-wrap: wrap;
}
.cols {
height: 400px;
width: 400px;
margin: 5px 5px 5px 5px;
background-color: blue;
}
<div class="row">
<div class="cols">
</div>
<div class="cols">
</div>
</div>
Like this:
#media all and (max-width: 480px) {
div{
float: left;
width: 98%;
margin-left: 1%;
overflow: hidden;
border: 1px solid #000;
box-sizing: border-box;
padding: 5px;
}
}
Or with class
.wrapper div{
...
}
More about #media
https://developer.mozilla.org/pl/docs/Web/CSS/Media_Queries/Using_media_queries
I have a header with 2 rows of 2 Foundation columns of content, as below:
<div class="wrapper">
<div class="header row">
<div class="large-6 columns">
HEADER
</div>
<div class="large-6 columns">
menu
</div>
</div>
<div class="row">
<div class="large-5 none show-for-medium columns info">
Some information to the left
</div>
<div class="large-7 columns">
<div class="image-container">
<div class="image">
image to the right
</div>
</div>
</div>
</div>
</div>
The .header height is dynamic and not set. I want the .image element to take up 100% of the remaining vertical space.
eg:
To that affect I have tried using flex and flex-grow, eg:
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
}
.image-container {
flex-grow: 1;
}
but had no luck, see fiddle: https://jsfiddle.net/9kkb2bxu/46/
Would anyone know how I could negate the dynamic height of the header from the 100vh of the image container?
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
border: 1px solid black;
background-color: #ccc;
}
.row {
width: 100%;
}
.header {
background-color: green;
}
.info {
background-color: yellow;
border: 1px solid #ccc;
}
.image-container {
border: 1px solid black;
display: flex;
}
.image {
background-color: red;
flex-grow: 1;
width: 100%;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css" rel="stylesheet"/>
<div class="wrapper">
<div class="header row">
<div class="large-6 columns">
<h1>
HEADER
</h1>
</div>
<div class="large-6 columns">
<h1>
menu
</h1>
</div>
</div>
<div class="row">
<div class="large-5 none show-for-medium columns info">
Some information to the left
</div>
<div class="large-7 columns">
<div class="image-container">
<div class="image">
image to the right
</div>
</div>
</div>
</div>
</div>
Set the second row to take up the rest of the remaining height with flex: 1 and make sure you nest that flex with display: flex:
.row.target-row {
flex: 1;
display: flex;
}
Set the .image-container to 100% height of its column parent.
.image-container {
height: 100%;
}
By default both columns will expand. Stop the left column from expanding with:
.large-5 {
align-self: flex-start;
}
(flex-start reference: https://stackoverflow.com/a/40156422/2930477)
Complete Example
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
border: 1px solid black;
background-color: #ccc;
}
.row {
width: 100%;
}
.header {
background-color: green;
}
.info {
background-color: yellow;
border: 1px solid #ccc;
}
.image-container {
height: 100%;
background-color: red;
}
.large-5 {
align-self: flex-start;
}
.row.target-row {
flex: 1;
display: flex;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css" rel="stylesheet" />
<div class="wrapper">
<div class="header row">
<div class="large-6 columns">
<h1>
HEADER
</h1>
</div>
<div class="large-6 columns">
<h1>
menu
</h1>
</div>
</div>
<div class="row target-row">
<div class="large-5 none show-for-medium columns info">
Some information to the left
</div>
<div class="large-7 columns">
<div class="image-container">
<div class="image">
image to the right
</div>
</div>
</div>
</div>
</div>
flex-grow only applies to flex children.
.image-container isn't a direct child of a display: flex element, so that property has no effect.
Plus, it affects the flex axis, which is not what you want.
Instead, you need to put those two elements in their own flex row, and use align-items (on the parent) and align-self (on either child) so that the first one aligns (on the cross axis) to flex-start (stick to top) and the second one to stretch.
You'll also want that flex row (parent) to have flex-grow: 1 so that it stretches along the vertical flex axis of its parent (.wrapper) to fill the rest of the page (otherwise, the grandchild will have nothing to stretch to).
For more information, read a good flex tutorial.
div.wrapper > div:not(.header).row {
flex: 1; /* 1 */
display: flex; /* 1 */
}
div.large-7.columns {
display: flex; /* 2 */
}
div.image-container { /* 3 */
flex: 1;
}
div.large-5.show-for-medium { /* 4 */
align-self: flex-start;
}
jsFiddle
Notes:
flex container and items consume all remaining height of respective parents
give children full height (via align-items: stretch initial setting)
flex item consumes all available width
yellow box does not need to expand to full height; now set to content height
I'm trying to achieve the effect where the boxes labeled "HALF", take up only 50% of the width (aka they share the first row evenly).
The base requirement is that they remain in a single container. Is this possible to achieve using flexbox?
I've tried playing around with flex-grow, flex-shrink, and flex-basis but I'm afraid I'm not understanding how to make it work, or if it's even possible, given the single container requirement.
Consider this fiddle: http://jsfiddle.net/GyXxT/270/
div {
border: 1px solid;
}
.container {
width: 400px;
display: flex;
flex-direction: column;
}
.child {
height: 200px;
}
.child.half {
flex: 1 1 10em;
color: green;
}
.child:not(.half) {
flex-shrink: 2;
flex-basis: 50%;
color: purple;
}
<div class="container">
<div class="child half">
HALF
</div>
<div class="child half">
HALF
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
</div>
Instead of flex-direction: column, you can try a wrapping flexbox using flex-wrap: wrap; and you can set:
flex-basis: 50% for the half width divs
flex-basis: 100% for the full width divs
See that I have thrown in box-sizing: border-box to adjust for the widths when using flex-basis.
See demo below:
div {
border: 1px solid;
box-sizing: border-box;
}
.container {
width: 400px;
display: flex;
flex-wrap: wrap;
}
.child {
height: 200px;
}
.child.half {
flex-basis: 50%;
color: green;
}
.child:not(.half) {
flex-basis: 100%;
color: purple;
}
<div class="container">
<div class="child half">
HALF
</div>
<div class="child half">
HALF
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
</div>
The flex sizing properties -- flex-grow, flex-shrink, flex-basis and flex -- work only along the main axis of the flex container.
Since your container is flex-direction: column, the main axis is vertical, and these properties are controlling height, not width.
For sizing flex items horizontally in a column-direction container you'll need the width property.
(Here's a more detailed explanation: What are the differences between flex-basis and width?)
To achieve your layout with a single container, see another answer to this question.
If you want to stay in column-direction, you'll need to wrap the .half elements in their own container.
.container {
display: flex;
flex-direction: column;
width: 400px;
}
.container > div:first-child {
display: flex;
}
.child.half {
flex: 1 1 10em;
color: green;
width: 50%;
}
.child {
height: 200px;
width: 100%;
border: 1px solid;
}
* {
box-sizing: border-box;
}
<div class="container">
<div><!-- nested flex container for half elements -->
<div class="child half">HALF</div>
<div class="child half">HALF</div>
</div>
<div class="child">FULL</div>
<div class="child">FULL</div>
<div class="child">FULL</div>
<div class="child">FULL</div>
</div>
The base requirement is that they remain in a single container.
That can also be done without flexbox, by simply float the 2 half elements
div {
border: 1px solid;
box-sizing: border-box;
}
.container {
width: 400px;
}
.child {
height: 200px;
}
.child.half {
float: left;
width: 50%;
color: green;
}
.child:not(.half) {
width: 100%;
color: purple;
}
<div class="container">
<div class="child half">
HALF
</div>
<div class="child half">
HALF
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
</div>
If the purpose is to hardcode the size in CSS units, or in percentages (which was mentioned the question), #kukkuz's solution is good as it is.
If you want to size element widths according to their own individual contents, then align-tems: flex-start or similar could do the job. It's possible to deal with the dimension perpendicular to that of the flex layout itself. See a tester on the bottom of the doc page
(Old question, but previous answers were incomplete, some are misleading)
I am using an outline and a margin in an attempt to avoid a double border around some flex-elements.
If I apply a margin to the flex element itself it works as expected. However, if I apply the margin to a child element the double border shows up again.
Why does the outline correctly render only when the margin is applied to the parent flex element? Is this a bug?
.comment {
padding:20px;
}
#flex-container {
display: flex;
}
.flex-element {
flex-grow: 1;
}
.flex-content {
width: 100%;
height: 100%;
margin-left: 5px;
outline: 5px solid #ccc;
}
.flex-element-working {
flex-grow: 1;
margin-left: 5px;
}
.flex-content-working {
width: 100%;
height: 100%;
outline: 5px solid #ccc;
}
<div class='comment'>
Why doesn't this work?:
</div>
<div id='flex-container'>
<div class='flex-element'>
<div class='flex-content'>
<div class='comment'> Flex Content</div>
</div>
</div>
<div class='flex-element'>
<div class='flex-content'>
<div class='comment'> Flex Content</div>
</div>
</div>
</div>
<div class='comment'>
Working Example:
</div>
<div id='flex-container'>
<div class='flex-element-working'>
<div class='flex-content-working'>
<div class='comment'> Flex Content</div>
</div>
</div>
<div class='flex-element-working'>
<div class='flex-content-working'>
<div class='comment'> Flex Content</div>
</div>
</div>
</div>
The point is in the top flex container (bad working) in double outline the left on is for the right div and the right one is for left div! Please add this style to your code:
.flex-content{background-color:red;}
You will see the out line is how you want.
.flex-content divs have width 303px But .flex-content-working divs have width 298px so in second one we have not such problem.
To see the width of your elements use developer tools of your browser and layout or box menu.
A bit another approach using padding and box-shadow:
#flex-container {
box-shadow: inset 0 0 0 2px red;
display: flex;
padding: 2px;
}
.flex-element {
flex-grow: 1;
box-shadow: inherit;
}
.comment {
padding: 20px;
}
<div id='flex-container'>
<div class='flex-element'>
<div class='flex-content'>
<div class='comment'> Flex Content</div>
</div>
</div>
<div class='flex-element'>
<div class='flex-content'>
<div class='comment'> Flex Content</div>
</div>
</div>
</div>