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 containerflex-wrap: wrap
andwrap-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).
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.
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
propertyThe
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).
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 withalign-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 setalign-items: center
,flex-end
, orflex-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.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. Thealign-self
applies to all flex items, allows this default alignment to be overridden for individual flex 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.
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:
- With stretch the height is variable based on the parent container which is the screen size
- 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
.container { display: flex; flex-direction: column; align-items: center; /* horizontal alignment */ justify-content: center; /* vertical alignment */ height: 40px; width: 400px; border: 1px solid black;}
h1,h2 { font-size: 12px; margin: 0px;}
<div class='container'> <h1>heading 1</h1> <h2>heading 2</h2></div>
Related Topics
How to Change Paper Size in Headless Chrome - Print-To-Pdf
Why It Is Not Taking 100% Height in Material Design
Canvas Has White Space At the Bottom and Scrolls Too Far
Change Bootstrap Navbar Collapse Breakpoint Without Using Less
Order Columns Through Bootstrap4
Twitter Bootstrap 3: How to Use Media Queries
Column Order Manipulation Using Col-Lg-Push and Col-Lg-Pull in Twitter Bootstrap 3
Prevent Flicker on Webkit-Transition of Webkit-Transform
Change Color and Appearance of Drop Down Arrow
Overflow-X:Hidden Doesn't Prevent Content from Overflowing in Mobile Browsers
How to Break a List into Columns
Rotated Elements in CSS That Affect Their Parent'S Height Correctly
Use of Xsl-Fo, Css3 Instead of Css2 to Create Paginated Documents Like Pdf
Transparent Hollow or Cut Out Circle
How to Keep Two Divs on the Same Line
Formatting Numbers (Decimal Places, Thousands Separators, Localization, etc) With CSS