Search code examples
htmlcssflexboxresponsive-designvertical-alignment

Aligning text to a specific baseline of a responsive image


I'm having trouble aligning some elements with CSS/HTML.

Screenshot of my current code output

My main objective is to keep the bottom of "Line 2" on the left and the logo on the right on the same red line even on window resize, and to ensure the centre of the logo is always vertically aligned in the middle of the screen.

More specifically:

  1. To align the bottom of "di" (not the "g" as it hangs lower) in the logo on the right to the red line even on window resize. I know this could be solved by changing the width of the image to a px value but i'd like the size of the logo to respond based on the width of the window so that it gets smaller on resize, whilst still keeping it in line with "Line 2" on the left.
  2. To adjust the height of the green section (.flex-container class) to always fit the content inside, so that the logo (.middle class) can always be vertically aligned in the middle (top:50vh) of the window. I know this could be solved by changing the .flex-container height to "auto" but then the point at which the "g" starts to hang disappears and I need it visible.
  3. Font size and line height for the text must remain at the specified values.

Here's a link to codepen: https://codepen.io/yuvi100/pen/yLOdyzG

Current HTML:

<div class="middle">
<div class="flex-container">
  <div class="flex-item left">
    <div class="inner-wrapper">
      <div class="flex-body">Line 1<br>Line 2</div>
    </div>
  </div>
  <div class="flex-item right">
    <div class="inner-wrapper">
      <div class="flex-img">
        <img src='https://yuvalashkenazi.com/logo.png'>
      </div>
      <div class="flex-body"></div>
    </div>
  </div>
</div>
</div>

Current CSS:

body {
  background: orange;
}

.middle {
  position: absolute;
  top: 50vh;
  transform: translateY(-50%);
}

.left {
  float: left;
  width: 20vw;
}

.right {
  float: right;
  width: 80vw;
}

img {
  margin-bottom: -40px;
  width: 15vw;
}

.flex-container {
  overflow: hidden;    
  position: relative;
  display: -webkit-flex;
  display: flex;
  -webkit-align-items: baseline;
  align-items: baseline;
  width: 100vw;
  height: 320px;
  background-color: green;
  flex-wrap: nowrap;
  box-sizing: border-box;
}

.inner-wrapper {
  display: inline-block;
  width: 100%;
  background-color: cornflowerblue;
}

.flex-body {
  border-bottom: 4px solid red;
  text-align: left;
  color: white;
  font-size: 16pt;
  line-height: 18pt;
}
.flex-img {
  text-align: right;
}

Solution

  • A few minor changes will give you something pretty close to what you are looking for:

    1. Use a variable value for your margin-bottom value on your image. I have 3.2% in the example, but you can tweak it to get exactly what you want.
    2. Use the flex box's property settings to position and size your elements along the horizontal dimension. (Of course, if you have flex-direction: column set, do so along the vertical dimension.) Here, I've used flex-grow to dynamically size the boxes.
    3. I could think of a few different interpretations of your number 2. In all cases, though, you can simply set your height to auto and use a positive padding value to offset the negative margin value (I used 2.5%), so as to extend the height of the container to include the descender in the logo. I've applied the padding to .inner-wrapper and put it on the top as well as the bottom. That resizes the green as well as the blue to contain the logo. If you want the background of the descender in the logo to be green, then apply the padding to .flex-container instead. You can also apply whatever padding to the top that you like. This isn't a perfect solution, because the padding is expressed as a percentage of the entire logo, rather than just the descender, so as the screen gets smaller, the gap under the descender gets larger. If that isn't close enough for what you want to do, you might experiment with a grid and a div underneath the logo.

    body {
      background: orange;
    }
    
    .middle {
      position: absolute;
      top: 50vh;
      transform: translateY(-50%);
    }
    
    .left {
      flex-grow: 1;
    }
    
    .right {
      flex-grow: 4;
    }
    
    img {
      margin-bottom: -3.2%;
      width: 15vw;
    }
    
    .flex-container {
      overflow: hidden;    
      position: relative;
      display: -webkit-flex;
      display: flex;
      -webkit-align-items: baseline;
      align-items: baseline;
      width: 100vw;
      height: auto;
      background-color: green;
      flex-wrap: nowrap;
      box-sizing: border-box;
    }
    
    .inner-wrapper {
      display: inline-block;
      width: 100%;
      padding: 0 0 2.5% 0;
      background-color: cornflowerblue;
    }
    
    .flex-body {
      border-bottom: 4px solid red;
      text-align: left;
      color: white;
      font-size: 16pt;
      line-height: 18pt;
    }
    
    .flex-img {
      text-align: right;
    }
    <div class="middle">
      <div class="flex-container">
        <div class="flex-item left">
          <div class="inner-wrapper">
            <div class="flex-body">Line 1<br>Line 2</div>
          </div>
        </div>
        <div class="flex-item right">
          <div class="inner-wrapper">
            <div class="flex-img">
              <img src='https://yuvalashkenazi.com/logo.png'>
            </div>
            <div class="flex-body"></div>
          </div>
        </div>
      </div>
    </div>