Flexbox horizontal menu centering while keeping last element to the right side
Give also #menu
a left margin of auto
.
Stack snippet
#container { display: flex; justify-content: center; align-items: center;}#last, #menu { margin-left: auto;}
#last span, #menu span { padding: 10px 20px; background: lightgray;}
<div id="container"> <div id="menu"> <span>1</span> <span>2</span> <span>3</span> </div> <div id="last"> <span>4</span> </div></div>
Center one and right/left align other flexbox element
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>
Position last flex item at the end of container
Flexible Box Layout Module - 8.1. Aligning with auto margins
Auto margins on flex items have an effect very similar to auto margins in block flow:
During calculations of flex bases and flexible lengths, auto margins are treated as 0.
Prior to alignment via
justify-content
andalign-self
, any positive free space is distributed to auto margins in that dimension.
Therefore you could use margin-top: auto
to distribute the space between the other elements and the last element.
This will position the last element at the bottom.
p:last-of-type {
margin-top: auto;
}
.container {
display: flex;
flex-direction: column;
border: 1px solid #000;
min-height: 200px;
width: 100px;
}
p {
height: 30px;
background-color: blue;
margin: 5px;
}
p:last-of-type {
margin-top: auto;
}
<div class="container">
<p></p>
<p></p>
<p></p>
</div>
Keep the middle item centered when side items have different widths
If the left and right boxes would be exactly the same size, I get the desired effect. However when one of the two is a different size the centered box is not truly centered anymore. Is there anyone that can help me?
Here's a method using flexbox to center the middle item, regardless of the width of siblings.
Key features:
- pure CSS
- no absolute positioning
- no JS/jQuery
Use nested flex containers and auto
margins:
.container { display: flex;}.box { flex: 1; display: flex; justify-content: center;}
.box:first-child > span { margin-right: auto; }
.box:last-child > span { margin-left: auto; }
/* non-essential */.box { align-items: center; border: 1px solid #ccc; background-color: lightgreen; height: 40px;}p { text-align: center; margin: 5px 0 0 0;}
<div class="container"> <div class="box"><span>short text</span></div> <div class="box"><span>centered text</span></div> <div class="box"><span>loooooooooooooooong text</span></div></div><p>↑<br>true center</p>
How can I align one item right with flexbox?
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>
Flex-box: Align last row to grid
Add a ::after
which autofills the space. No need to pollute your HTML. Here is a codepen showing it: http://codepen.io/DanAndreasson/pen/ZQXLXj
.grid {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
}
.grid::after {
content: "";
flex: auto;
}
Targeting flex items on the last or specific row
Unfortunately, in the current iteration of flexbox (Level 1), there is no clean way to solve the last-row alignment problem. It's a common problem.
It would be useful to have a flex property along the lines of:
last-row
last-column
only-child-in-a-row
alone-in-a-column
This problem does appear to be a high priority for Flexbox Level 2:
- CSS Working Group Wiki - Specification Issues and Planning
- https://lists.w3.org/Archives/Public/www-style/2015Jan/0150.html
Although this behavior is difficult to achieve in flexbox, it's simple and easy in CSS Grid Layout:
- Equal width flex items even after they wrap
In case Grid is not an option, here's a list of similar questions containing various flexbox hacks:
- Properly sizing and aligning the flex item(s) on the last row
- Flex-box: Align last row to grid
- Flexbox wrap - different alignment for last row
- How can a flex item keep the same dimensions when it is forced to a new row?
- Selector for an element alone in a row?
- Aligning elements in last flexbox row
- How can I allow flex-items to grow while keeping the same size?
- Left-align last row of flexbox using space-between and margins
- Inconsistent margin between flex items on last row
- How to keep wrapped flex-items the same width as the elements on the previous row?
- How to align left last row/line in multiple line flexbox
- Last children of grid get giant gutter cause of flexbox space-between
- Managing justify-content: space-between on last row
- Flexbox space between behavior combined with wrap
- Possible to use CSS Flexbox to stretch elements on every row while maintaining consistent widths?
Related Topics
Working with Canvas in Different Screen Sizes
Make Input Element (Type="Text") Handle Multiple Lines of Text
HTML: Should I Encode Greater Than or Not? ( > > )
How to Include Glyphicons in Bootstrap 3
Multiple Background Images in One Div
How to Get The Parent Url from an Iframe's Content
How Is Column Width Determined in Browser
Having Trouble with Attribute != Selector
Is It Safe to Use Anchor to Submit Form
Visual Studio (2012 and Lower) Deletes CSS Properties
Inject <Input> in Innerhtml Angular 2
Keep Box-Shadow Direction Consistent While Rotating