Search code examples
htmlcssflexboxvertical-alignment

Vertical-align doesn't work on flex item


I tried to vertically centralize plain text inside a flex box element.

I decided to use property display:table-cell with vertical-align: middle. But it doesn't seem to work properly in flexbox elements.

How can I centralize it vertically, ideally without using a wrapper or positioning, and while still truncating long text with ellipses?

.container {
  width: 400px;
  height: 400px;
  font-weight: 700;
  border: 1px solid #d9d9d9;
  display: flex;
  flex-direction: column;
}

.item {
  display: table-cell;
  vertical-align: middle;
  flex: 1 1;
  background-color: cyan;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.item:nth-of-type(2n) {
  background-color: aliceblue;
}
<div class="container">
  <div class="item">Hello, I'm very very long string! Hello, I'm very very long string!</div>
  <div class="item">Hello</div>
  <div class="item">Hello</div>
  <div class="item">Hello</div>
</div>

View On CodePen


Solution

  • One solution is to define each flex item as its own flex container in order to vertically center its contents with align-items:center. To keep text-overflow working, add a child element to each flex item, which can then be truncated with ellipses.

    I can't offer a succinct explanation as to why text-overflow doesn't work with display:flex, and neither can David Wesst. In his words:

    It turns out that there really isn't a clean way to do this. If you're wondering how I came to that conclusion you can stop because I didn't. Those responsible for the specification did, and you can read the full conversation that started with a Mozilla bug report and leads to a whole mail group discussion about why it should (or, in this case, should not) be implemented as part of the spec.

    Here's a working example:

    .container {
      width: 400px;
      height: 400px;
      font-weight: 700;
      border: 1px solid #d9d9d9;
      display: flex;
      flex-direction: column;
    }
    
    .item {
      display: flex;
      align-items: center;
      flex: 1;
      background-color: cyan;
    }
    
    .item span {
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    
    .item:nth-of-type(2n) {
      background-color: aliceblue;
    }
    <div class="container">
      <div class="item"><span>Hello, I'm very very long string! Hello, I'm very very long string!</span></div>
      <div class="item"><span>Hello</span></div>
      <div class="item"><span>Hello</span></div>
      <div class="item"><span>Hello</span></div>
    </div>

    Also see:
    Setting ellipsis on text from a flex container