Search code examples
cssflexboxvertical-alignmentright-align

Vertically center, right align, multi-line text in absolutely positioned div with flexbox parent


I have a some absolutely positioned divs with two lines of text, an h2 and a p. I'm trying to get the text to be: centered vertically within the absolutely positioned div, right aligned, and there be a linebreak between the h2 and p tag.

The absolutely positioned divs are contained within a parent so I thought I could use flexbox to solve this problem, but turns out it's harder than expected. I've given the parent display:flex and align-items:center which vertically centers them. But then my h2 and p are on the same line, there's no linebreak.

So then I used flex-direction: column which created a linebreak, but then the text is no longer centered vertically. If I use align-items:flex-end and flex-direction:column the text will be right aligned and there will be a linebreak between the h2 and p, but then they are not centered vertically.

margin-right:auto can supposedly right align items, but combined with align-items:center and flex-direction:column, it doesn't work. float:right also doesn't work.

My markup looks like this:

    <div class = "col-sm-12">
      <div class = "row overlay-container">
        <img src = "_img/[email protected]" class = "img-responsive grid-image" alt = "top-right@4x image" />
          <div class = "overlay overlay-2">
           <h2>Recent Work</h2>
           <p>Lorem ipsum dolor</p>
         </div> <!-- /overlay -->
      </div> <!-- /row -->
    </div> <!-- /top right -->

where overlay is the absolutely positioned div inside the overlay-container. The overlay is a box positioned over a portion of the image. The display:flex and other properties mentioned above are on the overlay class.

It seems that no matter what I try, I can only get two out of the three conditions to work. Using flexbox is not a requirement, but I thought it would make it easy to vertically center the text. Can anyone help?


Solution

  • Here is a sample how to center using display: flex

    Stack snippet

    body {
      margin: 0;
    }
    .overlay {
      width: 300px;
      margin-top: 5vh;
      height: 90vh;
      border: 1px solid;
      
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;  
    }
    <div class = "overlay overlay-2">
      <h2>Recent Work</h2>
      <p>Lorem ipsum dolor</p>
    </div> <!-- /overlay -->


    Updated

    In some situations one might need to use auto margin's instead, as the default behavior when centering with justify-content (when using flex-direction: column) is, when content doesn't fit, it will overflow at both top and bottom.

    Stack snippet

    body {
      margin: 0;
    }
    .overlay {
      width: 300px;
      margin-top: 5vh;
      height: 90vh;
      border: 1px solid;
      
      display: flex;
      flex-direction: column;
      /*justify-content: center;        removed  */
      align-items: center;  
      overflow: auto;               /*  scroll when overflowed  */
    }
    
    .overlay h2 {
      margin-top: auto;             /*  push to the bottom  */
    }
    .overlay p {
      margin-bottom: auto;          /*  push to the top  */
    }
    <div class = "overlay overlay-2">
      <h2>Recent Work</h2>
      <p>Lorem ipsum dolor</p>
    </div> <!-- /overlay -->


    Updated 2

    Here with a 3rd item in the middle, what will scroll when not fit.

    Stack snippet

    body {
      margin: 0;
    }
    .overlay {
      width: 300px;
      margin-top: 5vh;
      height: 90vh;
      border: 1px solid;
      
      display: flex;
      flex-direction: column;
      align-items: center;  
    }
    
    .overlay p:first-of-type {
      overflow: auto;               /*  scroll when overflowed  */
    }
    
    .overlay h2 {
      margin-top: auto;             /*  push to the bottom  */
    }
    .overlay p:last-of-type {
      margin-bottom: auto;          /*  push to the top  */
    }
    <div class = "overlay overlay-2">
      <h2>Recent Work</h2>
      <p>
        Lorem ipsum dolor<br>
        Lorem ipsum dolor<br>
        Lorem ipsum dolor<br>
        Lorem ipsum dolor<br>
        Lorem ipsum dolor<br>
        Lorem ipsum dolor<br>
        Lorem ipsum dolor<br>
      </p>
      <p>Maybe a link for more</p>
    </div> <!-- /overlay -->


    Another sample: