How Does Flex-Wrap Work With Align-Self, Align-Items and Align-Content

How does flex-wrap work with align-self, align-items and align-content?

Short Answer

Although the flex-wrap property seems pretty basic – it controls whether flex items can wrap – it actually has a wide-ranging impact on the entire flexbox layout.

The flex-wrap property determines the type of flex container you will use.

  • flex-wrap: nowrap creates a single-line flex container
  • flex-wrap: wrap and wrap-reverse create a multi-line flex container

The align-items and align-self properties work in both single- and multi-line containers. However, they can only have an effect when there's free space in the cross axis of the flex line.

The align-content property works only in multi-line containers. It is ignored in single-line containers.



Explanation

The flexbox specification provides four keyword properties for aligning flex items:

  • align-items
  • align-self
  • align-content
  • justify-content

To understand the functions of these properties it's important to first understand the structure of a flex container.



Part 1: Understanding the Main Axis and Cross Axis of a Flex Container

The X and Y Axes

A flex container works in two directions: x-axis (horizontal) and y-axis (vertical).

x-axis and the y-axis

                                                                                                                Source: Wikipedia

The child elements of a flex container – known as "flex items" – can be aligned in either direction. (Ignore the z axis in the image above. It doesn't apply here.)

This is flex alignment at its most fundamental level.

The Main and Cross Axes

Overlaying the x and y axes are, in flex layout, the main and cross axes.

By default, the main axis is horizontal (x-axis), and the cross axis is vertical (y-axis). That's the initial setting, as defined by the flexbox specification.

flex main axis and cross axis

                                                                                                                Source: W3C

However, unlike the x and y axes, which are fixed, the main and cross axes can switch directions.

The flex-direction Property

In the image above, the main axis is horizontal and the cross axis is vertical. As mentioned earlier, that's an initial setting of a flex container.

However, these directions can be easily switched with the flex-direction property. This property controls the direction of the main axis; it determines whether flex items align vertically or horizontally.

From the spec:

5.1. Flex Flow Direction: the flex-direction
property

The flex-direction property specifies how flex items are placed in
the flex container, by setting the direction of the flex container’s
main axis. This determines the direction in which flex items are laid
out.

There are four values for the flex-direction property:

/* main axis is horizontal, cross axis is vertical */
flex-direction: row; /* default */
flex-direction: row-reverse;

/* main axis is vertical, cross axis is horizontal */
flex-direction: column;
flex-direction: column-reverse;

The cross axis is always perpendicular to the main axis.



Part 2: Flex Lines

Within the container, flex items exist in a line, known as a "flex line".

A flex line is a row or column, depending on flex-direction.

A container can have one or more lines, depending on flex-wrap.

Single-Line Flex Container

flex-wrap: nowrap establishes a single-line flex container, in which flex items are forced to stay in a single line (even if they overflow the container).

a single-line flex container (one column)

The image above has one flex line.

flex-container {
display: flex;
flex-direction: column;
flex-wrap: nowrap; /* <-- allows single-line flex container */
width: 250px;
height: 250px;
background-color: silver;
}
flex-item {
flex: 0 0 50px;
width: 50px;
margin: 5px;
background-color: lightgreen;
}
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>

Flex align-items does not work with flex-wrap?

Edit 1:

I forgot to mention in the original answer about the flex-wrap that when its enabled and row items get wrapped up and multi-line flexbox is created. In that case when you are aligning the content (I did not mention items since you want to consider all the elements not just elements that are on single-line), you need to use align-content: flex-end.

This will pack all the multi-lines occurring in your flex layout at the end of the flexbox, and your items will be aligned at the bottom.

When you were using align-items: flex-end, flexbox was aligning the items based on lines on which the element was placed.

When you used align-items: flex-end, elements are aligned as per the their line.

Heading
--------- // line 1
Paragraph
--------- // line 2

And when you used align-content: flex-end, lines are moved at the bottom.

Heading
Paragraph
--------- // multi lines are packed at the end of the flexbox

Here's working example for you:

body { margin: 0; padding: 0; }

div {
display: flex;
align-content: flex-end;
padding: 20px;
height: 300px;
background: #222;
flex-wrap: wrap;
}

h1 {
width: 100%;
}

h1, p {
color: #fff;
}
<div>
<h1>Header something something something header more of header and more and more</h1>
<p>Just some content at the end of the div not sure what more to write</p>
</div>

Flexbox using align-items: flex-start together with align-content: center

To achieve the desired result, you can make use of a media query.

To make this work, remove the flex-wrap and align-content properties from the .flex-container element. We will nly add these properties on the .flex-container element at a particular width of the browser window.

For example, following media query

@media (max-width: 450px) {
.flex-container {
flex-wrap: wrap;
align-content: center;
}
}

will make a flex container a multi-line flex container when the width of the browser window equal to or smaller than 450px. We also add align-content: center to make sure that the flex-lines are aligned in the center of the flex container.

This ensures that for a width greater than 450px, flex container has only one flex-line and flex items are aligned at the start of that single flex-line. For a width smaller than or equal to 450px, we make the flex container a multi-line flex container and align those flex-lines at the center of the flex container using align-content: center.

Working Demo

* {
box-sizing: border-box;
font-size: 1.5rem;
}

html {
background: #b3b3b3;
padding: 5px;
}

body {
background: #b3b3b3;
padding: 5px;
margin: 0;
}

.flex-container {
height: 500px;
background: white;
padding: 10px;
border: 5px solid black;
display: flex;
justify-content: space-evenly;
align-items: flex-start;
}

.flex-container div {
color: white;
padding: 10px;
border: 5px solid black;
margin: 10px;
}

.item-1 { background: #ff7300; }
.item-2 { background: #ff9640; }
.item-3 { background: #ff9640; }
.item-4 { background: #f5c096; }
.item-5 { background: #d3c0b1; }
.item-6 { background: #d3c0b1; }

@media (max-width: 450px) {
.flex-container {
flex-wrap: wrap;
align-content: center;
}
}
<div class="flex-container">
<div class="item-1">1</div>
<div class="item-2">2</div>
<div class="item-3">3</div>
<div class="item-4">4</div>
<div class="item-5">5</div>
<div class="item-6">6</div>
</div>

Using flexbox, how does align-content:stretch work when combined with align-items?

Using flexbox, how does align-content:stretch work when combined with align-items?

When you are working with a single-line flex container (flex-wrap: nowrap), align-content has no effect. You can use align-items and align-self to position flex items.

When you are working with a multi-line flex container (flex-wrap: wrap), align-content goes into effect and can be used to pack flex lines in the same way justify-content works on the main axis.

...how if you set align-content to stretch (default option), and set align-items: center, flex-end, or flex-start, it does not stretch the rows.It instead gives you rows separated by a margin.

These are not margins. This is align-content: stretch at work. This setting is taking the length of the container's cross-axis (in this case, height), and distributing that space equally among each line.

Here's the spec definition of stretch for the align-content property:

stretch

Lines stretch to take up the remaining space. If the leftover free-space is negative, this value is identical to flex-start. Otherwise, the free-space is split equally between all of the lines, increasing their cross size.

In other words, align-content: stretch on the cross axis is similar to flex: 1 on the main axis.

If you switch from align-content: stretch to align-content: flex-start, those gaps are gone.

.parent {  display: flex;  flex-flow: row wrap;  width: 80%;  height: 400px;  border: solid 5px blue;  align-items: center;  align-content: flex-start;}.child {  width: 200px;  font-size: 20px;  border: solid 2px black;}
<div class="parent">  <div class="child">22</div>  <div class="child">211212</div>  <div class="child">6666666</div>  <div class="child">211212</div>  <div class="child">211212</div>  <div class="child">211212</div>  <div class="child">211212</div>  <div class="child">211212</div>  <div class="child">211212</div>  <div class="child">211212</div>  <div class="child">211212</div>
</div>

CSS flex-item align self not working with flex-wrap parent

Flexbox aligns items in 1D direction. Thats why the flex-start didnt work,

In oreder to make it work wrap it with a div and add appropriate styles as shown in the snippet

.container {  width: 500px;  height: 500px;  background: pink;  display: flex;  justify-content: flex-end;  flex-wrap: wrap;}
.button-group {background: lightblue;padding: 5px 10px;display: inline-block;}
.main-box { width: 450px; height: 300px; background: lime;}
.myfooter { width: 50%; height: 10%; background-color: black;}.holder{width: 100%;}
<div class="container"><div class="holder">  <div class="button-group">    <button>1</button>    <button>2</button>    <button>3</button>  </div>  </div>
<div class="main-box"></div> <div class="myfooter"> </div></div>

CSS Flexbox: difference between align-items and align-content

As described in 6. Flex Lines,

Flex items in a flex container are laid out and aligned
within flex lines, hypothetical containers used for grouping and
alignment by the layout algorithm. A flex container can be either
single-line or multi-line, depending on the flex-wrap
property

Then, you can set different alignments:

  • The justify-content property applies to all flex containers, and sets the alignment of the flex items along the main axis of each flex line.

    An illustration of the five justify-content keywords and their effects on a flex container with three colored items.

  • The align-items property applies to all flex containers, and sets the default alignment of the flex items along the cross axis of each flex line. The align-self applies to all flex items, allows this default alignment to be overridden for individual flex items.

    An illustration of the five align-items keywords and their effects on a flex container with four colored items.

  • The align-content property only applies to multi-line flex containers, and aligns the flex lines within the flex container when there is extra space in the cross-axis.

    An illustration of the align-content keywords and their effects on a multi-line flex container.

Here you have a snippet to play:

var form = document.forms[0],    flex = document.getElementById('flex');form.addEventListener('change', function() {  flex.style.flexDirection = form.elements.fd.value;  flex.style.justifyContent = form.elements.jc.value;  flex.style.alignItems = form.elements.ai.value;  flex.style.alignContent = form.elements.ac.value;});
ul {  display: flex;  flex-flow: row wrap;  padding: 0;  list-style: none;}li {  padding: 0 15px;}label {  display: block;}#flex {  display: flex;  flex-wrap: wrap;  height: 240px;  width: 240px;  border: 1px solid #000;  background: yellow;}#flex > div {  min-width: 60px;  min-height: 60px;  border: 1px solid #000;  background: blue;  display: flex;  justify-content: center;  align-items: center;  color: #fff;}#flex > .big {  font-size: 1.5em;  min-width: 70px;  min-height: 70px;}
<form>  <ul>    <li>flex-direction      <label><input type="radio" name="fd" value="row" checked /> row</label>      <label><input type="radio" name="fd" value="row-reverse" /> row-reverse</label>      <label><input type="radio" name="fd" value="column" /> column</label>      <label><input type="radio" name="fd" value="column-reverse" /> column-reverse</label>    </li>    <li>justify-content      <label><input type="radio" name="jc" value="flex-start" checked /> flex-start</label>      <label><input type="radio" name="jc" value="flex-end" /> flex-end</label>      <label><input type="radio" name="jc" value="center" /> center</label>      <label><input type="radio" name="jc" value="space-between" /> space-between</label>      <label><input type="radio" name="jc" value="space-around" /> space-around</label>    </li>    <li>align-items      <label><input type="radio" name="ai" value="flex-start" /> flex-start</label>      <label><input type="radio" name="ai" value="flex-end" /> flex-end</label>      <label><input type="radio" name="ai" value="center" /> center</label>      <label><input type="radio" name="ai" value="baseline" /> baseline</label>      <label><input type="radio" name="ai" value="stretch" checked /> stretch</label>    </li>    <li>align-content      <label><input type="radio" name="ac" value="flex-start" /> flex-start</label>      <label><input type="radio" name="ac" value="flex-end" /> flex-end</label>      <label><input type="radio" name="ac" value="center" /> center</label>      <label><input type="radio" name="ac" value="space-between" /> space-between</label>      <label><input type="radio" name="ac" value="space-around" /> space-around</label>      <label><input type="radio" name="ac" value="stretch" checked /> stretch</label>    </li>  </ul></form><div id="flex">  <div>1</div>  <div class="big">2</div>  <div>3</div>  <div>4</div>  <div class="big">5</div>  <div>6</div></div>

flex-wrap doesn't work for columns when align-items set to any other value than stretched

It's because stretch (which is the default alignment) make the b3 b4 have full height of their parent container which is a needed constraint in order to have a wrapping. Without stretch you will simply have a, overflow since there is no height contraint. Inspect the element in both cases and you will notice that:

  1. With stretch the height is variable based on the parent container which is the screen size
  2. without stretch (when you define align-items: flex-start) the height is fixed based on the content (the 3 boxes inside)

You can get a similar behavior with b1 and b2 if you disable the default shrink effect:

#box-container {
width: 100%;
height: 100vh;
background-color: hsl(0, 0%, 80%);
display: flex;
flex-direction: row;
align-items: flex-start;
/* !!! */
}

.box {
min-width: 135px;
min-height: 135px;
padding: 5px;
display: flex;
flex-wrap: wrap;
/* переносит на следующую строку/столбец элемент, если мало места */
align-content: flex-start;
/* выравнивание рядов по вертикали */
justify-items: flex-start;
/* выравнивание столбцов по горизонтали */
}

#b1 {
background-color: hsl(0, 25%, 50%);
flex-direction: row;
flex-shrink:0;
}

#b2 {
background-color: hsl(90, 25%, 50%);
flex-direction: row-reverse;
flex-shrink:0;
}

#b3 {
background-color: hsl(180, 25%, 50%);
flex-direction: column;
}

#b4 {
background-color: hsl(270, 25%, 50%);
flex-direction: column-reverse;
}

.smallbox {
width: 125px;
height: 125px;
margin: 5px;
display: flex;
align-items: center;
/* выравнивание содержимого по вертикали */
justify-content: center;
/* выравнивание содержимого по горизонтали */
}
<html>

<head>
<title>CSSFlexbox Main Page</title>
<link rel="stylesheet" href="style.css">
</head>

<body style="margin: 0;">
<div id="box-container">
<div id="b1" class="box">
<div class="smallbox sb1" style="background-color:hsla(0, 50%, 50%);">
<h2>1</h2>
</div>
<div class="smallbox sb2" style="background-color:hsla(30, 50%, 50%);">
<h2>2</h2>
</div>
<div class="smallbox sb3" style="background-color:hsla(60, 50%, 50%);">
<h2>3</h2>
</div>
</div>
<div id="b2" class="box">
<div class="smallbox sb1" style="background-color:hsla(90, 50%, 50%);">
<h2>1</h2>
</div>
<div class="smallbox sb2" style="background-color:hsla(120, 50%, 50%);">
<h2>2</h2>
</div>
<div class="smallbox sb3" style="background-color:hsla(150, 50%, 50%);">
<h2>3</h2>
</div>
</div>
<div id="b3" class="box">
<div class="smallbox sb1" style="background-color:hsla(180, 50%, 50%);">
<h2>1</h2>
</div>
<div class="smallbox sb2" style="background-color:hsla(210, 50%, 50%);">
<h2>2</h2>
</div>
<div class="smallbox sb3" style="background-color:hsla(240, 50%, 50%);">
<h2>3</h2>
</div>
</div>
<div id="b4" class="box">
<div class="smallbox sb1" style="background-color:hsla(270, 50%, 50%);">
<h2>1</h2>
</div>
<div class="smallbox sb2" style="background-color:hsla(300, 50%, 50%);">
<h2>2</h2>
</div>
<div class="smallbox sb3" style="background-color:hsla(330, 50%, 50%);">
<h2>3</h2>
</div>
</div>
</div>
</body>

</html>

flex item ignoring align-content property

In a single-line flex container (flex-wrap: nowrap), use align-items for cross-axis alignment.

In a multi-line flex container (flex-wrap: wrap), use align-content.

In this case, because there is only one flex line (which occupies the full-height of the container), use align-items: center on the container, or align-self: center on the item.

align-items goes on the flex container. It sets the default align-self for all items.

align-self goes on individual flex items. It overrides align-items set by the parent for that particular item.

Here's a more complete explanation:

  • How does flex-wrap work with align-self, align-items and align-content?

flexbox align-items and flex-direction conflicting

flex-direction: column