Alignment of item(s) in Flexbox

I came across an interesting problem today. I needed to align one or more flex items to the right. In the non-flex world this would be easy. I would just say float: right; and call it good. With flex this solution would never work, as space is divided evenly, even if one of the items has a float.

Luckily after some research I found a pretty elegant solution. Here is what my code looked like at the start:

.menu {
display: flex;
align-items: center;
}
.menu__item {
text-align: center;
flex-shrink: 0;
}

The first dilemma I had was that I didn’t know what item or items needed to be aligned to the right. They were not in any order, and I didn’t know how many items there would be. I needed a new class that would be added to all the items that needed to be right aligned:

.menu {
display: flex;
align-items: center;
}
.menu__item {
text-align: center;
flex-shrink: 0;
}
.menu__item--right {
order: 100;
}

Giving the items that needed to be aligned to the right an order of 100 caused them to be pushed to the end. I knew that there would never be 100 items. This is only the first step because this just re-arranges the items to be in the correct order. Now I needed something to actually push them to the right:

.menu {
display: flex;
align-items: center;
}
.menu__item {
text-align: center;
flex-shrink: 0;
}
.menu__item--right {
order: 100;
margin-left: auto;
}

Seems like a bit of a hack, but just as margin: auto; will center an item with a fixed width, margin-left: auto; will push it to the right.

Now I have items that are aligned to the right. At this point I thought I was done and everything worked. I was reminded however that multiple items could be aligned to the right. The solution how it stands would cause all the right aligned items to distribute the remaining space evenly among them.

I needed to restrict the margin-left: auto; to just the first item with that class. There is no such thing as :first-of-class in CSS, so how was I supposed to accomplish this? Google and stack overflow to the rescue:

.menu {
display: flex;
align-items: center;
}
.menu__item {
text-align: center;
flex-shrink: 0;
}
.menu__item--right {
order: 100;
margin-left: auto;
}
// reset margin-left: auto to margin-left: 0 on siblings 
.menu__item--right ~ .menu__item--right {
margin-left: 0;
}

Flex-box never ceases to surprise me. When I started trying to figure this out I assumed that I would need to separate the right-aligned items into a different container. This solution not only saved me some re-work but also saved our backend engineers from needing to re-work some JSON structures.

Show your support

Clapping shows how much you appreciated Kerry Powell’s story.