I would like to use flex box 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 flex box 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>
Edit: Please use Michael_B\'s answer instead of mine. I would delete this answer if I could, but accepted answers can\'t be deleted.
If you make the flex-direction
vertical (using column
) then justify-content: center
centers vertically. Then you can just use text-align: center
to center horizontally as well.
li {
display: flex;
justify-content: center;
flex-direction: column;
text-align: center;
}
Here it is in action: http://codepen.io/anon/pen/Fkhgo
Instead of using align-self: center
use align-items: center
.
There\'s no need to change flex-direction
or use text-align
(as suggested in another answer).
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.
For future Googlers,
The most voted answer and the second most one too, are for solving this specific problem posted by OP, where the content(text) was being \"algorithmic-ally\" being wrapped inside inline block element. BUT, your case 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;
Just putting this out here since this is the top result for the aforesaid query and also I was pretty confused for quite some time * Derp *
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;
}
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