Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 210
Mike Mameko Avatar asked Dec 24 '22 13:12

Mike Mameko


2 Answers

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

like image 148
showdev Avatar answered Dec 26 '22 19:12

showdev


When you make an element a flex container (with display: flex or display: inline-flex), all in-flow children become flex items.

All flex items have their display value controlled by the container. It doesn't matter what you specify, the container overrides it.

So when you give a flex item display: table-cell, the browser ignores it. Here's what it looks like in Chrome Dev Tools:

Style Tab

enter image description here

Computed Tab

enter image description here

A flex container "blockifies" flex items, causing them to assume many qualities of block-level elements (source).

But the vertical-align property applies only to inline-level and table-cell elements (source).

That's why it doesn't work.

Regardless, vertical-align, even if it worked, is a totally unnecessary hack in this case. There are flex properties designed for aligning content in flex items.

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

.item {
  flex: 1 1;
  display: flex;
  justify-content: center; /* horizontal alignment, in this case */
  align-items: center;     /* vertical alignment, in this case */
  background-color: cyan;
}

.item:nth-of-type(2n) {
  background-color: aliceblue;
}
<div class="container">
  <div class="item">Hello</div>
  <div class="item">Hello</div>
  <div class="item">Hello</div>
  <div class="item">Hello</div>
</div>  

Related posts:

  • How to vertically align text inside a flexbox?
  • Setting ellipsis on text from a flex container
like image 25
Michael Benjamin Avatar answered Dec 26 '22 19:12

Michael Benjamin