In order to achieve your goal (as specified in your second image) we need to make a few adjustments to your HTML and CSS. Everything can be done with flexbox.
HTML
<div id="flex-container-main">
<div class="flex-container-child">
<figure>
<img src="http://dreamatico.com/data_images/kitten/kitten-2.jpg" width="150px">
</figure>
<p>This is an example of a line of text.</p>
</div>
<div class="flex-container-child">
<figure>
<img src="http://dreamatico.com/data_images/kitten/kitten-2.jpg" width="150px">
</figure>
<p>This is an example of a much loooooooooooooonger line of text.</p>
</div>
</div><!-- end #flex-container-main -->
CSS
#flex-container-main {
display: flex;
flex-direction: column;
align-items: center;
}
.flex-container-child {
display: flex;
align-items: center;
min-height: 127px;
width: 75%;
margin: 10px;
}
figure {
margin: 0 20px 0 0;
}
img {
width: 150px;
height: 127px;
vertical-align: bottom;
}
p {
font-size: 48px;
margin: 0;
}
Revised Codepen Demo
Here's what's happening...
Your question asks:
Keeping flexbox centered when text wraps to 2 or more lines
I am trying to center two div elements side by side in a row with flexbox (display:flex
).
Let's quickly go over your two images.
Image 1
Image 2
In image 1 all flex items are actually centered. The blue highlight from Chrome Dev Tools emphasizes this point. Each item is perfectly centered on the screen.
Yes, it does get a bit clunky as you re-size the screen smaller – mostly because of the large font size – but the flex items remain centered nonetheless.
In image 2, the flex items are not evenly centered. What you've created in your mock-up is more like a column containing both flexboxes, and the column is centered. But individually only the first row is centered on the screen.
A couple of notes about your code:
- With
justify-content
declared on the flex containers, you are centering the flex items. The flex container itself is not centered.
- Since both flexboxes are direct children of the
<body>
, and <body>
has no defined width, the flexboxes align themselves in relation to the viewport.
So to achieve the effect you want we can wrap all your existing mark-up in a new flex container (#flex-container-main
). This converts the original flex containers into flex items, which can then be evenly centered as a group.
The new flex items (now classed as .flex-container-child
) are given a width to create space and a minimum height based on the height of the image. Each flex item is also declared a flex parent (display: flex
) which allows us to use flex properties on child elements. In particular, this is useful for vertically centering the text (as shown in your images).
(Note that my use of HTML semantic elements is not necessary for the code to work. If you prefer the original div
tags just swap them back. The important adjustment is the new parent container.)
Lastly (and this may not be important to your layout but just in case), browsers normally give images a small gap of whitespace under their bottom border. This is used to accommodate descenders. With vertical-align: bottom
, this space is removed. (For more details see my answer about descenders.)