Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keeping flexbox container centered when child text wraps to 2 or more lines [duplicate]

I am trying to center two div elements side by side in a row with flexbox (display:flex).

The first div element, on the left, just has an image.

The second div element, on the right, has left-aligned inline text of unspecified length.

When the line of text is short enough to fit on one line, both divs are aligned and justified to the center as I expect.

When the line of text is long enough to wrap onto two lines, the second div element does not wrap itself around the content as I expect. Instead, it leaves a large white space on the right side of the div.

I mocked up an example here: http://codepen.io/anon/pen/NGqYQX?editors=110. Vary your browser window's width to see what I mean.

enter image description here

How can I set the second div element to shrink itself to fit the text, so that both div elements appear centered?

HTML:

<div class="flexbox-container">   
    <div class="div1">
        <img src="http://dreamatico.com/data_images/kitten/kitten-2.jpg" width="150px">
    </div>
    <div class="div2">
        This is an example of a line of text.
    </div> 
</div>
<br>
<div class="flexbox-container">
    <div class="div1">
        <img src="http://dreamatico.com/data_images/kitten/kitten-2.jpg" width="150px">
    </div>
    <div class="div2">
        This is an example of a much loooooooooooooonger line of text.
    </div>
</div>

CSS:

.flexbox-container {
  display: flex;
  justify-content: center;
  align-items: center;
}

.div1 {
  margin-right: 30px;
}

.div2 {
  font-size: 48px;
  line-height: 48px;
  text-align: left;
}

Here is a Photoshop mockup showing what I am trying to do:

enter image description here

like image 364
MattSidor Avatar asked Sep 08 '15 19:09

MattSidor


1 Answers

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

enter image description here

Image 2

enter image description here

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:

  1. With justify-content declared on the flex containers, you are centering the flex items. The flex container itself is not centered.
  2. 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.)

like image 86
Michael Benjamin Avatar answered Sep 27 '22 18:09

Michael Benjamin