Flexbox: Centered Element with Space-Around Elements on Either Side

Flexbox: centered element with space-around elements on either side

You need to modify your nav structure and start from 3 containers left, center and right. DEMO


HTML

left and right will hold a few links, center is a link.

<nav>
<span>
<a href="#">aaa </a>
<a href="#">aa </a>
<a href="#">a </a>
</span>
<a href="#"> center </a>
<span>
<a href="#">bbbb </a>
<a href="#">bbbbb </a>
<a href="#">bbbbbb </a>
</span>
</nav>

CSS

nav will take display:flex and justify-content:space-between, so will left and right.

nav, nav span {
display:flex;
justify-content:space-between;
flex-wrap:wrap;/* so they do not overlap each other if space too short */
}

To generate a gap at edges of right and left towards center, we just add a pseudo element (or an empty element).

span:first-of-type:after,
span:last-of-type:before{
content:'';
display:inline-block;/* enough , no width needed , it will still generate a space between */
}

left and right can take a flex value higher than 1 , to avoid center to expand too much.

nav > span {
flex:2; /* 2 is minimum but plenty enough here */
}

lets draw our link boxes :

a {
padding:0 0.25em;
border:solid;
}

DEMO

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>

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>

Keep one element centered between two elements of different widths in flexbox

You can use margins to approximate centering. But in order to get perfect centering with flexbox that's consistent across a variety of viewports, you'll have to slightly modify your HTML somewhat.

You need to turn the direct children of #container into flex containers themselves with a display:inline-flex declaration and give them a flex value of 1 and justify-content: center.

From there, you add your content into child divs. To get alignment on the left and right divs, use margin-right: auto and margin-left: auto, respectively.

#container {  display: flex;  background-color: lightgrey;}.flex {  flex: 1;  display: inline-flex;  justify-content: center;}.flex > div {  height: 100px;  border: 2px dashed red;  text-align: center;  padding: 5px;}.left div {  margin-right: auto;}.right div {  margin-left: auto;}
<div id="container">  <div class="left flex">    <div>Left Side</div>  </div>  <div class="center flex">    <div>I want this centered</div>  </div>  <div class="right flex">    <div>Right Side (Extra text for extra length)</div>  </div></div>

Centering a specific element among others with flexbox

A simple solution to this problem would be to give your first box margin-right:auto and your last box margin-left:auto, the flex-box will sort out the rest and calculate spacing for you.

A more complex solution that is often used by websites when building grid systems, would be to wrap each of these flex-items in another DIV that is also a flex-box. Then make these new flex-boxes equally share the width of the master wrapping flex-box (1/3 of the width to each). Then inside of each of these boxes you can position your elements as you need. Here's an example (I've left black borders around the new wrapping flex-boxes so you can better see how this behaves):

body {  margin: 0;}.flex-container {  display: flex;  align-items: center;}.flex1,.flex2,.flex3 {  display: flex;  flex: 1 1 0;  border: 1px solid black;}.flex2 {  justify-content: space-around;}.flex3 {  justify-content: flex-end;}.flex-item {  width: 50px;  height: 50px;  background: orange;}.flex-item.plz-center {  width: 25px;}.flex-item.big {  width: 150px;}
<div class="flex-container">  <div class="flex1">    <div class="flex-item"></div>  </div>  <div class="flex2">    <div class="flex-item plz-center"></div>  </div>  <div class="flex3">    <div class="flex-item big"></div>  </div></div>

Aligning elements left, center and right in flexbox

Use nested flex containers and flex-grow: 1.

This allows you to create three equal-width sections on the nav bar.

Then each section becomes a (nested) flex container which allows you to vertically and horizontally align the links using flex properties.

Now the left and right items are pinned to the edges of the container and the middle item is perfectly centered (even though the left and right items are different widths).

.nav {  display: flex;  height: 50px;      /* optional; just for demo */  background: white;}
.links { flex: 1; /* shorthand for: flex-grow: 1, flex-shrink: 1, flex-basis: 0 */ display: flex; justify-content: flex-start; align-items: center; border: 1px dashed red;}
.header-title { flex: 1; display: flex; justify-content: center; align-items: center; border: 1px dashed red;}
.logout { flex: 1; display: flex; justify-content: flex-end; align-items: center; border: 1px dashed red;}
.links a { margin: 0 5px; text-decoration: none;}
<div class="nav mobilenav">
<div class="links"> <a href="/institutions/">Institutioner</a> <a href="/leaders/">Ledere</a> </div>
<div class="header-title">Institution institution 1</div>
<div class="logout"><a class="button-dark" href="/user/logout">Log ud</a></div>
</div>

Center flex item in container, when surrounded by other flex items

Flex alignment properties work by distributing free space in the container.

Hence, there's no single-step method to center one flex item when it shares space with other items, unless the total length of the siblings is equal on both sides.

In your second example, the total length of the spans is equal on either side of the h2. As a result, the h2 is perfectly centered in the container.

.container {    display: flex;    justify-content: center;    align-items: center;    border: 1px solid red;    margin: 5px;    padding: 5px;}p { text-align: center;}p > span { background-color: aqua; padding: 5px; }
<div class="container">  <span>I'm span 1</span>  <span>I'm span 2</span>  <span>I'm span 3</span>  <h2>I'm an h2</h2>  <span>I'm span 4</span>  <span>I'm span 5</span>  <span>I'm span 6</span></div><p><span>TRUE CENTER</span></p>

Aligning elements left and center with flexbox

EDIT: See Solo's answer below, it is the better solution.


The idea behind flexbox is to provide a framework for easily aligning elements with variable dimensions within a container. As such, it makes little sense to provide a layout where the width of one element is totally ignored. In essence, that is exactly what absolute positioning is for, as it takes the element out of the normal flow.

As far as I know, there is no nice way of doing this without using position: absolute;, so I would suggest using it... but If you REALLY don't want to, or can't use absolute positioning then I suppose you could use one of the following workarounds.


If you know the exact width of the "Left" div, then you could change justify-content to flex-start (left) and then align the "Center" div like this:

#center {
position: relative;
margin: auto;
left: -{half width of left div}px;
}

If you do not know the width, then you could duplicate "Left" on the right side, use justify-content: space-between;, and hide the new right element:
Just to be clear, this is really, really ugly... better to use absolute positioning than to duplicate content. :-)

#parent {  align-items: center;  border: 1px solid black;  display: flex;  justify-content: space-between;  margin: 0 auto;  width: 500px;}#right {    opacity: 0;}
<div id="parent">  <span id="left">Left</span>  <span id="center">Center</span>  <span id="right">Left</span></div>


Related Topics



Leave a reply



Submit