Css property align-items: center in Flexbox losing height of columns [duplicate] - html

I'd like to have two columns of equal height and their content should be middle aligned, so in the very center of each div.
Problem: 'equal height' and 'middle aligned' seem to exclude themselves, the one doesn't work with the other.
Question: How can I create a row with two columns with different width, equal height and their content centered in the middle of each column?
<!-- 'middle aligned' and 'equal height' don't like each other ? -->
<div class="ui equal height center aligned grid">
<div class="row">
<div class="twelve wide purple column">
<p>Text Text Text</p>
<p>Text Text Text</p>
<p>Text Text Text</p>
<p>Text Text Text</p>
</div>
<div class="four wide red column middle aligned">
<div class="row">Forward</div>
</div>
</div>
</div>
http://jsfiddle.net/kjjd66zk/1/

The key to this layout is to apply equal heights to the primary flex container.
Then make the flex items nested flex containers, which can center the content of the flex items.
Hence, the top level creates the equal height. The second level does the centering.
(See the note at the bottom for more details.)
Here's an example based on your code structure:
body {
height: 300px; /* for demo purposes */
color: white;
}
flex-container {
display: flex; /* primary flex container */
flex-direction: row; /* horizontal alignment of flex items
(default value; can be omitted) */
align-items: stretch; /* will apply equal heights to flex items
(default value; can be omitted) */
height: 100%;
}
flex-item {
display: flex; /* nested flex container */
flex-direction: column; /* vertical alignment of flex items */
justify-content: center; /* center flex items vertically */
align-items: center; /* center flex items horizontally */
}
flex-item:first-child {
flex: 3; /* consume 3x more free space than sibling */
background-color: #a333c8;
}
flex-item:last-child {
flex: 1;
background-color: #db2828;
}
<flex-container>
<flex-item><!-- also flex container -->
<p>Text Text Text</p>
<p>Text Text Text</p>
<p>Text Text Text</p>
<p>Text Text Text</p>
</flex-item>
<flex-item><!-- also flex container -->
<div>Forward</div>
</flex-item>
</flex-container>
jsFiddle demo
People sometimes consider a flex item and its content to be one element. This is not correct.
The HTML structure of a flex container has three levels:
the container
the item
the content
Therefore, the content inside an item does not represent the item; it represents a separate element.
If the content inside an item is text, it becomes an anonymous element.
From the flexbox spec:
4. Flex Items
Each in-flow child of a flex container becomes a flex item, and each
contiguous run of text that is directly contained inside a flex
container is wrapped in an anonymous flex item.
That's why, in the solution above, the flex item becomes a flex container. It enables the use of flex properties on the children of the flex item (the content).

You need to give height to your elements
.height {
height: 300px;
}
.row {
height: 100%;
}
.row > div {
height: 100%;
}
Updated fiddle 1
If you want them to center vertical, update above .row > div rule to this
.row > div {
height: 100%;
display: flex !important;
flex-direction: column;
justify-content: center;
}
Updated fiddle 2

Related

Flex column align-items: flex-start not working [duplicate]

