styler
styler

Reputation: 16481

How to vertically align text inside a flexbox?

I would like to use flexbox to vertically align some content inside an <li> but not having great success.

I've checked online and many of the tutorials actually use a wrapper div which gets the align-items:center from the flex settings on the parent, but I'm wondering is it possible to cut out this additional element?

I've opted to use flexbox in this instance as the list item height will be a dynamic %.

* {
  padding: 0;
  margin: 0;
}

html,
body {
  height: 100%;
}

ul {
  height: 100%;
}

li {
  display: flex;
  justify-content: center;
  align-self: center;
  background: silver;
  width: 100%;
  height: 20%;
}
<ul>
  <li>This is the text</li>
</ul>

Upvotes: 668

Views: 1092786

Answers (14)

Pyton
Pyton

Reputation: 60

You can make the width of the lenght of a letter so it appears vertically. Something like this:

* {
  padding: 0;
  margin: 0;
}

html,
body {
  height: 100%;
}

ul {
  height: 100%;
}

li {
  display: flex;
  justify-content: center;
  align-self: center;
  background: silver;
  width: 10px;
  height: 20%;
}
<ul>
  <li>T h i s i s t h e t e x t</li>
</ul>

Upvotes: 0

Krzysztof Antosik
Krzysztof Antosik

Reputation: 993

I will not write the answer because many people have already given the correct one. However, I want to show you a useful tool that can save you from such problems in the future.

In your browser's Dev Tools, you need to inspect an element with display: flex and click the icon shown in the screenshot.

enter image description here

You will then be presented with the option to select some properties for display: flex so you can easily check all options quickly, without knowing what you can use.

Upvotes: 43

serraosays
serraosays

Reputation: 7849

The best move is to just nest a flexbox inside of a flexbox. All you have to do is give the child align-items: center. This will vertically align the text inside of its parent.

// Assuming a horizontally centered row of items for the parent but it doesn't have to be
.parent {
  align-items: center;
  display: flex;
  justify-content: center;
}

.child {
  display: flex;
  align-items: center;
}

Upvotes: 92

Michael Benjamin
Michael Benjamin

Reputation: 370993

Instead of using align-self: center use align-items: center.

There's no need to change flex-direction or use text-align.

Here's your code, with one adjustment, to make it all work:

ul {
  height: 100%;
}

li {
  display: flex;
  justify-content: center;
  /* align-self: center;    <---- REMOVE */
  align-items: center;   /* <---- NEW    */
  background: silver;
  width: 100%;
  height: 20%;
}

The align-self property applies to flex items. Except your li is not a flex item because its parent – the ul – does not have display: flex or display: inline-flex applied.

Therefore, the ul is not a flex container, the li is not a flex item, and align-self has no effect.

The align-items property is similar to align-self, except it applies to flex containers.

Since the li is a flex container, align-items can be used to vertically center the child elements.

* {
  padding: 0;
  margin: 0;
}
html, body {
  height: 100%;
}
ul {
  height: 100%;
}
li {
  display: flex;
  justify-content: center;
  /* align-self: center; */
  align-items: center;
  background: silver;
  width: 100%;
  height: 20%;
}
<ul>
  <li>This is the text</li>
</ul>

codepen demo


Technically, here's how align-items and align-self work...

The align-items property (on the container) sets the default value of align-self (on the items). Therefore, align-items: center means all flex items will be set to align-self: center.

But you can override this default by adjusting the align-self on individual items.

For example, you may want equal height columns, so the container is set to align-items: stretch. However, one item must be pinned to the top, so it is set to align-self: flex-start.

example


How is the text a flex item?

Some people may be wondering how a run of text...

<li>This is the text</li>

is a child element of the li.

The reason is that text that is not explicitly wrapped by an inline-level element is algorithmically wrapped by an inline box. This makes it an anonymous inline element and child of the parent.

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.

The flexbox specification provides for similar behavior.

4. Flex Items

Each in-flow child of a flex container becomes a flex item, and each contiguous run of text that is directly contained inside a flex container is wrapped in an anonymous flex item.

Hence, the text in the li is a flex item.

Upvotes: 862

sumit dubey
sumit dubey

Reputation: 123

.flex-container {
  display: flex;
  height: 300px;
  align-items: center;
  justify-content: center;
  width: 100%;
}

