951

Is there a more flexbox-ish way to right-align "Contact" than to use position: absolute?

.main {
  display: flex;
}

.a,
.b,
.c {
  background: #efefef;
  border: 1px solid #999;
}

.b {
  flex: 1;
  text-align: center;
}

.c {
  position: absolute;
  right: 0;
}
<h2>With title</h2>
<div class="main">
  <div class="a"><a href="#">Home</a></div>
  <div class="b"><a href="#">Some title centered</a></div>
  <div class="c"><a href="#">Contact</a></div>
</div>

<h2>Without title</h2>
<div class="main">
  <div class="a"><a href="#">Home</a></div>
  <!--<div class="b"><a href="#">Some title centered</a></div>-->
  <div class="c"><a href="#">Contact</a></div>
</div>

http://jsfiddle.net/vqDK9/

biberman
  • 5,606
  • 4
  • 11
  • 35
Mark Boulder
  • 13,577
  • 12
  • 48
  • 78

14 Answers14

1467

A more flex approach would be to use an auto left margin (flex items treat auto margins a bit differently than when used in a block formatting context).

.c {
    margin-left: auto;
}

Updated fiddle:

.main { display: flex; }
.a, .b, .c { background: #efefef; border: 1px solid #999; }
.b { flex: 1; text-align: center; }
.c {margin-left: auto;}
<h2>With title</h2>
<div class="main">
    <div class="a"><a href="#">Home</a></div>
    <div class="b"><a href="#">Some title centered</a></div>
    <div class="c"><a href="#">Contact</a></div>
</div>
<h2>Without title</h2>
<div class="main">
    <div class="a"><a href="#">Home</a></div>
    <!--<div class="b"><a href="#">Some title centered</a></div>-->
    <div class="c"><a href="#">Contact</a></div>
</div>
<h1>Problem</h1>
<p>Is there a more flexbox-ish way to right align "Contact" than to use position absolute?</p>
Nitin Bisht
  • 5,053
  • 4
  • 14
  • 26
Adrift
  • 58,167
  • 12
  • 92
  • 90
  • 2
    Thanks. Would you personally prefer this over Yohann Tilotti's display table method above? If so, why? – Mark Boulder Mar 16 '14 at 04:19
  • 6
    @MarkBoulder: For compatibility reasons his method is better, but if you're already using flexbox my answer would make more sense. – Adrift Mar 16 '14 at 11:46
  • Compatibility reasons aside then? – Mark Boulder Mar 16 '14 at 14:15
  • 4
    @MarkBoulder: They both accomplish the same thing in this case. The advantage would be having other properties (and behaviour) associated with flex items that the table approach doesn't have ([`flex`](http://www.w3.org/TR/css3-flexbox/#flex), [`order`](http://www.w3.org/TR/css3-flexbox/#order-property), etc). – Adrift Mar 16 '14 at 14:38
  • 1
    speed readers note "margin-left: auto" aligns to the right, not the left. – Alexander Taylor Oct 18 '16 at 01:23
  • 3
    This should be the accepted answer. Because `justify-content: space-between;` only accomplishes that you want if you only have 2 items in your flex container (first item would be on the left and second one would be to the right). But for more than 2 items, to only align some on the right, this is the correct approach! – MrCroft Apr 14 '17 at 10:56
  • 1
    This works better than the accepted answer if your items need to have different widths. `justify-content: space-between;` will make all items to have the same width by default. http://imgur.com/a/Fhvyh – chh Apr 18 '17 at 07:27
  • This does not work if you have multiple elements you want float to the right, the elements end being spaced out - any suggestions ? – Daniel Sokolowski Jul 24 '17 at 17:02
  • Holy crap, that worked. That is magic. @DanielSokolowski I needed several items that I wanted to be aligned to the right, so i just wrapped them in a container, and applied the style to that. – Justin Aug 05 '17 at 21:43
  • 3
    If you can not wrap the elements and you need to float say the last three right, target the 3rd one from the last only with this `margin-left: auto;` style. – Daniel Sokolowski Aug 06 '17 at 22:31
  • 2
    @Justin figured it out, no need to wrap them - I couldn't in my case. The solution was to target the 1st of the three items only with `margin-left: auto;`. – Daniel Sokolowski Sep 04 '17 at 20:01
  • A heads up about margin being different on flex items is good, a list of what is different would be great! Since this answer comes up very fast in search, could we get a bit more info? I hate blindly using the code... – Salketer Oct 29 '19 at 08:05
581

Here you go. Set justify-content: space-between on the flex container.

.main { 
    display: flex; 
    justify-content: space-between;
  }
.a, .b, .c { background: #efefef; border: 1px solid #999; }
.b { text-align: center; }
<h2>With title</h2>
<div class="main">
    <div class="a"><a href="#">Home</a></div>
    <div class="b"><a href="#">Some title centered</a></div>
    <div class="c"><a href="#">Contact</a></div>
</div>
<h2>Without title</h2>
<div class="main">
    <div class="a"><a href="#">Home</a></div>
<!--     <div class="b"><a href="#">Some title centered</a></div> -->
    <div class="c"><a href="#">Contact</a></div>
</div>
Kevin Suttle
  • 8,358
  • 3
  • 33
  • 37
  • 401
    Or `justify-content: flex-end` – B T Mar 17 '17 at 00:21
  • 1
    Try setting the width of .c to 300px. The title is no longer centered. So yes, this answers the question, but this breaks the design. – Agamemnus May 11 '17 at 00:03
  • 34
    Note that this doesn't always work the way you may expect, like when there's a `.c::after` pseudo-element. In my experience, `margin-left: auto;` is the way to go. – Will Nov 05 '17 at 04:06
  • 18
    Or `flex-flow: row-reverse;` – jchook Feb 09 '18 at 01:21
  • 23
    I don't see this being a correct answer if you wan't to align just one item in a flex container. – Foxhoundn Jan 22 '19 at 00:01
  • If there is only one element in the container and the container is full width then the @jchook answer works best. `.container { display: flex; flex-flow: row-reverse; }` – Etienne Marais Apr 11 '19 at 09:24
  • 1
    `justify-content: space-between;` just spaces out the flex children. `justify-content: flex-end` is the solution that worked for me – Chris Jul 02 '19 at 14:41
  • @Will your solution works for me because it stays on the right even if there are no flex elements in the container. – Nathaniel Flick Aug 22 '19 at 02:49
  • 1
    `.b { text-align: center; }` is redundant – luukvhoudt Oct 23 '19 at 15:13
  • That does not work with `flex-direction: column;` so items should have `align-self` that does not support this feature or right and left. I know the solution is `flex-end` but for `direction: rtl` that makes the problem because in that case `flex-end` is left! P.S I should say also `align-items` do not have that `space-between` thingy. – Amir2mi Jun 01 '21 at 21:07
  • @BT -- Accidently ran into this post and saw your comment, getting 350+ upvotes, and still it doesn't solve what is asked for. Amazing how people _believe_ that something can be correct before testing it. – Asons Dec 12 '21 at 19:46
66

You can also use a filler to fill the remaining space.

<div class="main">
    <div class="a"><a href="#">Home</a></div>
    <div class="b"><a href="#">Some title centered</a></div>
    <div class="filler"></div>
    <div class="c"><a href="#">Contact</a></div>
</div>

.filler{
    flex-grow: 1;
}

I have updated the solution with 3 different versions. This because of the discussion of the validity of using an additional filler element. If you run the code snipped you see that all solutions do different things. For instance setting the filler class on item b will make this item fill the remaining space. This has the benefit that there is no 'dead' space that is not clickable.

Update: now with display grid (just for fun)

<div class="mainfiller">
    <div class="a"><a href="#">Home</a></div>
    <div class="b"><a href="#">Some title centered</a></div>
    <div class="filler"></div>
    <div class="c"><a href="#">Contact</a></div>
</div>

<div class="mainfiller">
    <div class="a"><a href="#">Home</a></div>
    <div class="filler b"><a href="#">Some title centered</a></div>
    <div class="c"><a href="#">Contact</a></div>
</div>

<div class="main">
    <div class="a"><a href="#">Home</a></div>
    <div class="b"><a href="#">Some title centered</a></div>
    <div class="c"><a href="#">Contact</a></div>
</div>

<div class="main-grid">
    <div class="a"><a href="#">Home</a></div>
    <div class="b text-centered"><a href="#">Some title centered</a></div>
    <div class="c"><a href="#">Contact</a></div>
</div>
<style>
.main { display: flex; justify-content: space-between; }
.mainfiller { display: flex; }
.main-grid { display: grid; grid-template-columns: min-content 1fr min-content; }
.text-centered { text-align: center; }
.filler{flex-grow:1; text-align:center}
.a, .b, .c { background: yellow; border: 1px solid #999; }
</style>
Arno van Lieshout
  • 1,570
  • 1
  • 13
  • 19
  • 7
    Finally someone who understands flexbox – Kokodoko Aug 14 '17 at 12:05
  • 25
    @Kokodoko yeah, using one more non-semantic html element to move another element is the top of understanding flexbox... – Zanshin13 Aug 14 '17 at 13:31
  • @Zanshin13 The other answers all write so much extra css that you might as well leave out the flex container and code the whole thing yourself :) – Kokodoko Aug 15 '17 at 14:12
  • 3
    @Kokodoko `justify-content: space-between` is "so much" css, seriously? No need for further comments (but if you want - welcome to chat). This answer has its right to be here, because it *is* a solution. But definitely *not* optimal one. Idk, maybe you did't notice but most of css from another answers are OP's and answers actually reduce (a little bit) amount of author's css. This answer does not have less css then others (will not work without OP's css - https://jsfiddle.net/63ma3b56/). But it has one more html element. – Zanshin13 Aug 15 '17 at 15:01
  • Not very pretty using "filler" just to push an element to the end – Florestan Korp Jan 08 '22 at 18:15
  • People negatively associate "filler" with the early years of 1px gap filling pixels. The point of this is that the most "flexbox" answer is to utilize flex-grow appropriately and this answer gets to that. You can set flex-grow either on a "filler" or the preceding element depending on your needs - But this answer is the most correct. – david Jan 27 '22 at 11:18
56

If you want to use flexbox for this, you should be able to, by doing this (display: flex on the container, flex: 1 on the items, and text-align: right on .c):

.main { display: flex; }
.a, .b, .c {
    background: #efefef;
    border: 1px solid #999;
    flex: 1;
}
.b { text-align: center; }
.c { text-align: right; }

...or alternatively (even simpler), if the items don't need to meet, you can use justify-content: space-between on the container and remove the text-align rules completely:

.main { display: flex; justify-content: space-between; }
.a, .b, .c { background: #efefef; border: 1px solid #999; }

Here's a demo on Codepen to allow you to quickly try the above.

Nick F
  • 9,781
  • 7
  • 75
  • 90
56

Or you could just use justify-content: flex-end

.main { display: flex; }
.c { justify-content: flex-end; }
Melchia
  • 22,578
  • 22
  • 103
  • 117
30

As easy as

.main {
    display: flex;
    flex-direction:row-reverse;
}
Shreyash.K
  • 487
  • 4
  • 14
CESCO
  • 7,305
  • 8
  • 51
  • 83
  • I discovered this independently and came to check stack overflow to see if it was legit. And it turns out, this is the only suggestion on this page that would work for me. I think a lot of that comes down to the fact that this flex, which is like the third nested one, has a single flex child (an `ul`). That also means reversing it didn't mess with list/tab order! – tannerbaum Jul 22 '22 at 22:01
22

margin-left: auto works well. But clean flex box solution would be space-between in the main class. Space between works well if there is two or more elements. I have added a solution for single element as well.

.main { display: flex; justify-content: space-between; }
.a, .b, .c { background: #efefef; border: 1px solid #999; padding: 0.25rem; margin: 0.25rem;}
.b { flex: 1; text-align: center; }

.c-wrapper {
  display: flex;
  flex: 1;
  justify-content: flex-end;
}

.c-wrapper2 {
  display: flex;
  flex: 1;
  flex-flow: row-reverse;
}
<div class="main">
    <div class="a"><a href="#">Home</a></div>
    <div class="b"><a href="#">Some title centered</a></div>
    <div class="c"><a href="#">Contact</a></div>
</div>

<div class="main">
    <div class="a"><a href="#">Home</a></div>
    <div class="c"><a href="#">Contact</a></div>
</div>

<div class="main">
    <div class="c-wrapper">
      <a class="c" href="#">Contact</a>
      <a class="c" href="#">Contact2</a>
    </div>
</div>
<div class="main">
    <div class="c-wrapper2">
      <span class="c">Contact</span>
      <span class="c">Contact2</span>
    </div>
</div>
Monir Khan
  • 425
  • 4
  • 13
17

Add the following CSS class to your stylesheet:

.my-spacer {
    flex: 1 1 auto;
}

Place an empty element between the element on the left and the element you wish to right-align:

<span class="my-spacer"></span>

Shreyash.K
  • 487
  • 4
  • 14
andreisrob
  • 1,615
  • 15
  • 11
  • For those who don't merely want to right align a single element, but may want to left align one element, and right align another (within the same flex layout) this is the way to go! – Sensei James Jan 10 '19 at 19:55
13

If you need one item to be left aligned (like a header) but then multiple items right aligned (like 3 images), then you would do something like this:

h1 {
   flex-basis: 100%; // forces this element to take up any remaining space
}

img {
   margin: 0 5px; // small margin between images
   height: 50px; // image width will be in relation to height, in case images are large - optional if images are already the proper size
}

Here's what that will look like (only relavent CSS was included in snippet above)

enter image description here

TetraDev
  • 16,074
  • 6
  • 60
  • 61
10

'justify-content: flex-end' worked within price box container.

.price-box {
    justify-content: flex-end;
}
Mohammad Adeel
  • 109
  • 1
  • 4
6

For those using Angular and Flex-Layout, use the following on the flex-item container:

<div fxLayout="row" fxLayoutAlign="flex-end">

See fxLayoutAlign docs here and the full fxLayout docs here.

Lindauson
  • 2,963
  • 1
  • 30
  • 33
4

I find that adding 'justify-content: flex-end' to the flex container solves the problem while 'justify-content: space-between' doesnt do anything.

nights
  • 411
  • 3
  • 9
4

Example code based on answer by TetraDev

Images on right:

* {
  outline: .4px dashed red;
}

.main {
  display: flex;
  flex-direction: row;
  align-items: center;
}

h1 {
  flex-basis: 100%;
}

img {
  margin: 0 5px;
  height: 30px;
}
<div class="main">
  <h1>Secure Payment</h1>
  <img src="https://i.stack.imgur.com/i65gn.png">
  <img src="https://i.stack.imgur.com/i65gn.png">
</div>

Images on left:

* {
  outline: .4px dashed red;
}

.main {
  display: flex;
  flex-direction: row;
  align-items: center;
}

h1 {
  flex-basis: 100%;
  text-align: right;
}

img {
  margin: 0 5px;
  height: 30px;
}
<div class="main">
  <img src="https://i.stack.imgur.com/i65gn.png">
  <img src="https://i.stack.imgur.com/i65gn.png">
  <h1>Secure Payment</h1>
</div>
1.21 gigawatts
  • 16,517
  • 32
  • 123
  • 231
1

Set justify-content: space-between on the flex container.

VIktoriyaV
  • 21
  • 4