What is the difference between align-items and align-content?
The align-items property of flex-box aligns the items inside a flex container along the cross axis just like justify-content does along the main axis. (For the default flex-direction: row the cross axis corresponds to vertical and the main axis corresponds to horizontal. With flex-direction: column those two are interchanged respectively).
Here's an example of how align-items:center looks:
But align-content is for multi line flexible boxes. It has no effect when items are in a single line. It aligns the whole structure according to its value. Here's an example for align-content: space-around;:
And here's how align-content: space-around; with align-items:center looks:
Note the 3rd box and all other boxes in first line change to vertically centered in that line.
Here are some codepen links to play with:
http://codepen.io/asim-coder/pen/MKQWbb
http://codepen.io/asim-coder/pen/WrMNWR
Here's a super cool pen which shows and lets you play with almost everything in flexbox.
From the example at flexboxfroggy.com:
It will take you 10-20 minutes and at level 21 you will find the answer to your question.
align-content determines the spacing between lines
align-items determines how the items as a whole are aligned within the container.
When there is only one line, align-content has no effect
First, align-items is for items in a single row. So for a single row of elements on main axis, align-items will align these items respective of each other and it will start with fresh perspective from the next row.
Now, align-content doesn't interfere with items in a row but with rows itself. Hence, align-content will try to align rows with respect to each other and flex container.
Check this fiddle : https://jsfiddle.net/htym5zkn/8/
I had the same confusion. After some tinkering based on many of the answers above, I can finally see the differences. In my humble opinion, the distinction is best demonstrated with a flex container that satisfies the following two conditions:
The flex container itself has a height constraint (e.g., min-height: 60rem) and thus can become too tall for its content
The child items enclosed in the container have uneven heights
Condition 1 helps me understand what content means relative to its parent container. When the content is flush with the container, we will not be able to see any positioning effects coming from align-content. It is only when we have extra space along the cross axis, we start to see its effect: It aligns the content relative to the boundaries of the parent container.
Condition 2 helps me visualize the effects of align-items: it aligns items relative to each other.
Here is a code example. Raw materials come from Wes Bos' CSS Grid tutorial (21. Flexbox vs. CSS Grid)
Example HTML:
<div class="flex-container">
<div class="item">Short</div>
<div class="item">Longerrrrrrrrrrrrrr</div>
<div class="item">💩</div>
<div class="item" id="tall">This is Many Words</div>
<div class="item">Lorem, ipsum.</div>
<div class="item">10</div>
<div class="item">Snickers</div>
<div class="item">Wes Is Cool</div>
<div class="item">Short</div>
</div>
Example CSS:
.flex-container {
display: flex;
/*dictates a min-height*/
min-height: 60rem;
flex-flow: row wrap;
border: 5px solid white;
justify-content: center;
align-items: center;
align-content: flex-start;
}
#tall {
/*intentionally made tall*/
min-height: 30rem;
}
.item {
margin: 10px;
max-height: 10rem;
}
Example 1: Let's narrow the viewport so that the content is flush with the container. This is when align-content: flex-start; has no effects since the entire content block is tightly fit inside the container (no extra room for repositioning!)
Also, note the 2nd row--see how the items are center aligned among themselves.
Example 2: As we widen the viewport, we no longer have enough content to fill the entire container. Now we start to see the effects of align-content: flex-start;--it aligns the content relative to the top edge of the container.
These examples are based on flexbox, but the same principles are applicable to CSS grid. Hope this helps :)
The effect of both align-items and align-content is along the cross-axis.
Let say if flex-direction is row then the main axis is Left to Right and if flex-direction is column then the main axis is from top to bottom.
So In the below examples, we gonna assume that flex-direction is row i.e. main axis is from Left to Right and cross-axis is from top to bottom.
align-content only works if there is flex-wrap: wrap and if there is more than one flex-line in container.
align-content has higher priority than align-items if there are multiple flex-line.
What is flex-line?
Each row or column of flex items in a flex container is a flex line. Multiple lines occur when there is not enough space in a container and flex-items would take the next line(in flex-direction: row;) to fit in. In flex-direction: column it will add flex items to next line.
example
By default, the flex is a flexible container i.e. it can accommodate any number of elements unless we have specified flex-wrap: wrap. Without wrap, flex-items will overflow the container(if flex-direction is row).
align-content example
.container{
border: 5px solid #000;
height: 100vh;
display: flex;
flex-wrap: wrap;
align-content: flex-end;
}
.box{
height:100px;
font-size: 2rem;
width: 33.33%;
}
.box1{
background: purple;
}
.box2{
background: #ff8c00;
}
.box3{
background: lime;
}
.box4{
background: #008080;
}
.box5{
background-color: red;
}
<div class="container">
<div class="box box1">box 1</div>
<div class="box box2">box 2</div>
<div class="box box3">box 3</div>
<div class="box box4">box 4</div>
<div class="box box5">box 5</div>
</div>
In the above example, If there would have been flex-wrap: no-wrap then align-content doesn't affect our layout.
align-items example
The align-items property determines how flex items are positioned within a flex line, along the cross-axis.
.container{
border: 5px solid #000;
height: 100vh;
display: flex;
flex-wrap: wrap;
align-items: flex-end;
}
.box{
height:100px;
font-size: 2rem;
width: 33.33%;
}
.box1{
background: purple;
}
.box2{
background: #ff8c00;
}
.box3{
background: lime;
}
.box4{
background: #008080;
}
.box5{
background-color: red;
}
<div class="container">
<div class="box box1">box 1</div>
<div class="box box2">box 2</div>
<div class="box box3">box 3</div>
<div class="box box4">box 4</div>
<div class="box box5">box 5</div>
</div>
If align-content and align-items are declared on a container with properties flex-wrap: wrap and if there are more than flex-line then align-content property has higher priority than align-items.
align-content and align-items priority example
.container{
border: 5px solid #000;
height: 100vh;
display: flex;
flex-wrap: wrap;
align-content: flex-end;
align-items: flex-start;
}
.box{
height:100px;
font-size: 2rem;
width: 33.33%;
}
.box1{
background: purple;
}
.box2{
background: #ff8c00;
}
.box3{
background: lime;
}
.box4{
background: #008080;
}
.box5{
background-color: red;
}
<div class="container">
<div class="box box1">box 1</div>
<div class="box box2">box 2</div>
<div class="box box3">box 3</div>
<div class="box box4">box 4</div>
<div class="box box5">box 5</div>
</div>
Well I have examined them on my browser.
align-content can change a line's height for row direction or width for column when it's value is stretch, or add empty space between or around the lines for space-between, space-around, flex-start, flex-end values.
align-items can change items height or position inside the line's area. When items are not wrapped they have only one line which it's area is always stretched to the flex-box area (even if the items overflow), and align-content has no effect on a single line. So it has no effect on items that are not wrapped and only align-items can change items position or stretch them when all of them are on a single line.
However, if they are wrapped you have multiple lines and items inside each line. And if all items of each line have the same height (for row direction) that line's height will be equal to those items height and you don't see any effect by changing align-items value.
So if you want to affect items by align-items when your items are wrapped and have the same height (for row direction) first you have to use align-content with stretch value in order to expand the lines area.
Having read some of the answers, they identify correctly that align-content takes no affect if the flex content is not wrapped. However what they don't understand is align-items still plays an important role when there is wrapped content:
In the following two examples, align-items is used to center the items within each row, then we change align-content to see it's effect.
Example 1:
align-content: flex-start;
Example 2:
align-content: flex-end;
Here's the code:
<div class="container">
<div class="child" style="height: 30px;">1</div>
<div class="child" style="height: 50px;">2</div>
<div class="child" style="height: 60px;">3</div>
<div class="child" style="height: 40px;">4</div>
<div class="child" style="height: 50px;">5</div>
<div class="child" style="height: 20px;">6</div>
<div class="child" style="height: 90px;">7</div>
<div class="child" style="height: 50px;">8</div>
<div class="child" style="height: 30px;">9</div>
<div class="child" style="height: 40px;">10</div>
<div class="child" style="height: 30px;">11</div>
<div class="child" style="height: 60px;">12</div>
</div>
<style>
.container {
display: flex;
width: 300px;
flex-flow: row wrap;
justify-content: space-between;
align-items: center;
align-content: flex-end;
background: lightgray;
height: 400px;
}
.child {
padding: 12px;
background: red;
border: solid 1px black;
}
</style>
align-content
align-content controls the cross-axis (i.e. vertical direction if the flex-direction is row, and horizontal if the flex-direction is column) positioning of multiple lines relative to each other.
(Think lines of a paragraph being vertically spread out, stacked toward the top, stacked toward the bottom. This is under a flex-direction row paradigm).
align-items
align-items controls the cross-axis of an individual line of flex elements.
(Think how an individual line of a paragraph is aligned, if it contains some normal text and some taller text like math equations. In that case, will it be the bottom, top, or center of each type of text in a line that will be aligned?)
align-items spreads the child elements vertically with space between them.
align-content bunches them together as if they were one element.
(if the flex-direction is column)
What I have learned from every answer and visiting the blog is
what is the cross axis and main axis
main axis is horizontal row and cross axis is vertical column - for flex-direction: row
main axis is vertical column and cross axis is horizontal row - for flex-direction: column
Now align-content and align-items
align-content is for the row, it works if the container has (more than one row)
Properties of align-content
.container {
align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch | start | end | baseline | first baseline | last baseline + ... safe | unsafe;
}
align-items is for the items in row
Properties of align-items
.container {
align-items: stretch | flex-start | flex-end | center | baseline | first baseline | last baseline | start | end | self-start | self-end + ... safe | unsafe;
}
For more reference visit to flex
The key property is flex-wrap. When nowrap (or when there is no extra space in the cross axis), align-content has no effect. When wrap or wrap-reverse, it has always an effect (regardless of the line count) if there is extra space in the cross axis.
Compare these four boxes:
while align-items would centre as a single line of text both horizontally and vertically inside a container , align-content would behave as if there were multiple lines of text,or a paragraph, and start from top aligning even a single line of text as if it were paragraph which has been given a text-align: center rule.
This is the result we get from
align-content:center;
First Part
align-items applies to single line of boxes only. Suppose there are 4 boxes in a single line inside the container. then align-items will be applied to align those boxes in a single line. If flex-direction is row (which is default) then align-items will arrange the boxes vertically, if its column then arrange the boxes horizontally.
Second Part
Continuing with the above single line of boxes, if we add one more line of 4 boxes, now there are 8 boxes, 4 in each line. Here align-content comes into picture, if we apply align-content to the container, it will be applied to both lines having total of 8 boxes. If we apply align-content:center, it will center both lines in a container. In that sense align-content is used to arrange multi line flexible boxes.
align-items: center, align-content: flex-start
The main difference is when the height of the elements are not the same!
Then you can see how in the row, they are all center\end\start
according to what I understood from here:
when you use align-item or justify-item, you are adjusting "the content inside a grid item along the column axis or row axis respectively.
But:
if you use align-content or justify-content, you are setting the position a grid along the column axis or the row axis. it occurs when you have a grid in a bigger container and width or height are inflexible (using px).

