Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS Flexbox: How do you align child elements of a flexbox container to opposite far ends of the main axis?

Tags:

html

css

flexbox

I am styling a header of a webpage. I want the header to be a single line which includes a logo and some navigational links. I feel the best, most modern way to layout this header today is with CSS3's flexbox, so that is what I would like to use.

I would like for the logo to be as far left in the flex container as possible, and the remaining navigation items to be as far right as possible. This could easily be achieved by floating the elements left and right, but that is not what I would like to do. So...

How do you align child elements of a flexbox container to opposite far ends of the main axis?

There is a property for the flexbox child elements that allows you to do this on the cross axis, align-self, but it seems there is none to do this on the main axis.

The best way I have come up with to achieve this is to insert an additional, empty, element in between the logo and the navigational links to serve as a spacer. But part of the reason I am choosing to use flexbox for this header is to cohere with a responsive design and I do not know of a way to make the spacing element take up all the remaining space, regardless of the width of the viewing window.

Here is where I currently stand with the mark-up, simplified to only include the elements pertinent to this situation.

HTML

<ul>
  <!-- Should be as far left as possible -->
  <li id="main">Some Logo <span>Some tag line.</span></li>

  <!-- Should be as far right as possible -->
  <li>Home</li>
  <li>Products</li>
  <li>Price Sheet</li>
  <li>Capabilities</li>
  <li>Contact</li>
</ul>

CSS

ul {
  width:           100%; 
  display:         flex;
  flex-flow:       row nowrap;
  justify-content: flex-end;
  align-items:     center;

  padding:    0;
  margin:     0;

  list-style: none;
}

li {
  margin:     0 8px;
  padding:    8px;

  font-size:   1rem;
  text-align:  center;
  font-weight: bold;

  color:       white;
  background:  green;
  border:     solid 4px #333;
}

#main { font-size: 2rem; }
#main span { font-size: 1rem; }
like image 352
JacksonHunt Avatar asked Sep 12 '15 15:09

JacksonHunt


People also ask

How do you change the alignment of Flex items on the main axis in a Flex container?

If you are working with flex-direction set to row , this alignment will be in the inline direction. However, in Flexbox you can change the main axis by setting flex-direction to column . In this case, justify-content will align items in the block direction.

How do you align a flexbox container?

To center the inner div element we will make the parent a flex container. By adding the display: flex; property we make the section element a flex container allowing us to adjust the layout of the div which is now a flex item. To center out item horizontally we use the justify-content: center; .

How do I align two items in flexbox?

With the existing markup, using flex-direction: column , you can't make those two "buttons" align side-by-side. One way is to change to row wrap and make all the input + label 100% width, which can be done with either width: 100% (used below) or flex-basis: 100% .

Which property is use to align Flex items along main axis?

On the main axis, we align using the justify-content property. This property deals with all of our flex items as a group, and controls how space is distributed between them. The initial value of justify-content is flex-start .


2 Answers

From your question:

I do not know of a way to make the spacing element take up all the remaining space, regardless of the width of the viewing window.

This is exactly what the flex-grow CSS rule was designed for. If only one child element has the flex-grow attribute set, then it will take up all the remaining space in the flex container. The only markup you will need in this case is the following:

HTML:

<li id="spacer"></li>

CSS:

#spacer {
    visibility: hidden;
    flex-grow: 1;    
}

Full Live Demo:

ul {
  width:           100%; 
  display:         flex;
  flex-flow:       row nowrap;
  justify-content: flex-end;
  align-items:     center;

  padding:    0;
  margin:     0;

  list-style: none;
}

li {
  margin:     0 8px;
  padding:    8px;

  font-size:   1rem;
  text-align:  center;
  font-weight: bold;

  color:       white;
  background:  green;
  border:     solid 4px #333;
}

#main { font-size: 2rem; }
#main span { font-size: 1rem; }

#spacer {
    visibility: hidden;
    flex-grow: 1;    
}
<ul>
  <!-- Should be as far left as possible -->
  <li id="main">Some Logo <span>Some tag line.</span></li>

  <!-- Spacer element -->
  <li id="spacer"></li>
    
  <!-- Should be as far right as possible -->
  <li>Home</li>
  <li>Products</li>
  <li>Price Sheet</li>
  <li>Capabilities</li>
  <li>Contact</li>
</ul>

JSFiddle Version: https://jsfiddle.net/7oaahkk1/

like image 70
Maximillian Laumeister Avatar answered Sep 18 '22 08:09

Maximillian Laumeister


I think the only flexibility that is needed, at least on large screens, should go on the first flex-item in the list. The one you want to place your logo at.

By setting this items flex-grow rule to 1 and the text-align to left it will stay on the left side, growing in size, making sure all other items stay on the right side. Since the logo may have a greater height value than all the other items it would make sense to change the align-items rule to baseline, making sure all items are horizontally aligned.

Furthermore i have added a few media queries to change the flex settings accordingly.

html {
    box-sizing: border-box;
}

*, *:before, *:after {
    box-sizing: border-box;
}

body {
    margin: 0;
}

ul {
    width:           100%; 
    display:         flex;
    flex-flow:       column nowrap;
    justify-content: center;
    align-items:     stretch;

    padding:         0;
    margin:          0;

    list-style:      none;
}

li {
    margin:     0;
    padding:    8px;

    font-size:   1rem;
    text-align:  center;
    font-weight: bold;

    color:       white;
    background:  green;
    border:     solid 4px #333;

}

li:first-child {
    font-family: sans;
    font-size: 2em;
    text-align: center;
}

li:first-child span {
    font-size: initial;
}

@media (min-width: 34em) {
    ul {
        flex-flow: row wrap;
        justify-content: space-between;
        align-items:     flex-start;
    }

    li {
        flex: 1;
    }

    #main {
        flex: 0 0 100vw;
    }
}

@media (min-width: 48em) {
    ul {
        justify-content: flex-end;
        align-items:     baseline;
    }

    li {
        flex: none;
    }

    #main {
        flex: 1 0 auto;
        text-align: left;
    }
}
<ul>
  <!-- Should be as far left as possible -->
  <li id="main">Some Logo <span>Some tag line.</span></li>
  <!-- Should be as far right as possible -->
  <li>Home</li>
  <li>Products</li>
  <li>Price Sheet</li>
  <li>Capabilities</li>
  <li>Contact</li>
</ul>
like image 32
DavidDomain Avatar answered Sep 19 '22 08:09

DavidDomain