I just ran into a situation where I had a title that was split into two sections. The main title, big and bold, left-aligned like any regular title. But then a bit of a subtitle, right-aligned, sitting on the same line as the title. When there is room for that, it’s great. But of course text is always changing and the space you have available is variable. Let’s take a look.
This is the look we’re going for when there is room:
If there isn’t room based on screen size or length issues, left-aligned wrapping is what we want:
There are a bunch of ways to get that right-aligned text over there when there is room.
- We could absolutely position it to the right. The main problem with that though, is that absolutely positioned elements are out of the document flow, so it can’t intelligently decide when to wrap against the other text. We’d have to specify some hard widths that we don’t want to in this case.
- We could float it to the right. We don’t have to set widths that way and the text remains in the document flow, which is great. But, as soon as wrapping needs to happen, the text will remain hugged up toward the right, not nicely left aligned like we want.
- We could make the thing a table, which allows us to put the text along the right edge with no trouble. But table cells don’t wrap at all so we can’t get the layout we’re looking for.
Thankfully flexbox can help us here! By making the title a flex container with display: flex;
and the title itself flex-grow: 1;
, it can push the subtitle all the way over to the right. Flex containers can wrap, so we’ll make sure that’s happening with flex-wrap: wrap;
.
Here’s a video showing all the not-so-great methods and flexbox winning:
And a live demo:
See the Pen Wrapping Same-Line Titles by Chris Coyier (@chriscoyier) on CodePen.
Great solution.
I’m curious about what’s the job of “align-items: flex-end” ?
align-items: flex-end
vertically aligns all children to the bottom of the container.(or more generally, to the end of the cross-axis direction, since if
flex-direction
was column, it would move everything to the right)Useful Flexible Grid System Technique: Alignment Shifting Wrapping :)
The flex solution is the only one that degrades in a nice way in smaller viewports (no overlapping/overflowing text etc). Nice!
I found a solution for this sort of thing using
text-align: justify
and :after elements. It has the exact same degrading characteristics as the flex solution :)Should work in IE8+:
http://jsfiddle.net/rasmusfl0e/ao989zs7/
(… with one minor caveat; uncollapsed whitespace after the last text will be interpreted as a single space char…)
That’s the usual inline element problem. You solve it by either
1) Removing all symbols between the elements in the markup (html comment blocks are allowed)
or
2) Setting the parent font-size to 0 and children font-size to anything but zero.
Yeah – it was just a heads-up in case anyone tried using this technique and got stumped on the additional white-space.
It’s fixable – as you note :)
There are baseline alignment problems in the float and the flexbox examples.
By which I mean title-main and title-note don’t line up on the baseline.
Yep, but all you need is
align-items: baseline;
That works well until the items bumps to the next line, whereupon it creeps closer to the border. Still, it’s an acceptable solution.
Media queries… your days are numbered.* :D
*If it weren’t for IE, you’d probably already be dead.
I don’t think media queries will go away just because of flexbox. There are a lot of other use cases for using them. E.g. changing font-size.
Also you might want to make other layout arrangements with flexbox as this was already demo-ed in the ultimate flexbox-cheatsheet –> http://codepen.io/HugoGiraudel/pen/pkwqH
Why not use text-align justify on the parent container, inline-block on the two children and an additional after pseudo element of the container to enable justify and position both children on the left and right?
That should work in IE8+.
I liked your thinking so much I travelled back in time and suggested that + made a demo in a comment further up ;D
This looks great, and looks like it might work really well for navigation too? One pattern I use a lot is to float the nav left and float the nav UL right, which has the same problems as example #2 in your pen.
Ive been searching since 8 years for this wrapping and its very easy, thank you a lot!
Up until now, I was using the absolute positioning approach! Well, I would’ve used this if it weren’t for the IE8 restriction I was working around with.
And it is supported across all major browsers. Phew!
http://caniuse.com/#feat=flexbox
Thanks for your article!
You can also just do the following:
This avoids the need to set the
flex-grow
prop on the main title. Probably no difference, really, but just an alternative!There’s a bit of a difference: in Chris’ version there’s no space between the elements when they’re on a line; in yours, there is space. You can see the difference if you put a background on the elements: http://codepen.io/karaken12/pen/KpyQwM
Neither is better than the other, I think; it just depends on which one is more appropriate for your needs.