.flex-child {
  display: flex;
  width: 100%;
  background-color: khaki;
  border: 1px solid #000;
  align-items: center;
  justify-content: center;
  height: 100px;
  margin: 10px;
  padding: 10px;
}
<div class="container flex-container">
  <div class="flex-child item-1">English</div>
  <div class="flex-child item-2"> English</div>
  <div class="flex-child item-3"> English</div>
</div>

Upvotes: 4

Leena
Leena

Reputation: 239

Align-self does not align the items inside the li. Instead it aligns the li as a whole.

Using align-items would aling the text inside the li. Check out this code. It works.

* {
  padding: 0;
  margin: 0;
}

html,
body {
  height: 100%;
}

ul {
  height: 100%;
}

li {
  display: flex;
  justify-content: center;
  align-items: center;
  background: silver;
  width: 100%;
  height: 20%;
}
<ul>
  <li>This is the text</li>
</ul>

Upvotes: 6

Victor Santizo
Victor Santizo

Reputation: 1171

Set the display in li as flex and set align-items to center.

li {
  display: flex;

  /* Align items vertically */
  align-items: center;

  /* Align items horizontally */
  justify-content: center;

}

I, personally, would also target pseudo elements and use border-box (Universal selector * and pseudo elements)

*,
*::before,
*::after {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}
  

Upvotes: 11

Umesh
Umesh

Reputation: 529

It's depend on your li height just call one more thing line height

* {
  padding: 0;
  margin: 0;
}

html,
body {
  height: 100%;
}

ul {
  height: 100%;
}

li {
  display: flex;
  justify-content: center;
  align-self: center;
  background: silver;
  width: 100%;
  height:50px;line-height:50px;
}
<ul>
  <li>This is the text</li>
</ul>

Upvotes: 4

Ankur prajapati
Ankur prajapati

Reputation: 517

Using display: flex you can control the vertical alignment of HTML elements.

.box {
  height: 100px;
  display: flex;
  align-items: center; /* Vertical */
  justify-content: center; /* Horizontal */
  border:2px solid black;
}

.box div {
  width: 100px;
  height: 20px;
  border:1px solid;
}
<div class="box">
  <div>Hello</div>
  <p>World</p>
</div>

Upvotes: 7

Anatoly Gorchuk
Anatoly Gorchuk

Reputation: 49

* {
  padding: 0;
  margin: 0;
}

html,
body {
  height: 100%;
}

ul {
  height: 100%;
}

li {
 display: flex;
 justify-content: center;
 align-items: center;
 background: silver;
 width: 100%;
 height: 20%;
}
<ul>
  <li>This is the text</li>
</ul>

Upvotes: 4

Wilson
Wilson

Reputation: 9136

RESULT

enter image description here

HTML

<ul class="list">
  <li>This is the text</li>
  <li>This is another text</li>
  <li>This is another another text</li>
</ul>

Use align-items instead of align-self and I also added flex-direction to column.

CSS

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

.list {
  display: flex;
  justify-content: center;
  flex-direction: column;  /* <--- I added this */
  align-items: center;   /* <--- Change here */
  height: 100px;
  width: 100%;
  background: silver;
}

.list li {  
  background: gold;
  height: 20%; 
}

Upvotes: 13

Mohd Abdul Mujib
Mohd Abdul Mujib

Reputation: 13908

The most voted answer is for solving this specific problem posted by OP, where the content (text) was being wrapped inside an inline-block element. Some cases may be about centering a normal element vertically inside a container, which also applied in my case, so for that all you need is:

align-self: center;

Upvotes: 59

LcSalazar
LcSalazar

Reputation: 16821

You could change the ul and li displays to table and table-cell. Then, vertical-align would work for you:

ul {
    height: 20%;
    width: 100%;
    display: table;
}

li {
    display: table-cell;
    text-align: center;
    vertical-align: middle;
    background: silver;
    width: 100%; 
}

http://codepen.io/anon/pen/pckvK

Upvotes: -7

Swapnil
Swapnil

Reputation: 39

* {
  padding: 0;
  margin: 0;
}
html, body {
  height: 100%;
}
ul {
  height: 100%;
}
li {
  display: flex;
  justify-content: center;
  align-items:center;
  background: silver;
  width: 100%;
  height: 20%;
}
<ul>
  <li>This is the text</li>
</ul>

Upvotes: -1

Related Questions