nerdess
nerdess

Reputation: 10920

Vertical alignment on flex item with fixed height

Why is the text not centered vertically anymore as soon as I set a height to the flex container? How can I fix this?

ul {
  display: flex;
  list-style: none;
  background: green;
  width: 400px;
  align-items: center;
}

ul li {
  flex: 50%;
}

ul.fail {
  background: red;
}

ul.fail li {
  height: 100px;
}
<ul>
  <li>I am some text</li>
  <li>I am some more text I am some more text I am some more text</li>
</ul>

<ul class="fail">
  <li>I am some text</li>
  <li>I am some more text I am some more text I am some more text</li>
</ul>

https://jsfiddle.net/na4avkdg/

Upvotes: 3

Views: 3743

Answers (3)

Michael Benjamin
Michael Benjamin

Reputation: 371241

With align-items: center, your flex items are being vertically centered in the available space of the container.

In your first example (the green container), since you have no heights defined, the second item – the one with more text – establishes the height of the container.

The first item is vertically centered within the height set by the second item.

ul {
  display: flex;
  align-items: center;
  list-style: none;
  background: green;
  width: 400px;
}

ul li {
  flex: 50%;
  border: 1px dashed yellow;
}

ul.fail {
  background: red;
}

ul.fail li {
  height: 100px;
}
<ul>
  <li>I am some text</li>
  <li>I am some more text I am some more text I am some more text</li>
</ul>

<ul class="fail">
  <li>I am some text</li>
  <li>I am some more text I am some more text I am some more text</li>
</ul>

In the second example (the red container), again the container has align-items: center and no defined height. However, the flex items are set to height: 100px.

The items are, in fact, centered in the container, but since there's no extra space between the items and the container, it's not noticeable.

If you give the container a height greater than 100px, you'll notice the centering.

ul {
  display: flex;
  align-items: center;
  list-style: none;
  background: green;
  width: 400px;
  height: 150px;  /* new */
}

ul li {
  flex: 50%;
  border: 1px dashed yellow;
}

ul.fail {
  background: red;
}

ul.fail li {
  height: 100px;
}
<ul>
  <li>I am some text</li>
  <li>I am some more text I am some more text I am some more text</li>
</ul>

<ul class="fail">
  <li>I am some text</li>
  <li>I am some more text I am some more text I am some more text</li>
</ul>

Another area of confusion may be the difference between the flex item and the text. The HTML structure of your container is actually three levels, not two: The container, the items and the text.

From the CSS spec:

9.2.2.1 Anonymous inline boxes

Any text that is directly contained inside a block container element must be treated as an anonymous inline element.

Therefore, the text does not represent the flex item; it represents a separate element. In order to center the text in the item, simply repeat the flex alignment rules from the container:

ul {
  display: flex;
  align-items: center;
  list-style: none;
  background: green;
  width: 400px;
}

ul li {
  flex: 50%;
  border: 1px dashed yellow;
}

ul.fail {
  background: red;
}

ul.fail li {
  height: 100px;
  display: flex;          /* new */
  align-items: center;    /* new */
}
<ul>
  <li>I am some text</li>
  <li>I am some more text I am some more text I am some more text</li>
</ul>

<ul class="fail">
  <li>I am some text</li>
  <li>I am some more text I am some more text I am some more text</li>
</ul>

Upvotes: 4

LearnHey
LearnHey

Reputation: 31

To fix this you would need to set three new properties to your ul li declaration. These include: justify-content, flex-direction and text-align. Try the below HTML & CSS and check if this is what you want.

JS Fiddle: https://jsfiddle.net/ay5grw9t/

<ul>
  <li>I am some text</li>
  <li>I am some more text I am some more text I am some more text</li>
</ul>

<ul class="fail">
  <li>I am some text</li>
  <li>I am some more text I am some more text I am some more text</li>
</ul>

ul {
    display: -webkit-box;   
    display: -moz-box;  
    display: -ms-flexbox;  
    display: -webkit-flex; 
    display: flex;
    list-style: none;
    background: green;
    width: 400px;
    -ms-flex-align: center;
    -webkit-align-items: center;
    -webkit-box-align: center;
    align-items: center;
}
/*Changes made below*/
ul li {
    -webkit-box-flex: 50%;   
    -moz-box-flex: 50%;        
    -webkit-flex: 50%;     
    -ms-flex: 50%;          
    flex: 50%;  
    display: flex;
    justify-content: center;
    flex-direction: column;
    text-align: center;
}


ul.fail {
  background: red;
}

ul.fail li {
  height: 100px;
}

Upvotes: 0

Nenad Vracar
Nenad Vracar

Reputation: 122047

Because now you need to center text inside li if you set height.

ul {
  display: flex;
  list-style: none;
  background: green;
  width: 400px;
  align-items: center;
}
ul li {
  flex: 50%;
}
ul.fail {
  background: red;
}
ul.fail li {
  height: 100px;
  display: flex;
  align-items: center;
}
<ul>
  <li>I am some text</li>
  <li>I am some more text I am some more text I am some more text</li>
</ul>

<ul class="fail">
  <li>I am some text</li>
  <li>I am some more text I am some more text I am some more text</li>
</ul>

Upvotes: 2

Related Questions