23

I find the difference between align-items and align-content in CSS Flexbox properties extremely confusing. I've been looking at the documentation, and several examples online for hours, but I still can't fully grasp it.

To be more precise, align-items makes total sense to me and it's completely clear how it behaves. On the other hand, align-content is not clear at all. In particular, I don't understand why we should use two different properties depending on whether the content all fits in one line or multiple ones.

What is the explanation in layman's terms?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Pensierinmusica
  • 6,404
  • 9
  • 40
  • 58

2 Answers2

55

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>
Oriol
  • 274,082
  • 63
  • 437
  • 513
16

First you need to understand how the Flexible box structure works. The below image is part of the Cheatsheet.

Flexbox Structure

Flexbox structure

Flexbox was built to adapt both as a row and column.

Main-axis:

When flex-direction is row: the x-axis as on a graph. When flex-direction is column: the y-axis on a graph

Cross-axis:

When flex-direction is column: the x-axis as on a graph. When flex-direction is row: the y-axis on a graph

Justify-Content

justify-content is used to align the items along with the main-axis.

.justify-content {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  height: 500px;
  width: 500px;
  background: lightgray;
  padding: 5px;
}
.box {
  background: tomato;
  width: 100px;
  height: 100px;
  margin: 10px;
}
<div class="justify-content">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>

Align-content

align-content is used to align the items inside the flexbox along the cross-axis. Note that it applies to Multi-line containers

.align-content {
  display: flex;
  align-content: center;
  flex-wrap: wrap;
  height: 500px;
  width: 500px;
  background: lightgray;
  padding: 5px;
}
.box {
  background: tomato;
  width: 100px;
  height: 100px;
  margin: 10px;
}
<div class="align-content">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>

Align-items

align-items has the same functionality as align-content but the difference is that it works to center every single-line container instead of centering the whole container. Check that in the snippet, the whole container is divided into 250 pixels height each and centered within, while in align-content it is centered within 500 pixels height of the row.

.align-items {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  height: 500px;
  width: 500px;
  background: lightgray;
  padding: 5px;
}
.box {
  background: tomato;
  width: 100px;
  height: 100px;
  margin: 10px;
}
<div class="align-items">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>
m4n0
  • 29,823
  • 27
  • 76
  • 89
  • Hi Manoj, thanks for your answer! When you say "Align-content is used to align the items inside the flexbox along the cross-axis which is y-axis if you take a graph", isn't this actually what `align-items` is supposed to do? That's exactly why I'm so confused. – Pensierinmusica Jul 07 '15 at 09:14
  • `align-content` works for Multi-line container. `align-items` work for single-line container :) – m4n0 Jul 07 '15 at 09:25
  • I think I'm starting to get the whole thing, although I still find it somewhat confusing and not explained in a simple way in the docs. Thanks! – Pensierinmusica Jul 07 '15 at 09:27
  • I have edited the code again to show the parent container which is set the flex property. Let me know if it isn't easy for you again. – m4n0 Jul 07 '15 at 09:44
  • Hi Manoj, do you think it would be possible to achieve [a layout identical to this one](http://the-echoplex.net/flexyboxes/?fixed-height=on&display=flex&flex-direction=column&flex-wrap=nowrap&justify-content=space-between&align-items=stretch&align-content=stretch&order%5B%5D=0&flex-grow%5B%5D=0&flex-shrink%5B%5D=1&flex-basis%5B%5D=auto&align-self%5B%5D=auto&order%5B%5D=0&flex-grow%5B%5D=1&flex-shrink%5B%5D=1&flex-basis%5B%5D=auto&align-self%5B%5D=auto&order%5B%5D=0&flex-grow%5B%5D=0&flex-shrink%5B%5D=1&flex-basis%5B%5D=auto&align-self%5B%5D=auto), but using `flex-direction: row`? – Pensierinmusica Jul 07 '15 at 22:45
  • I didn't get you. You want 3 boxes with one aligned to the right and others left? Opening a new question might help :) – m4n0 Jul 07 '15 at 22:47
  • Not exactly. I wonder if it's possible to achieve a layout identical to the one posted above, but using `flex-direction: row` instead of `column`. The layout consists of three boxes where the first one is pinned to the top, the third one is pinned to the bottom, and the second one takes all the remaining space in the middle. If you know how to do it, it'd be great to post the resulting link you obtain using Flexy Boxes, so I can take a look on it. Thanks! – Pensierinmusica Jul 07 '15 at 22:53
  • p.s. The closest I get so far is [this](http://the-echoplex.net/flexyboxes/?fixed-height=on&display=flex&flex-direction=row&flex-wrap=wrap&justify-content=center&align-items=flex-start&align-content=stretch&order%5B%5D=0&flex-grow%5B%5D=0&flex-shrink%5B%5D=1&flex-basis%5B%5D=100%25&align-self%5B%5D=auto&order%5B%5D=0&flex-grow%5B%5D=0&flex-shrink%5B%5D=1&flex-basis%5B%5D=100%25&align-self%5B%5D=stretch&order%5B%5D=0&flex-grow%5B%5D=0&flex-shrink%5B%5D=1&flex-basis%5B%5D=100%25&align-self%5B%5D=flex-end), but it still has some issues as you can see comparing it with the other one. – Pensierinmusica Jul 07 '15 at 22:56