Center and right align flexbox elements2019 Community Moderator ElectionHow to center-align one flex item and right-align another using FlexboxCenter flex items with one at the end of the rowCSS: flexbox first child to left and rest to centerCSS Flex all center except single right horizontally aligned elementCenter one element and right-align another on the same rowHow to make 1 div centre align and other float right using CSSHow to align icon to the left and text to the center by using flex?Justify-self is not working when I want to align content in the centerHow to align 2 columns in flexbox layout, one centered of parent and one left of parentHow to center inner div?How to horizontally center a <div>?How to align checkboxes and their labels consistently cross-browsersVertically align text next to an image?How to move an element into another element?How do I vertically center text with CSS?Flexbox: center horizontally and verticallyvertical-align with Bootstrap 3How to Right-align flex item?In CSS Flexbox, why are there no “justify-items” and “justify-self” properties?How to center-align one flex item and right-align another using Flexbox
What's the best tool for cutting holes into duct work?
Affine transformation of circular arc in 3D
Why is my explanation wrong?
Iron deposits mined from under the city
Python 3.6+ function to ask for a multiple-choice answer
“I had a flat in the centre of town, but I didn’t like living there, so …”
I can't die. Who am I?
Why do we call complex numbers “numbers” but we don’t consider 2 vectors numbers?
Using the imperfect indicative vs. subjunctive with si
Ultrafilters as a double dual
The need of reserving one's ability in job interviews
I've given my players a lot of magic items. Is it reasonable for me to give them harder encounters?
The (Easy) Road to Code
Quitting employee has privileged access to critical information
Computing the volume of a simplex-like object with constraints
Does the US political system, in principle, allow for a no-party system?
Why are special aircraft used for the carriers in the United States Navy?
What's the difference between Compensation, Indemnity, and Reparations?
Should I use HTTPS on a domain that will only be used for redirection?
Can a space-faring robot still function over a billion years?
Is every open circuit a capacitor?
Giving a talk in my old university, how prominently should I tell students my salary?
If nine coins are tossed, what is the probability that the number of heads is even?
Is this nominative case or accusative case?
Center and right align flexbox elements
2019 Community Moderator ElectionHow to center-align one flex item and right-align another using FlexboxCenter flex items with one at the end of the rowCSS: flexbox first child to left and rest to centerCSS Flex all center except single right horizontally aligned elementCenter one element and right-align another on the same rowHow to make 1 div centre align and other float right using CSSHow to align icon to the left and text to the center by using flex?Justify-self is not working when I want to align content in the centerHow to align 2 columns in flexbox layout, one centered of parent and one left of parentHow to center inner div?How to horizontally center a <div>?How to align checkboxes and their labels consistently cross-browsersVertically align text next to an image?How to move an element into another element?How do I vertically center text with CSS?Flexbox: center horizontally and verticallyvertical-align with Bootstrap 3How to Right-align flex item?In CSS Flexbox, why are there no “justify-items” and “justify-self” properties?How to center-align one flex item and right-align another using Flexbox
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>
https://jsfiddle.net/z44p7bsx/
html css css3 flexbox
add a comment |
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>
https://jsfiddle.net/z44p7bsx/
html css css3 flexbox
add a comment |
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>
https://jsfiddle.net/z44p7bsx/
html css css3 flexbox
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>
https://jsfiddle.net/z44p7bsx/
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>
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>
html css css3 flexbox
html css css3 flexbox
edited Sep 5 '16 at 18:45
Michael_B
154k48250360
154k48250360
asked Aug 15 '16 at 1:13
hazyredhazyred
3721412
3721412
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
Below are five options for achieving this layout:
- CSS Positioning
- Flexbox with Invisible DOM Element
- Flexbox with Invisible Pseudo-Element
- Flexbox with
flex: 1
- CSS Grid Layout
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
and right
to move this element into position.
li:last-child
position: absolute;
top: 0;
right: 0;
background: #ddd;
ul
position: relative;
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
li
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
p
text-align: center;
margin-top: 0;
span
background-color: aqua;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
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:
- Create a duplicate of the
D
element. - Place it at the beginning of the list.
- Use flex
auto
margins to keepA
,B
andC
centered, with bothD
elements creating equal balance from both ends. - Apply
visibility: hidden
to the duplicateD
li:first-child
margin-right: auto;
visibility: hidden;
li:last-child
margin-left: auto;
background: #ddd;
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;
p text-align: center; margin-top: 0;
span background-color: aqua;
<ul>
<li>D</li><!-- new; invisible spacer item -->
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
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.
- Create a pseudo-element with the same width as
D
. - Place it at the start of the container with
::before
. - Use flex
auto
margins to keepA
,B
andC
perfectly centered, with the pseudo andD
elements creating equal balance from both ends.
ul::before
content:"D";
margin: 1px auto 1px 1px;
visibility: hidden;
padding: 5px;
background: #ddd;
li:last-child
margin-left: auto;
background: #ddd;
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;
p text-align: center; margin-top: 0;
span background-color: aqua;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
Method #4: Add flex: 1
to left and right items
Starting 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 rule flex: 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 when min-height
is used on the container. This is because, as a general rule, percentage heights on the children require an explicit height
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:
#flex-container
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
#flex-container>div
background: orange;
margin: 5px;
#flex-container>div:first-child
flex: 1;
#flex-container::after
content: "";
flex: 1;
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
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).
#flex-container
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
#flex-container > div
background: orange;
margin: 5px;
/* OVERRIDE THE BROWSER SETTING IN THE FLEX PROPERTY */
#flex-container > div:first-child
flex: 1;
flex-basis: 0;
#flex-container::after
content: "";
flex: 1;
flex-basis: 0;
/* OR... JUST SET THE LONG-HAND PROPERTIES INDIVIDUALLY
#flex-container > div:first-child
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
#flex-container::after
content: "";
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
*/
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
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.
ul
display: grid;
grid-template-columns: 1fr repeat(3, auto) 1fr;
grid-column-gap: 5px;
justify-items: center;
li:nth-child(1) grid-column-start: 2;
li:nth-child(4) margin-left: auto;
/* for demo only */
ul padding: 0; margin: 0; list-style: none;
li padding: 5px; background: #aaa;
p text-align: center;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>| true center |</span></p>
2
great answer! Tested all 5 solutions and every one of it is viable!
– Mobiletainment
Jan 14 '18 at 18:15
I have a problem with method 4 when usingmin-width/min-height
for my flex-container. Theflex: 1
children of such a parent do not get equal width/height. Any way around that?
– user2651804
Mar 26 '18 at 9:45
@user2651804, I updated my answer with a review of the problem. See Method #4.
– Michael_B
Mar 26 '18 at 22:09
2
Love the use of visibility:hidden in Method #2 - so clever! For the first time got a practical use for hidden :D
– small mammal
May 27 '18 at 22:35
2
One of the best answers I've seen here at Stackoverflow.
– Philip
Aug 29 '18 at 8:00
|
show 4 more comments
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 :)
.parent
display: flex;
justify-content: flex-end;
.center
margin: auto;
http://codepen.io/rgfx/pen/BLorgd
4
This doesn't truly center the middle items because it only factors in the remaining space, not the entire space. codepen.io/anon/pen/QKGrRk
– Michael_B
Sep 20 '16 at 23:35
@Michael_B, your right didn't notice that, my bad. Back to using absolute positions :( Maybe with your high rep you should set a bounty get this resolved for good. I would but I have a very low rep, even lower now trying to help you.
– rgfx
Sep 22 '16 at 18:29
No bounty is going to add a new behavior to the flexbox model, the, by Michael_B, given answer is as good as it gets...today.
– LGSon
May 16 '17 at 12:07
add a comment |
I expanded on Michael_B's answer
.center-flex__2-of-3 > :nth-child(1), .center-flex__2-of-3 > :nth-child(3)
flex: 1;
.center-flex__2-of-3 > :nth-child(1)
justify-content: flex-start;
.center-flex__2-of-3 > :nth-child(3)
justify-content: flex-end;
.center-flex__1-of-2 > :nth-child(1)
margin: auto;
.center-flex__1-of-2 > :nth-child(2)
flex: 1;
justify-content: flex-end;
.center-flex__2-of-2 > :nth-child(1)
flex: 1;
justify-content: flex-start;
.center-flex__2-of-2 > :nth-child(2)
margin: auto;
.center-flex__1-of-2:before, .center-flex__1-of-1:before
content: '';
flex: 1;
.center-flex__1-of-1:after, .center-flex__2-of-2:after
content: '';
flex: 1;
[class*=center-flex]
display: flex;
list-style: none;
margin: 0;
padding: 0;
border: 10px solid rgba(0, 0, 0, 0.1);
[class*=center-flex] > *
display: flex;
li
padding: 3px 5px;
2 of 3
<ul class="center-flex__2-of-3">
<span>
<li>Accusamus</li>
<li>Porro</li>
</span>
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
1 of 2
<ul class="akex center-flex__1-of-2">
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
2 of 2
<ul class="akex center-flex__2-of-2">
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
</ul>
<br><br>
1 of 1
<ul class="center-flex__1-of-1">
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
</ul>
Here with the help of SASS as a codepen
add a comment |
The accepted answer can be changed a bit because you can use grid template areas and do it without fake element
grid-template-areas '. b c'
grid-template-columns: 1fr 1fr 1fr
the question is about flexbox not CSS grid and the porption of code you share will not give the intended result even using CSS grid.
– Temani Afif
Dec 8 '18 at 13:33
add a comment |
protected by Temani Afif Dec 8 '18 at 13:32
Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).
Would you like to answer one of these unanswered questions instead?
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
Below are five options for achieving this layout:
- CSS Positioning
- Flexbox with Invisible DOM Element
- Flexbox with Invisible Pseudo-Element
- Flexbox with
flex: 1
- CSS Grid Layout
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
and right
to move this element into position.
li:last-child
position: absolute;
top: 0;
right: 0;
background: #ddd;
ul
position: relative;
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
li
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
p
text-align: center;
margin-top: 0;
span
background-color: aqua;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
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:
- Create a duplicate of the
D
element. - Place it at the beginning of the list.
- Use flex
auto
margins to keepA
,B
andC
centered, with bothD
elements creating equal balance from both ends. - Apply
visibility: hidden
to the duplicateD
li:first-child
margin-right: auto;
visibility: hidden;
li:last-child
margin-left: auto;
background: #ddd;
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;
p text-align: center; margin-top: 0;
span background-color: aqua;
<ul>
<li>D</li><!-- new; invisible spacer item -->
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
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.
- Create a pseudo-element with the same width as
D
. - Place it at the start of the container with
::before
. - Use flex
auto
margins to keepA
,B
andC
perfectly centered, with the pseudo andD
elements creating equal balance from both ends.
ul::before
content:"D";
margin: 1px auto 1px 1px;
visibility: hidden;
padding: 5px;
background: #ddd;
li:last-child
margin-left: auto;
background: #ddd;
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;
p text-align: center; margin-top: 0;
span background-color: aqua;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
Method #4: Add flex: 1
to left and right items
Starting 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 rule flex: 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 when min-height
is used on the container. This is because, as a general rule, percentage heights on the children require an explicit height
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:
#flex-container
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
#flex-container>div
background: orange;
margin: 5px;
#flex-container>div:first-child
flex: 1;
#flex-container::after
content: "";
flex: 1;
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
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).
#flex-container
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
#flex-container > div
background: orange;
margin: 5px;
/* OVERRIDE THE BROWSER SETTING IN THE FLEX PROPERTY */
#flex-container > div:first-child
flex: 1;
flex-basis: 0;
#flex-container::after
content: "";
flex: 1;
flex-basis: 0;
/* OR... JUST SET THE LONG-HAND PROPERTIES INDIVIDUALLY
#flex-container > div:first-child
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
#flex-container::after
content: "";
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
*/
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
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.
ul
display: grid;
grid-template-columns: 1fr repeat(3, auto) 1fr;
grid-column-gap: 5px;
justify-items: center;
li:nth-child(1) grid-column-start: 2;
li:nth-child(4) margin-left: auto;
/* for demo only */
ul padding: 0; margin: 0; list-style: none;
li padding: 5px; background: #aaa;
p text-align: center;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>| true center |</span></p>
2
great answer! Tested all 5 solutions and every one of it is viable!
– Mobiletainment
Jan 14 '18 at 18:15
I have a problem with method 4 when usingmin-width/min-height
for my flex-container. Theflex: 1
children of such a parent do not get equal width/height. Any way around that?
– user2651804
Mar 26 '18 at 9:45
@user2651804, I updated my answer with a review of the problem. See Method #4.
– Michael_B
Mar 26 '18 at 22:09
2
Love the use of visibility:hidden in Method #2 - so clever! For the first time got a practical use for hidden :D
– small mammal
May 27 '18 at 22:35
2
One of the best answers I've seen here at Stackoverflow.
– Philip
Aug 29 '18 at 8:00
|
show 4 more comments
Below are five options for achieving this layout:
- CSS Positioning
- Flexbox with Invisible DOM Element
- Flexbox with Invisible Pseudo-Element
- Flexbox with
flex: 1
- CSS Grid Layout
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
and right
to move this element into position.
li:last-child
position: absolute;
top: 0;
right: 0;
background: #ddd;
ul
position: relative;
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
li
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
p
text-align: center;
margin-top: 0;
span
background-color: aqua;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
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:
- Create a duplicate of the
D
element. - Place it at the beginning of the list.
- Use flex
auto
margins to keepA
,B
andC
centered, with bothD
elements creating equal balance from both ends. - Apply
visibility: hidden
to the duplicateD
li:first-child
margin-right: auto;
visibility: hidden;
li:last-child
margin-left: auto;
background: #ddd;
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;
p text-align: center; margin-top: 0;
span background-color: aqua;
<ul>
<li>D</li><!-- new; invisible spacer item -->
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
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.
- Create a pseudo-element with the same width as
D
. - Place it at the start of the container with
::before
. - Use flex
auto
margins to keepA
,B
andC
perfectly centered, with the pseudo andD
elements creating equal balance from both ends.
ul::before
content:"D";
margin: 1px auto 1px 1px;
visibility: hidden;
padding: 5px;
background: #ddd;
li:last-child
margin-left: auto;
background: #ddd;
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;
p text-align: center; margin-top: 0;
span background-color: aqua;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
Method #4: Add flex: 1
to left and right items
Starting 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 rule flex: 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 when min-height
is used on the container. This is because, as a general rule, percentage heights on the children require an explicit height
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:
#flex-container
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
#flex-container>div
background: orange;
margin: 5px;
#flex-container>div:first-child
flex: 1;
#flex-container::after
content: "";
flex: 1;
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
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).
#flex-container
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
#flex-container > div
background: orange;
margin: 5px;
/* OVERRIDE THE BROWSER SETTING IN THE FLEX PROPERTY */
#flex-container > div:first-child
flex: 1;
flex-basis: 0;
#flex-container::after
content: "";
flex: 1;
flex-basis: 0;
/* OR... JUST SET THE LONG-HAND PROPERTIES INDIVIDUALLY
#flex-container > div:first-child
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
#flex-container::after
content: "";
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
*/
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
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.
ul
display: grid;
grid-template-columns: 1fr repeat(3, auto) 1fr;
grid-column-gap: 5px;
justify-items: center;
li:nth-child(1) grid-column-start: 2;
li:nth-child(4) margin-left: auto;
/* for demo only */
ul padding: 0; margin: 0; list-style: none;
li padding: 5px; background: #aaa;
p text-align: center;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>| true center |</span></p>
2
great answer! Tested all 5 solutions and every one of it is viable!
– Mobiletainment
Jan 14 '18 at 18:15
I have a problem with method 4 when usingmin-width/min-height
for my flex-container. Theflex: 1
children of such a parent do not get equal width/height. Any way around that?
– user2651804
Mar 26 '18 at 9:45
@user2651804, I updated my answer with a review of the problem. See Method #4.
– Michael_B
Mar 26 '18 at 22:09
2
Love the use of visibility:hidden in Method #2 - so clever! For the first time got a practical use for hidden :D
– small mammal
May 27 '18 at 22:35
2
One of the best answers I've seen here at Stackoverflow.
– Philip
Aug 29 '18 at 8:00
|
show 4 more comments
Below are five options for achieving this layout:
- CSS Positioning
- Flexbox with Invisible DOM Element
- Flexbox with Invisible Pseudo-Element
- Flexbox with
flex: 1
- CSS Grid Layout
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
and right
to move this element into position.
li:last-child
position: absolute;
top: 0;
right: 0;
background: #ddd;
ul
position: relative;
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
li
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
p
text-align: center;
margin-top: 0;
span
background-color: aqua;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
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:
- Create a duplicate of the
D
element. - Place it at the beginning of the list.
- Use flex
auto
margins to keepA
,B
andC
centered, with bothD
elements creating equal balance from both ends. - Apply
visibility: hidden
to the duplicateD
li:first-child
margin-right: auto;
visibility: hidden;
li:last-child
margin-left: auto;
background: #ddd;
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;
p text-align: center; margin-top: 0;
span background-color: aqua;
<ul>
<li>D</li><!-- new; invisible spacer item -->
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
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.
- Create a pseudo-element with the same width as
D
. - Place it at the start of the container with
::before
. - Use flex
auto
margins to keepA
,B
andC
perfectly centered, with the pseudo andD
elements creating equal balance from both ends.
ul::before
content:"D";
margin: 1px auto 1px 1px;
visibility: hidden;
padding: 5px;
background: #ddd;
li:last-child
margin-left: auto;
background: #ddd;
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;
p text-align: center; margin-top: 0;
span background-color: aqua;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
Method #4: Add flex: 1
to left and right items
Starting 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 rule flex: 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 when min-height
is used on the container. This is because, as a general rule, percentage heights on the children require an explicit height
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:
#flex-container
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
#flex-container>div
background: orange;
margin: 5px;
#flex-container>div:first-child
flex: 1;
#flex-container::after
content: "";
flex: 1;
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
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).
#flex-container
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
#flex-container > div
background: orange;
margin: 5px;
/* OVERRIDE THE BROWSER SETTING IN THE FLEX PROPERTY */
#flex-container > div:first-child
flex: 1;
flex-basis: 0;
#flex-container::after
content: "";
flex: 1;
flex-basis: 0;
/* OR... JUST SET THE LONG-HAND PROPERTIES INDIVIDUALLY
#flex-container > div:first-child
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
#flex-container::after
content: "";
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
*/
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
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.
ul
display: grid;
grid-template-columns: 1fr repeat(3, auto) 1fr;
grid-column-gap: 5px;
justify-items: center;
li:nth-child(1) grid-column-start: 2;
li:nth-child(4) margin-left: auto;
/* for demo only */
ul padding: 0; margin: 0; list-style: none;
li padding: 5px; background: #aaa;
p text-align: center;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>| true center |</span></p>
Below are five options for achieving this layout:
- CSS Positioning
- Flexbox with Invisible DOM Element
- Flexbox with Invisible Pseudo-Element
- Flexbox with
flex: 1
- CSS Grid Layout
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
and right
to move this element into position.
li:last-child
position: absolute;
top: 0;
right: 0;
background: #ddd;
ul
position: relative;
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
li
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
p
text-align: center;
margin-top: 0;
span
background-color: aqua;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
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:
- Create a duplicate of the
D
element. - Place it at the beginning of the list.
- Use flex
auto
margins to keepA
,B
andC
centered, with bothD
elements creating equal balance from both ends. - Apply
visibility: hidden
to the duplicateD
li:first-child
margin-right: auto;
visibility: hidden;
li:last-child
margin-left: auto;
background: #ddd;
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;
p text-align: center; margin-top: 0;
span background-color: aqua;
<ul>
<li>D</li><!-- new; invisible spacer item -->
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
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.
- Create a pseudo-element with the same width as
D
. - Place it at the start of the container with
::before
. - Use flex
auto
margins to keepA
,B
andC
perfectly centered, with the pseudo andD
elements creating equal balance from both ends.
ul::before
content:"D";
margin: 1px auto 1px 1px;
visibility: hidden;
padding: 5px;
background: #ddd;
li:last-child
margin-left: auto;
background: #ddd;
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;
p text-align: center; margin-top: 0;
span background-color: aqua;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
Method #4: Add flex: 1
to left and right items
Starting 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 rule flex: 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 when min-height
is used on the container. This is because, as a general rule, percentage heights on the children require an explicit height
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:
#flex-container
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
#flex-container>div
background: orange;
margin: 5px;
#flex-container>div:first-child
flex: 1;
#flex-container::after
content: "";
flex: 1;
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
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).
#flex-container
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
#flex-container > div
background: orange;
margin: 5px;
/* OVERRIDE THE BROWSER SETTING IN THE FLEX PROPERTY */
#flex-container > div:first-child
flex: 1;
flex-basis: 0;
#flex-container::after
content: "";
flex: 1;
flex-basis: 0;
/* OR... JUST SET THE LONG-HAND PROPERTIES INDIVIDUALLY
#flex-container > div:first-child
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
#flex-container::after
content: "";
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
*/
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
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.
ul
display: grid;
grid-template-columns: 1fr repeat(3, auto) 1fr;
grid-column-gap: 5px;
justify-items: center;
li:nth-child(1) grid-column-start: 2;
li:nth-child(4) margin-left: auto;
/* for demo only */
ul padding: 0; margin: 0; list-style: none;
li padding: 5px; background: #aaa;
p text-align: center;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>| true center |</span></p>
li:last-child
position: absolute;
top: 0;
right: 0;
background: #ddd;
ul
position: relative;
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
li
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
p
text-align: center;
margin-top: 0;
span
background-color: aqua;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
li:last-child
position: absolute;
top: 0;
right: 0;
background: #ddd;
ul
position: relative;
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
li
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
p
text-align: center;
margin-top: 0;
span
background-color: aqua;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
li:first-child
margin-right: auto;
visibility: hidden;
li:last-child
margin-left: auto;
background: #ddd;
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;
p text-align: center; margin-top: 0;
span background-color: aqua;
<ul>
<li>D</li><!-- new; invisible spacer item -->
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
li:first-child
margin-right: auto;
visibility: hidden;
li:last-child
margin-left: auto;
background: #ddd;
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;
p text-align: center; margin-top: 0;
span background-color: aqua;
<ul>
<li>D</li><!-- new; invisible spacer item -->
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
ul::before
content:"D";
margin: 1px auto 1px 1px;
visibility: hidden;
padding: 5px;
background: #ddd;
li:last-child
margin-left: auto;
background: #ddd;
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;
p text-align: center; margin-top: 0;
span background-color: aqua;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
ul::before
content:"D";
margin: 1px auto 1px 1px;
visibility: hidden;
padding: 5px;
background: #ddd;
li:last-child
margin-left: auto;
background: #ddd;
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;
p text-align: center; margin-top: 0;
span background-color: aqua;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
#flex-container
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
#flex-container>div
background: orange;
margin: 5px;
#flex-container>div:first-child
flex: 1;
#flex-container::after
content: "";
flex: 1;
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
#flex-container
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
#flex-container>div
background: orange;
margin: 5px;
#flex-container>div:first-child
flex: 1;
#flex-container::after
content: "";
flex: 1;
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
#flex-container
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
#flex-container > div
background: orange;
margin: 5px;
/* OVERRIDE THE BROWSER SETTING IN THE FLEX PROPERTY */
#flex-container > div:first-child
flex: 1;
flex-basis: 0;
#flex-container::after
content: "";
flex: 1;
flex-basis: 0;
/* OR... JUST SET THE LONG-HAND PROPERTIES INDIVIDUALLY
#flex-container > div:first-child
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
#flex-container::after
content: "";
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
*/
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
#flex-container
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
#flex-container > div
background: orange;
margin: 5px;
/* OVERRIDE THE BROWSER SETTING IN THE FLEX PROPERTY */
#flex-container > div:first-child
flex: 1;
flex-basis: 0;
#flex-container::after
content: "";
flex: 1;
flex-basis: 0;
/* OR... JUST SET THE LONG-HAND PROPERTIES INDIVIDUALLY
#flex-container > div:first-child
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
#flex-container::after
content: "";
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
*/
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
ul
display: grid;
grid-template-columns: 1fr repeat(3, auto) 1fr;
grid-column-gap: 5px;
justify-items: center;
li:nth-child(1) grid-column-start: 2;
li:nth-child(4) margin-left: auto;
/* for demo only */
ul padding: 0; margin: 0; list-style: none;
li padding: 5px; background: #aaa;
p text-align: center;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>| true center |</span></p>
ul
display: grid;
grid-template-columns: 1fr repeat(3, auto) 1fr;
grid-column-gap: 5px;
justify-items: center;
li:nth-child(1) grid-column-start: 2;
li:nth-child(4) margin-left: auto;
/* for demo only */
ul padding: 0; margin: 0; list-style: none;
li padding: 5px; background: #aaa;
p text-align: center;
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>| true center |</span></p>
edited Mar 26 '18 at 22:16
answered Aug 15 '16 at 2:44
Michael_BMichael_B
154k48250360
154k48250360
2
great answer! Tested all 5 solutions and every one of it is viable!
– Mobiletainment
Jan 14 '18 at 18:15
I have a problem with method 4 when usingmin-width/min-height
for my flex-container. Theflex: 1
children of such a parent do not get equal width/height. Any way around that?
– user2651804
Mar 26 '18 at 9:45
@user2651804, I updated my answer with a review of the problem. See Method #4.
– Michael_B
Mar 26 '18 at 22:09
2
Love the use of visibility:hidden in Method #2 - so clever! For the first time got a practical use for hidden :D
– small mammal
May 27 '18 at 22:35
2
One of the best answers I've seen here at Stackoverflow.
– Philip
Aug 29 '18 at 8:00
|
show 4 more comments
2
great answer! Tested all 5 solutions and every one of it is viable!
– Mobiletainment
Jan 14 '18 at 18:15
I have a problem with method 4 when usingmin-width/min-height
for my flex-container. Theflex: 1
children of such a parent do not get equal width/height. Any way around that?
– user2651804
Mar 26 '18 at 9:45
@user2651804, I updated my answer with a review of the problem. See Method #4.
– Michael_B
Mar 26 '18 at 22:09
2
Love the use of visibility:hidden in Method #2 - so clever! For the first time got a practical use for hidden :D
– small mammal
May 27 '18 at 22:35
2
One of the best answers I've seen here at Stackoverflow.
– Philip
Aug 29 '18 at 8:00
2
2
great answer! Tested all 5 solutions and every one of it is viable!
– Mobiletainment
Jan 14 '18 at 18:15
great answer! Tested all 5 solutions and every one of it is viable!
– Mobiletainment
Jan 14 '18 at 18:15
I have a problem with method 4 when using
min-width/min-height
for my flex-container. The flex: 1
children of such a parent do not get equal width/height. Any way around that?– user2651804
Mar 26 '18 at 9:45
I have a problem with method 4 when using
min-width/min-height
for my flex-container. The flex: 1
children of such a parent do not get equal width/height. Any way around that?– user2651804
Mar 26 '18 at 9:45
@user2651804, I updated my answer with a review of the problem. See Method #4.
– Michael_B
Mar 26 '18 at 22:09
@user2651804, I updated my answer with a review of the problem. See Method #4.
– Michael_B
Mar 26 '18 at 22:09
2
2
Love the use of visibility:hidden in Method #2 - so clever! For the first time got a practical use for hidden :D
– small mammal
May 27 '18 at 22:35
Love the use of visibility:hidden in Method #2 - so clever! For the first time got a practical use for hidden :D
– small mammal
May 27 '18 at 22:35
2
2
One of the best answers I've seen here at Stackoverflow.
– Philip
Aug 29 '18 at 8:00
One of the best answers I've seen here at Stackoverflow.
– Philip
Aug 29 '18 at 8:00
|
show 4 more comments
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 :)
.parent
display: flex;
justify-content: flex-end;
.center
margin: auto;
http://codepen.io/rgfx/pen/BLorgd
4
This doesn't truly center the middle items because it only factors in the remaining space, not the entire space. codepen.io/anon/pen/QKGrRk
– Michael_B
Sep 20 '16 at 23:35
@Michael_B, your right didn't notice that, my bad. Back to using absolute positions :( Maybe with your high rep you should set a bounty get this resolved for good. I would but I have a very low rep, even lower now trying to help you.
– rgfx
Sep 22 '16 at 18:29
No bounty is going to add a new behavior to the flexbox model, the, by Michael_B, given answer is as good as it gets...today.
– LGSon
May 16 '17 at 12:07
add a comment |
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 :)
.parent
display: flex;
justify-content: flex-end;
.center
margin: auto;
http://codepen.io/rgfx/pen/BLorgd
4
This doesn't truly center the middle items because it only factors in the remaining space, not the entire space. codepen.io/anon/pen/QKGrRk
– Michael_B
Sep 20 '16 at 23:35
@Michael_B, your right didn't notice that, my bad. Back to using absolute positions :( Maybe with your high rep you should set a bounty get this resolved for good. I would but I have a very low rep, even lower now trying to help you.
– rgfx
Sep 22 '16 at 18:29
No bounty is going to add a new behavior to the flexbox model, the, by Michael_B, given answer is as good as it gets...today.
– LGSon
May 16 '17 at 12:07
add a comment |
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 :)
.parent
display: flex;
justify-content: flex-end;
.center
margin: auto;
http://codepen.io/rgfx/pen/BLorgd
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 :)
.parent
display: flex;
justify-content: flex-end;
.center
margin: auto;
http://codepen.io/rgfx/pen/BLorgd
answered Sep 12 '16 at 2:48
rgfxrgfx
1438
1438
4
This doesn't truly center the middle items because it only factors in the remaining space, not the entire space. codepen.io/anon/pen/QKGrRk
– Michael_B
Sep 20 '16 at 23:35
@Michael_B, your right didn't notice that, my bad. Back to using absolute positions :( Maybe with your high rep you should set a bounty get this resolved for good. I would but I have a very low rep, even lower now trying to help you.
– rgfx
Sep 22 '16 at 18:29
No bounty is going to add a new behavior to the flexbox model, the, by Michael_B, given answer is as good as it gets...today.
– LGSon
May 16 '17 at 12:07
add a comment |
4
This doesn't truly center the middle items because it only factors in the remaining space, not the entire space. codepen.io/anon/pen/QKGrRk
– Michael_B
Sep 20 '16 at 23:35
@Michael_B, your right didn't notice that, my bad. Back to using absolute positions :( Maybe with your high rep you should set a bounty get this resolved for good. I would but I have a very low rep, even lower now trying to help you.
– rgfx
Sep 22 '16 at 18:29
No bounty is going to add a new behavior to the flexbox model, the, by Michael_B, given answer is as good as it gets...today.
– LGSon
May 16 '17 at 12:07
4
4
This doesn't truly center the middle items because it only factors in the remaining space, not the entire space. codepen.io/anon/pen/QKGrRk
– Michael_B
Sep 20 '16 at 23:35
This doesn't truly center the middle items because it only factors in the remaining space, not the entire space. codepen.io/anon/pen/QKGrRk
– Michael_B
Sep 20 '16 at 23:35
@Michael_B, your right didn't notice that, my bad. Back to using absolute positions :( Maybe with your high rep you should set a bounty get this resolved for good. I would but I have a very low rep, even lower now trying to help you.
– rgfx
Sep 22 '16 at 18:29
@Michael_B, your right didn't notice that, my bad. Back to using absolute positions :( Maybe with your high rep you should set a bounty get this resolved for good. I would but I have a very low rep, even lower now trying to help you.
– rgfx
Sep 22 '16 at 18:29
No bounty is going to add a new behavior to the flexbox model, the, by Michael_B, given answer is as good as it gets...today.
– LGSon
May 16 '17 at 12:07
No bounty is going to add a new behavior to the flexbox model, the, by Michael_B, given answer is as good as it gets...today.
– LGSon
May 16 '17 at 12:07
add a comment |
I expanded on Michael_B's answer
.center-flex__2-of-3 > :nth-child(1), .center-flex__2-of-3 > :nth-child(3)
flex: 1;
.center-flex__2-of-3 > :nth-child(1)
justify-content: flex-start;
.center-flex__2-of-3 > :nth-child(3)
justify-content: flex-end;
.center-flex__1-of-2 > :nth-child(1)
margin: auto;
.center-flex__1-of-2 > :nth-child(2)
flex: 1;
justify-content: flex-end;
.center-flex__2-of-2 > :nth-child(1)
flex: 1;
justify-content: flex-start;
.center-flex__2-of-2 > :nth-child(2)
margin: auto;
.center-flex__1-of-2:before, .center-flex__1-of-1:before
content: '';
flex: 1;
.center-flex__1-of-1:after, .center-flex__2-of-2:after
content: '';
flex: 1;
[class*=center-flex]
display: flex;
list-style: none;
margin: 0;
padding: 0;
border: 10px solid rgba(0, 0, 0, 0.1);
[class*=center-flex] > *
display: flex;
li
padding: 3px 5px;
2 of 3
<ul class="center-flex__2-of-3">
<span>
<li>Accusamus</li>
<li>Porro</li>
</span>
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
1 of 2
<ul class="akex center-flex__1-of-2">
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
2 of 2
<ul class="akex center-flex__2-of-2">
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
</ul>
<br><br>
1 of 1
<ul class="center-flex__1-of-1">
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
</ul>
Here with the help of SASS as a codepen
add a comment |
I expanded on Michael_B's answer
.center-flex__2-of-3 > :nth-child(1), .center-flex__2-of-3 > :nth-child(3)
flex: 1;
.center-flex__2-of-3 > :nth-child(1)
justify-content: flex-start;
.center-flex__2-of-3 > :nth-child(3)
justify-content: flex-end;
.center-flex__1-of-2 > :nth-child(1)
margin: auto;
.center-flex__1-of-2 > :nth-child(2)
flex: 1;
justify-content: flex-end;
.center-flex__2-of-2 > :nth-child(1)
flex: 1;
justify-content: flex-start;
.center-flex__2-of-2 > :nth-child(2)
margin: auto;
.center-flex__1-of-2:before, .center-flex__1-of-1:before
content: '';
flex: 1;
.center-flex__1-of-1:after, .center-flex__2-of-2:after
content: '';
flex: 1;
[class*=center-flex]
display: flex;
list-style: none;
margin: 0;
padding: 0;
border: 10px solid rgba(0, 0, 0, 0.1);
[class*=center-flex] > *
display: flex;
li
padding: 3px 5px;
2 of 3
<ul class="center-flex__2-of-3">
<span>
<li>Accusamus</li>
<li>Porro</li>
</span>
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
1 of 2
<ul class="akex center-flex__1-of-2">
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
2 of 2
<ul class="akex center-flex__2-of-2">
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
</ul>
<br><br>
1 of 1
<ul class="center-flex__1-of-1">
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
</ul>
Here with the help of SASS as a codepen
add a comment |
I expanded on Michael_B's answer
.center-flex__2-of-3 > :nth-child(1), .center-flex__2-of-3 > :nth-child(3)
flex: 1;
.center-flex__2-of-3 > :nth-child(1)
justify-content: flex-start;
.center-flex__2-of-3 > :nth-child(3)
justify-content: flex-end;
.center-flex__1-of-2 > :nth-child(1)
margin: auto;
.center-flex__1-of-2 > :nth-child(2)
flex: 1;
justify-content: flex-end;
.center-flex__2-of-2 > :nth-child(1)
flex: 1;
justify-content: flex-start;
.center-flex__2-of-2 > :nth-child(2)
margin: auto;
.center-flex__1-of-2:before, .center-flex__1-of-1:before
content: '';
flex: 1;
.center-flex__1-of-1:after, .center-flex__2-of-2:after
content: '';
flex: 1;
[class*=center-flex]
display: flex;
list-style: none;
margin: 0;
padding: 0;
border: 10px solid rgba(0, 0, 0, 0.1);
[class*=center-flex] > *
display: flex;
li
padding: 3px 5px;
2 of 3
<ul class="center-flex__2-of-3">
<span>
<li>Accusamus</li>
<li>Porro</li>
</span>
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
1 of 2
<ul class="akex center-flex__1-of-2">
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
2 of 2
<ul class="akex center-flex__2-of-2">
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
</ul>
<br><br>
1 of 1
<ul class="center-flex__1-of-1">
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
</ul>
Here with the help of SASS as a codepen
I expanded on Michael_B's answer
.center-flex__2-of-3 > :nth-child(1), .center-flex__2-of-3 > :nth-child(3)
flex: 1;
.center-flex__2-of-3 > :nth-child(1)
justify-content: flex-start;
.center-flex__2-of-3 > :nth-child(3)
justify-content: flex-end;
.center-flex__1-of-2 > :nth-child(1)
margin: auto;
.center-flex__1-of-2 > :nth-child(2)
flex: 1;
justify-content: flex-end;
.center-flex__2-of-2 > :nth-child(1)
flex: 1;
justify-content: flex-start;
.center-flex__2-of-2 > :nth-child(2)
margin: auto;
.center-flex__1-of-2:before, .center-flex__1-of-1:before
content: '';
flex: 1;
.center-flex__1-of-1:after, .center-flex__2-of-2:after
content: '';
flex: 1;
[class*=center-flex]
display: flex;
list-style: none;
margin: 0;
padding: 0;
border: 10px solid rgba(0, 0, 0, 0.1);
[class*=center-flex] > *
display: flex;
li
padding: 3px 5px;
2 of 3
<ul class="center-flex__2-of-3">
<span>
<li>Accusamus</li>
<li>Porro</li>
</span>
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
1 of 2
<ul class="akex center-flex__1-of-2">
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
2 of 2
<ul class="akex center-flex__2-of-2">
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
</ul>
<br><br>
1 of 1
<ul class="center-flex__1-of-1">
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
</ul>
Here with the help of SASS as a codepen
.center-flex__2-of-3 > :nth-child(1), .center-flex__2-of-3 > :nth-child(3)
flex: 1;
.center-flex__2-of-3 > :nth-child(1)
justify-content: flex-start;
.center-flex__2-of-3 > :nth-child(3)
justify-content: flex-end;
.center-flex__1-of-2 > :nth-child(1)
margin: auto;
.center-flex__1-of-2 > :nth-child(2)
flex: 1;
justify-content: flex-end;
.center-flex__2-of-2 > :nth-child(1)
flex: 1;
justify-content: flex-start;
.center-flex__2-of-2 > :nth-child(2)
margin: auto;
.center-flex__1-of-2:before, .center-flex__1-of-1:before
content: '';
flex: 1;
.center-flex__1-of-1:after, .center-flex__2-of-2:after
content: '';
flex: 1;
[class*=center-flex]
display: flex;
list-style: none;
margin: 0;
padding: 0;
border: 10px solid rgba(0, 0, 0, 0.1);
[class*=center-flex] > *
display: flex;
li
padding: 3px 5px;
2 of 3
<ul class="center-flex__2-of-3">
<span>
<li>Accusamus</li>
<li>Porro</li>
</span>
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
1 of 2
<ul class="akex center-flex__1-of-2">
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
2 of 2
<ul class="akex center-flex__2-of-2">
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
</ul>
<br><br>
1 of 1
<ul class="center-flex__1-of-1">
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
</ul>
.center-flex__2-of-3 > :nth-child(1), .center-flex__2-of-3 > :nth-child(3)
flex: 1;
.center-flex__2-of-3 > :nth-child(1)
justify-content: flex-start;
.center-flex__2-of-3 > :nth-child(3)
justify-content: flex-end;
.center-flex__1-of-2 > :nth-child(1)
margin: auto;
.center-flex__1-of-2 > :nth-child(2)
flex: 1;
justify-content: flex-end;
.center-flex__2-of-2 > :nth-child(1)
flex: 1;
justify-content: flex-start;
.center-flex__2-of-2 > :nth-child(2)
margin: auto;
.center-flex__1-of-2:before, .center-flex__1-of-1:before
content: '';
flex: 1;
.center-flex__1-of-1:after, .center-flex__2-of-2:after
content: '';
flex: 1;
[class*=center-flex]
display: flex;
list-style: none;
margin: 0;
padding: 0;
border: 10px solid rgba(0, 0, 0, 0.1);
[class*=center-flex] > *
display: flex;
li
padding: 3px 5px;
2 of 3
<ul class="center-flex__2-of-3">
<span>
<li>Accusamus</li>
<li>Porro</li>
</span>
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
1 of 2
<ul class="akex center-flex__1-of-2">
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
2 of 2
<ul class="akex center-flex__2-of-2">
<span>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
</ul>
<br><br>
1 of 1
<ul class="center-flex__1-of-1">
<span>
<li>Lorem</li>
<li>Dolor</li>
</span>
</ul>
answered Dec 6 '18 at 14:15
yunzenyunzen
21.4k84980
21.4k84980
add a comment |
add a comment |
The accepted answer can be changed a bit because you can use grid template areas and do it without fake element
grid-template-areas '. b c'
grid-template-columns: 1fr 1fr 1fr
the question is about flexbox not CSS grid and the porption of code you share will not give the intended result even using CSS grid.
– Temani Afif
Dec 8 '18 at 13:33
add a comment |
The accepted answer can be changed a bit because you can use grid template areas and do it without fake element
grid-template-areas '. b c'
grid-template-columns: 1fr 1fr 1fr
the question is about flexbox not CSS grid and the porption of code you share will not give the intended result even using CSS grid.
– Temani Afif
Dec 8 '18 at 13:33
add a comment |
The accepted answer can be changed a bit because you can use grid template areas and do it without fake element
grid-template-areas '. b c'
grid-template-columns: 1fr 1fr 1fr
The accepted answer can be changed a bit because you can use grid template areas and do it without fake element
grid-template-areas '. b c'
grid-template-columns: 1fr 1fr 1fr
answered Dec 6 '18 at 14:26
reporepo
182212
182212
the question is about flexbox not CSS grid and the porption of code you share will not give the intended result even using CSS grid.
– Temani Afif
Dec 8 '18 at 13:33
add a comment |
the question is about flexbox not CSS grid and the porption of code you share will not give the intended result even using CSS grid.
– Temani Afif
Dec 8 '18 at 13:33
the question is about flexbox not CSS grid and the porption of code you share will not give the intended result even using CSS grid.
– Temani Afif
Dec 8 '18 at 13:33
the question is about flexbox not CSS grid and the porption of code you share will not give the intended result even using CSS grid.
– Temani Afif
Dec 8 '18 at 13:33
add a comment |
protected by Temani Afif Dec 8 '18 at 13:32
Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).
Would you like to answer one of these unanswered questions instead?