flexbox is setting all of my text side by side

I have some weird behavior going on in my divs at the moment, each div is written like the other (they are just mirror images). The text is mimicking columns and is setting side by side instead of top to bottom like it should. The oddest thing is, it seems to be working fine on another page this particular page only contains the behavior.
The code is something like this
<div class="flex-wrap">
<div class="flex">
<h3>A title</h3>
<p>some text</p>
</div>
<div class="flex">
<h3>A title</h3>
<p>some text</p>
</div>
</div>
<style>
.flex-wrap{
display:flex;
flex-wrap:wrap;
}
.flex{
display:flex;
align-items: center;
}
</style>
I've taken this apart piece by piece in the inspector tool and I'm even more baffled as to why it works fine on one page and not at all on another. The last section uses the same css layout it just contains a different picture and text. Can anyone tell me how to fix this? BONUS POINTS IF YOU CAN TELL ME WHY.
The first thing to keep in mind is that flex layout applies only between parent and child elements. Descendants in a flex container beyond the children do not participate in flex layout.
In your "broken page", the four side-by-side paragraph elements are children of a flex container (.tours-sec-3-p2-wrap).
.tours-sec-3-p2-wrap {
padding: 2%;
align-items: center;
display: flex;
background-size: 15%;
padding-top: 0;
background-position: 0px 30%;
background-repeat: no-repeat;
}
An initial setting of a flex container is flex-direction: row, so the children (flex items) are lining up in a row. The quick and easy solution is to override the default with flex-direction: column.
In your "working fine" page, the image and paragraphs are not children of a flex container. These elements are children of a block container, and that container is the child of the flex container.
Your image and text are being aligned with float, not flex, properties.
If you want to use flex properties, add display: flex to the parent element.
Despite anyone's belief, the layouts of each section are exactly the same. They are generated with the cms, they are not static pages.
That said, the behavior was only different between the 2 because of the length of the content in each flex container. Adding the same content to the tours page created the same behavior.
The problem was indeed solved with flex-direction: column; and additionally adding justify-content: center;
If you don't want to use flex-direction: column; you can make your elements stretch to 100% width to force the wrap.
.flex-wrap{
display:flex;
flex-wrap:wrap;
}
.flex{
display:flex;
align-items: center;
flex-wrap:wrap; /* added */
}
.flex,
.flex h3,
.flex p
{
width: 100%;
}
<div class="flex-wrap">
<div class="flex">
<h3>A title</h3>
<p>some text</p>
</div>
<div class="flex">
<h3>A title</h3>
<p>some text</p>
</div>
</div>
Bonus Tip for justify-content: center and text aligning left after wrapping. (run the code snippet)
.flex-wrap{
display:flex;
flex-wrap:wrap;
flex-direction: column;
}
.flex {
display:flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.text-centered {
text-align: center;
}
<div class="flex-wrap">
<div class="flex">
<h3>Centered (but it hasn't wrapped)</h3>
<p>centered text</p>
</div>
<div class="flex">
<h3>Not Centered (after wrap)</h3>
<p>sometimes you'll want to use justify-content: center; and keep the text centered along with whatever other elements are inside the div. You'll see in the 2nd example the text aligns left after it wraps. Add text-align: center; and it will center the text.</p>
</div>
<div class="flex text-centered">
<h3>Centered</h3>
<p>sometimes you'll want to use justify-content: center; and keep the text centered along with whatever other elements are inside the div. You'll see in the 2nd example the text aligns left after it wraps. Add text-align: center; and it will center the text.</p>
</div>
</div>

Elements in a flex container are not wrapping

When I try to insert block elements in a flex container, they all stay on the same line as if they were inline-blocks.
I would like the two first div's to be on the same line, and the last one to be on a second line. Sadly, that doesn't seem to work.
Anyone have any idea ?
<div style="display: flex">
<div style="display: inline-block">
This is an inline block element
</div>
<div style="display: inline-block">
This is an inline block element
</div>
<div style="display: block">
This is a block element
</div>
</div>
An initial setting of a flex container is flex-wrap: nowrap. This means flex items are forced to remain in a single line.
You can override the default with flex-wrap: wrap.
The display value of flex items is ignored in flex layout.
A flex container, which is an element with display: flex or display: inline-flex, establishes a flex formatting context. Although similar to a block formatting context, there are differences.
One difference is that children of a flex container ignore the display property.
Another difference is that, in a flex container, margins don't collapse, and the float and clear properties have no effect.
A flex container also comes with several default settings. Among them:
justify-content: flex-start - flex items will stack at the start of the line
flex-shrink: 1 - flex items are allowed to shrink and will not overflow the container
align-items: stretch - flex items will expand to cover the cross-size of the container
flex-direction: row - flex items will align horizontally
flex-wrap: nowrap - flex items are forced to stay in a single line
Note the last two items.
Flex items will line up in a row and cannot wrap.
If you want to have two flex items on the first line, and a third item on the second line, allow the container to be multi-line with flex-wrap: wrap.
.container {
display: flex;
flex-wrap: wrap;
}
.box {
flex: 0 0 45%;
height: 50px;
margin: 5px;
background-color: lightgreen;
border: 1px solid #ccc;
}
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
Also, if you want flex containers to display inline, use display: inline-flex not display: flex. These are comparable to display: inline-block and display: block.
use flex-wrap:wrap in parent because by default the flex-wrap is nowrap
use flex-basis:50% in child, to divide both inline-block elements in same size.
See more detailed info about flexbox on this article: A Complete Guide to Flexbox
*,
*::before,
*::after {
box-sizing: border-box
}
body {
margin: 0
}
.flex {
display: flex;
flex-wrap: wrap
}
.flex div {
flex: 0 50%; /*change to 1 50% to see the difference */
border: 1px solid black;
padding: 10px
}
<div class="flex">
<div>
This is an inline block element
</div>
<div>
This is an inline block element
</div>
<div>
This is a block element
</div>
</div>

Equal height columns with centered content in flexbox

I'd like to have two columns of equal height and their content should be middle aligned, so in the very center of each div.
Problem: 'equal height' and 'middle aligned' seem to exclude themselves, the one doesn't work with the other.
Question: How can I create a row with two columns with different width, equal height and their content centered in the middle of each column?
<!-- 'middle aligned' and 'equal height' don't like each other ? -->
<div class="ui equal height center aligned grid">
<div class="row">
<div class="twelve wide purple column">
<p>Text Text Text</p>
<p>Text Text Text</p>
<p>Text Text Text</p>
<p>Text Text Text</p>
</div>
<div class="four wide red column middle aligned">
<div class="row">Forward</div>
</div>
</div>
</div>
http://jsfiddle.net/kjjd66zk/1/
The key to this layout is to apply equal heights to the primary flex container.
Then make the flex items nested flex containers, which can center the content of the flex items.
Hence, the top level creates the equal height. The second level does the centering.
(See the note at the bottom for more details.)
Here's an example based on your code structure:
body {
height: 300px; /* for demo purposes */
color: white;
}
flex-container {
display: flex; /* primary flex container */
flex-direction: row; /* horizontal alignment of flex items
(default value; can be omitted) */
align-items: stretch; /* will apply equal heights to flex items
(default value; can be omitted) */
height: 100%;
}
flex-item {
display: flex; /* nested flex container */
flex-direction: column; /* vertical alignment of flex items */
justify-content: center; /* center flex items vertically */
align-items: center; /* center flex items horizontally */
}
flex-item:first-child {
flex: 3; /* consume 3x more free space than sibling */
background-color: #a333c8;
}
flex-item:last-child {
flex: 1;
background-color: #db2828;
}
<flex-container>
<flex-item><!-- also flex container -->
<p>Text Text Text</p>
<p>Text Text Text</p>
<p>Text Text Text</p>
<p>Text Text Text</p>
</flex-item>
<flex-item><!-- also flex container -->
<div>Forward</div>
</flex-item>
</flex-container>
jsFiddle demo
People sometimes consider a flex item and its content to be one element. This is not correct.
The HTML structure of a flex container has three levels:
the container
the item
the content
Therefore, the content inside an item does not represent the item; it represents a separate element.
If the content inside an item is text, it becomes an anonymous element.
From the flexbox spec:
4. Flex Items
Each in-flow child of a flex container becomes a flex item, and each
contiguous run of text that is directly contained inside a flex
container is wrapped in an anonymous flex item.
That's why, in the solution above, the flex item becomes a flex container. It enables the use of flex properties on the children of the flex item (the content).
You need to give height to your elements
.height {
height: 300px;
}
.row {
height: 100%;
}
.row > div {
height: 100%;
}
Updated fiddle 1
If you want them to center vertical, update above .row > div rule to this
.row > div {
height: 100%;
display: flex !important;
flex-direction: column;
justify-content: center;
}
Updated fiddle 2

Flexbox, have 2 items aligned left, a 3rd aligned right that stretches the full height of the container

Is it possible to have 3 items in a flex container but have them displayed like this:
1 3
2 3
Basically, where items 1 & 2 are on the left and about whatever height they each need to be, then item 3 is right-aligned but stretches the full height of the flex container?
Here's a codepen to illustrate: http://codepen.io/anon/pen/RrORbj
Here is a jsFiddle using flexbox.
<div class="container">
<div class="col">
<div class="box one">
one
</div>
<div class="box two">
two
</div>
</div>
<div class="col">
<div class="box three">
three
</div>
</div>
</div>
First, you set the container to a flexbox. Note, that the default value of flex-direction is row (horizontal). Setting the child element (col) with flex: 1 makes the columns flexible in the direction of the parents flex direction.
Note also, that the default value of align-items on the container is stretch. What this does is set the height of all child elements (col's) to the height of the tallest col.
.container {
display: flex; //make container a flexbox
}
.col {
flex: 1; //make columns flexible (horizontally)
}
Next, we will use the same approach as before to spread box three vertically across the column.
.container {
display: flex;
}
.col {
flex: 1;
display: flex; //make col a flexbox
flex-direction: column; //make the children of col flex vertically
}
Here we have added display: flex and flex-direction: column to turn column into a verticale flexbox. The last thing to do is make the box you want to be full height flexible vertically.
.three {
flex: 1; //make it flexible
}
.three is flexible vertically (not the default horizontal) due to setting the flex direction on its parent.
EDIT:
Personally, I would set the class box to have flex: 1 as shown in this updated jsFiddle. This allows any number of columns to flex vertically (while still allowing boxes of the "taller" column to grow as they need.