1

#flex-container {
  height: 200px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  align-content: flex-end;
  border: 2px solid;
}

#first-box {
  background-color: gray;
  width: 200px;
  margin: 5px;
}

#second-box {
  background-color: aqua;
  width: 200px;
  margin: 5px;
}
<div id="flex-container">
  <div id="first-box">Box 1 </div>
  <div id="second-box">Box 2</div>
</div>

Rule is: There must be multiple lines of items for this property to have any effect! Why then have effect on displaying when there are not multiple lines of items? Those two boxes should be centered on browser but there are on the bottom.

Temani Afif
  • 245,468
  • 26
  • 309
  • 415

2 Answers2

1

Rule is: There must be multiple lines of items for this property to have any effect!

The rule isn't exactly like that. There must be a multi-line flex container and this is not defined by the number of lines but by the flex-wrap property.

Read the below until the end to get the full explanation


From the specification:

The align-content property aligns a flex container’s lines within the flex container when there is extra space in the cross-axis .. Note, this property has no effect on a single-line flex container1.

and

Initial: stretch

So by default your one line is stretched to fill all the available space and the content is centred inside. If you select flex-end, your line will fit its content and will be placed at the bottom. The content is still centred inside but since the height is now defined by the content, the vertical centring is useless.

The trick here is to understand that centring in flexbox happen inside a line and not the container but in most of the case that line is stretched to fit the container height2. By changing align-content and flex-wrap it's no more the case.


flex-end

Lines are packed toward the end of the flex container. The cross-end edge of the last line is placed flush with the cross-end edge of the flex container, and each preceding line is placed flush with the subsequent line.

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.

Some examples to better illustrate. The pink and yellow coloration represent the flexbox lines.

.box {
  display: inline-flex;
  vertical-align: top;
  width: 100px;
  height: 100px;
  border: 1px solid;
  align-items: center;
  flex-wrap: wrap;
}

span {
  width: 100%;
  height: 10px;
  margin: 5px;
  background: red;
}
<div class="box" style="background:yellow;">
  <span></span>
</div>

<div class="box" style="background:linear-gradient(yellow 50%,pink 50%);">
  <span></span>
  <span></span>
</div>
<div class="box" style="align-content:flex-end">
  <span style="box-shadow:0 0 0 5px yellow"></span>
</div>
<div class="box" style="align-content:flex-end">
  <span style="box-shadow:0 0 0 5px yellow"></span>
  <span style="box-shadow:0 0 0 5px pink"></span>
</div>

1Now the tricky part is the use of flex-wrap

A single-line flex container (i.e. one with flex-wrap: nowrap) lays out all of its children in a single line, even if that would cause its contents to overflow.

A multi-line flex container (i.e. one with flex-wrap: wrap or flex-wrap: wrap-reverse) breaks its flex items across multiple lines, ...

If you specify wrap as flex-wrap, it's no more considered as single-line even if there is only one line thus align-content apply like described above.

If you keep it nowrap then nothing will happen because it's a single-line flexbox container and by default that line is always stretched to fill the space:

.box {
  display: inline-flex;
  vertical-align: top;
  width: 100px;
  height: 100px;
  border: 1px solid;
  align-items: center;
}

span {
  width: 100%;
  height: 10px;
  margin: 5px;
  background: red;
}
<div class="box" >
  <span></span>
</div>

<div class="box" >
  <span></span>
  <span></span>
</div>
<div class="box" style="align-content:flex-end">
  <span ></span>
</div>
<div class="box" style="align-content:flex-end">
  <span ></span>
  <span ></span>
</div>

2Note: Only multi-line flex containers ever have free space in the cross-axis for lines to be aligned in, because in a single-line flex container the sole line automatically stretches to fill the space.

Community
  • 1
  • 1
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
0

If you go to the "try it" page for "CSS align-content Property" at w3schools.com you can insert your CSS and see exactly what it does. As far as I can see it is acting as expected and as Temani explains. You can also tweak the code until it does what you actually want.

pjaj
  • 225
  • 4
  • 12