I would like to have A
B
and C
aligned in the middle.
How can I get D
to go completely to the right?
BEFORE:
AFTER:
What's the best practice for doing this?
ul {
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
li:last-child {
background: #ddd;
/* magic to throw to the right*/
}
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
Very clear question. I couldn't help but post the answer after a few hours of digging. We Could of solved this with tables, table-cell, absolute positions, transforms but we just had to do it with flexbox :)
http://codepen.io/rgfx/pen/BLorgd
I expanded on Michael_B's answer
Here with the help of SASS as a codepen
The accepted answer can be changed a bit because you can use grid template areas and do it without fake element
Below are five options for achieving this layout:
flex: 1
Method #1: CSS Positioning Properties
Apply
position: relative
to the flex container.Apply
position: absolute
to item D.Now this item is absolutely positioned within the flex container.
More specifically, item D is removed from the document flow but stays within the bounds of the nearest positioned ancestor.
Use the CSS offset properties
top
andright
to move this element into position.One caveat to this method is that some browsers may not completely remove an absolutely-positioned flex item from the normal flow. This changes the alignment in a non-standard, unexpected way. More details: Absolutely positioned flex item is not removed from the normal flow in IE11
Method #2: Flex Auto Margins & Invisible Flex Item (DOM element)
With a combination of
auto
margins and a new, invisible flex item the layout can be achieved.The new flex item is identical to item D and is placed at the opposite end (the left edge).
More specifically, because flex alignment is based on the distribution of free space, the new item is a necessary counterbalance to keep the three middle boxes horizontally centered. The new item must be the same width as the existing D item, or the middle boxes won't be precisely centered.
The new item is removed from view with
visibility: hidden
.In short:
D
element.auto
margins to keepA
,B
andC
centered, with bothD
elements creating equal balance from both ends.visibility: hidden
to the duplicateD
Method #3: Flex Auto Margins & Invisible Flex Item (pseudo-element)
This method is similar to #2, except it's cleaner semantically and the width of
D
must be known.D
.::before
.auto
margins to keepA
,B
andC
perfectly centered, with the pseudo andD
elements creating equal balance from both ends.Method #4: Add
flex: 1
to left and right itemsStarting with Method #2 or #3 above, instead of worrying about equal width for the left and right items to maintain equal balance, just give each one
flex: 1
. This will force them both to consume available space, thus centering the middle item.You can then add
display: flex
to individual items in order to align their content.NOTE about using this method with
min-height
: Currently in Chrome, Firefox, Edge and possibly other browsers, the shorthand ruleflex: 1
breaks down to this:flex-grow: 1
flex-shrink: 1
flex-basis: 0%
That percentage unit (%) on
flex-basis
causes this method to break whenmin-height
is used on the container. This is because, as a general rule, percentage heights on the children require an explicitheight
property setting on the parent.This is an old CSS rule dating back to 1998 (CSS Level 2) which is still in effect in many browsers to some degree or another. For complete details see here and here.
Here's an illustration of the problem posted in the comments by user2651804:
The solution is to not use the percentage unit. Try
px
or just nothing at all (which is what the spec actually recommends, despite the fact that at least some of the major browsers have appended a percentage unit for whatever reason).Method #5: CSS Grid Layout
This may be the cleanest and most efficient method. There is no need for absolute positioning, fake elements or other hackery.
Simply create a grid with multiple columns. Then position your items in the middle and end columns. Basically, just leave the first column empty.