277

https://jsfiddle.net/vhem8scs/

Is it possible to have two items align left and one item align right with flexbox? The link shows it more clearly. The last example is what I want to achieve.

In flexbox I have one block of code. With float I have four blocks of code. That is one reason why I prefer flexbox.

HTML

<div class="wrap">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
</div>

<!-- DESIRED RESULT -->

<div class="result">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
</div>

CSS

.wrap {
  display: flex;
  background: #ccc;
  width: 100%;
  justify-content: space-between;
}

.result {
  background: #ccc;
  margin-top: 20px;
}

.result:after {
  content: '';
  display: table;
  clear: both;
}

.result div {
  float: left;
}
.result div:last-child {
  float: right;
}
isherwood
  • 46,000
  • 15
  • 100
  • 132
Jens Törnell
  • 18,167
  • 36
  • 100
  • 168

3 Answers3

661

To align one flex child to the right set it withmargin-left: auto;

From the flex spec:

One use of auto margins in the main axis is to separate flex items into distinct "groups". The following example shows how to use this to reproduce a common UI pattern - a single bar of actions with some aligned on the left and others aligned on the right.

.wrap div:last-child {
  margin-left: auto;
}

Updated fiddle

.wrap {
  display: flex;
  background: #ccc;
  width: 100%;
  justify-content: space-between;
}
.wrap div:last-child {
  margin-left: auto;
}
.result {
  background: #ccc;
  margin-top: 20px;
}
.result:after {
  content: '';
  display: table;
  clear: both;
}
.result div {
  float: left;
}
.result div:last-child {
  float: right;
}
<div class="wrap">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
</div>

<!-- DESIRED RESULT -->
<div class="result">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
</div>

Note:

You could achieve a similar effect by setting flex-grow:1 on the middle flex item (or shorthand flex:1) which would push the last item all the way to the right. (Demo)

The obvious difference however is that the middle item becomes bigger than it may need to be. Add a border to the flex items to see the difference.

Demo

.wrap {
  display: flex;
  background: #ccc;
  width: 100%;
  justify-content: space-between;
}
.wrap div {
  border: 3px solid tomato;
}
.margin div:last-child {
  margin-left: auto;
}
.grow div:nth-child(2) {
  flex: 1;
}
.result {
  background: #ccc;
  margin-top: 20px;
}
.result:after {
  content: '';
  display: table;
  clear: both;
}
.result div {
  float: left;
}
.result div:last-child {
  float: right;
}
<div class="wrap margin">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
</div>

<div class="wrap grow">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
</div>

<!-- DESIRED RESULT -->
<div class="result">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
</div>
Danield
  • 106,624
  • 34
  • 201
  • 230
  • Thanks! I tried another thing that worked before I read this. It was to set flex-grow: 1 on the element that should push the other. It worked as well. Do you know which of them are better and why? – Jens Törnell Feb 08 '16 at 15:09
  • 2
    Great answer. So the margin takes up no extra space, and the flex: 1 does. Cool! – Jens Törnell Feb 08 '16 at 15:59
  • 4
    @JensTörnell, the `auto` margin uses the empty space in the container to separate the flex items. The `flex-grow`/`flex` property takes that empty space, gives it to the flex item, which expands by that amount. As mentioned by Danield, the latter method makes flex item TWO bigger, which you may not want. – Michael Benjamin Feb 08 '16 at 20:12
  • 19
    Not all heroes wear capes. – Tom Apr 09 '18 at 18:46
  • Any way to align more that one item to the right (or left)? – user1063287 Jun 06 '18 at 07:46
  • 2
    @user1063287 to align multiple elements to the right just apply margin-left: auto on the first element which need to be aligned right. So let's say you want the last 4 elements aligned to the right, you'd do this: `div:nth-last-child(4) { margin-left: auto }` https://codepen.io/danield770/pen/ERyoar – Danield Jun 06 '18 at 07:53
  • Thank you! Also realised spflow's answer below covers this scenario as well. – user1063287 Jun 06 '18 at 08:04
44

For a terse, pure flexbox option, group the left-aligned items and the right-aligned items:

<div class="wrap">
  <div>
    <span>One</span>
    <span>Two</span>
  </div>
  <div>Three</div>
</div>

and use space-between:

.wrap {
  display: flex;
  background: #ccc;
  justify-content: space-between;
}

This way you can group multiple items to the right(or just one).

https://jsfiddle.net/c9mkewwv/3/

spflow
  • 614
  • 5
  • 9
  • 1
    This works, but if you don't change the elements inside each group to be `display: inline;` or `display: inline-block;`, then they get stacked instead of all in a row like flexbox otherwise would have them. – The DIMM Reaper Sep 21 '17 at 18:46
  • @TheDIMMReaper I'm not sure I see the problem. Could you expand? – spflow Sep 26 '17 at 17:57
  • I just mean how you changed the tags immediately wrapping `One` and `Two` from `div`s to `span`s - if they were still `display: block;` then they would flow to separate lines. Since the OP originally had `div`s, I just wanted to point out that simply putting them inside another `div` wouldn't work without changing the display of the original tags. – The DIMM Reaper Sep 26 '17 at 18:15
  • 1
    Yes, since the elements are now down a level, `display: flex` is no longer influencing their layout. If you want to use div's, yes, `inline` or `inline-block` would work. But also, obviously, `flex`, since we're using it for the default `flex-direction: row` with parent div's already. ex. https://jsfiddle.net/ynbb5964/2/ – spflow Sep 28 '17 at 04:16
  • Thanks, I tried align-self: flex-end, but why it doesn't work? – Anand Mar 14 '18 at 05:35
  • Oh ok, just found that align-self only works on cross-axis. – Anand Mar 14 '18 at 05:44
3

To align some elements (headerElement) in the center and the last element to the right (headerEnd).

.headerElement {
    margin-right: 5%;
    margin-left: 5%;
}
.headerEnd{
    margin-left: auto;
}