3

I have hard time understanding vertical-align property for some time now, and I haven't successfully managed to apply that, so I decided to write here.

Having simple markup

<div class="parent">
  <span class="text">Some text centered here
</div>

and

.parent{
  height:100px;
  background-color:red;
  .text{
    vertical-align:middle;
    background-color:green;
  }
}

results in

enter image description here

why span is not centered in parent container? To what exactly this property applies to?

Code pen for you:

https://codepen.io/anon/pen/wXYoBO

Please be aware that I am not asking here how to center element in div, but why this particular css property does not work as common sense would suggest me to.

Here, vertical-align starts to take affect https://codepen.io/anon/pen/QxZpYP

Community
  • 1
  • 1
Antoniossss
  • 31,590
  • 6
  • 57
  • 99
  • vertical-align should be applied to an element in order to vertical align it based on the text ... actually you have nothing to align, if you have 2 spans, then you can align one of them – Temani Afif Jun 27 '18 at 08:14
  • Possible duplicate of [How do I vertically center text with CSS?](https://stackoverflow.com/questions/8865458/how-do-i-vertically-center-text-with-css) – leonheess Jun 27 '18 at 08:14
  • check this ; https://css-tricks.com/almanac/properties/v/vertical-align/ until I find the good duplicate question ;) – Temani Afif Jun 27 '18 at 08:16
  • *The vertical-align property in CSS controls how **elements set next to each other** on a line are lined up* Wow that is crucial part there. It would explain a lot.... – Antoniossss Jun 27 '18 at 08:58
  • I added a simplified answer so you can have a clear idea but for in deep explanation better refer to the full specification ;) – Temani Afif Jun 27 '18 at 09:18

6 Answers6

3

If you want to use vertical-align: middle it needs to be combined with display: table-cell and applied for parent and I would not recommend this solution, however below is your code, fixed, and some other solutions.

Solution 1

.parent{
  height:100px;
  display: table-cell;
  vertical-align: middle;
  background-color: red
}

.text{
  background-color:green;
}
<div class="parent">
  <span class="text">Some text centered here</span>
</div>

Solution 2

Using defined line-height for .parent and vertical-align for child. In this solution child aligns itself vertically relative to line-height, which is stretched -- it has 100px.

.parent {
  height: 100px;
  background-color: red;
  line-height: 100px;
}

.text {
  vertical-align: middle;
  line-height: normal;
  background-color: green;
}
<div class="parent">
  <span class="text">Some text centered here</span>
</div>

Solution 3

I would recommend using display: flex, because use of display: table-cell outside of tables is not a good practice, at all.align-items: center aligns content vertically, while justify-content: center aligns content horizontally.

.parent{
  height:100px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color:red
}

.text{
  background-color:green;
}
<div class="parent">
  <span class="text">Some text centered here</span>
</div>
Community
  • 1
  • 1
Andrzej Ziółek
  • 2,241
  • 1
  • 13
  • 21
  • Thansk Andrzej for workaround, but do you know what actually causes that to not work? https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align says it it applies to table cells as well as to inline elements. So what do I miss here? – Antoniossss Jun 27 '18 at 07:50
  • `vertical-align: middle` must be applied to element with `display: table-cell`. Your `.parent` doesn't have `display: table-cell` and `vertical-align: middle` is applied to child, `.text`, instead of parent, `.parent`. – Andrzej Ziółek Jun 27 '18 at 07:53
  • 1
    vertical-align don't only work with table-cell ...read the doc and you will see it work perfectly with span and inline element if we do it correctly – Temani Afif Jun 27 '18 at 08:20
  • Using predefined `line-height`? It does, but I think it's a dirty way of doing things. I added it to my answer anyway, thanks. – Andrzej Ziółek Jun 27 '18 at 08:35
  • 1
    Quiting: *The vertical-align CSS property specifies the vertical alignment of **an inline** or table-cell box.* So it should work for inline lements, but for some reasons it don't - I want to know that reasons:) – Antoniossss Jun 27 '18 at 08:53
  • See my **Solution 2**. It works on inline elements when you define `line-height` on which it has to align. – Andrzej Ziółek Jun 27 '18 at 08:54
  • no, line-height has nothing to do with vertical-align too ... vertical-aling work with **adjacent** elements @Antoniossss check the link I shared, it doesn't work on an element alone – Temani Afif Jun 27 '18 at 08:54
  • `vertical-align` works with `line-height` and it works with adjacent elements, but only when there are any. Creating dummy element is not possible here, as it requires giving `font-size` to this dummy element, and we can't give font size equal to parent element's height. I would create a chat room if I could. – Andrzej Ziółek Jun 27 '18 at 09:07
1

Vertical align doesn't work on divs, a common workaround is to use display: table-cell in the container:

.parent{
  height:100px;
  background-color:red;
  display: table-cell;
  vertical-align:middle;
  .text{
    background-color:green;
  }
}

Or, using CSS3 Flexbox, you can use this:

.parent{
  height:100px;
  background-color:red;
  display : flex;
  align-items : center;
  .text{
    background-color:green;
  }
}
Damian Peralta
  • 1,846
  • 7
  • 11
  • So it will work on inline element inside inline element ? like span in span? – Antoniossss Jun 27 '18 at 07:51
  • Yes, it should work, span is an inline element by default, but you are changing the display property to table-cell or flex – Damian Peralta Jun 27 '18 at 07:56
  • I don't! That is something everyone suggest me to do – Antoniossss Jun 27 '18 at 08:00
  • I believe my [answer](https://stackoverflow.com/questions/51056965/why-vertical-align-css-property-not-working-and-does-not-put-span-in-middle-heig/51057069#51057069) is pretty straightforward. You are using `vertical-align: middle` in a wrong way. It needs to be applied to `.parent` with `display: table-cell` at the same time. – Andrzej Ziółek Jun 27 '18 at 08:03
1

If we check the documentation we will read this:

The vertical-align property can be used in two contexts:

To vertically align an inline element's box inside its containing line box. For example, it could be used to vertically position an <img> in a line of text:

But what is a line box?

You can refer to this part of the specification to get better idea about line boxes. It may be complex at the start but to make it easy the height of the line box is defined by the inline element.

In your case, you have only one inline element that define the line box and its height is equal to the height of the line box thus there is nothing to align as all the alignment will be equivalent.

.box {
  height:100px;
  border:1px solid red;
}
span {
 background:pink;
 /*All these values will define the line box*/
 line-height:25px;
 font-size:20px;
}
<div class="box">
<span>text</span>
</div>
<div class="box">
<span style="vertical-align:middle;">text</span>
</div>
<div class="box">
<span style="vertical-align:top;">text</span>
</div>
<div class="box">
<span style="vertical-align:bottom;">text</span>
</div>
<div class="box">
<span style="vertical-align:text-top;">text</span>
</div>
<div class="box">
<span style="vertical-align:text-bottom;">text</span>
</div>

Now, suppose you have two inlines elements with different properties (font-size, line-height, font-family, etc). In this case, the line box will be calulcated considering both elements like described in the specification and vertical-align will have an effect in this case because:

When the height of a box B is less than the height of the line box containing it, the vertical alignment of B within the line box is determined by the 'vertical-align' property.

.box {
  height:100px;
  border:1px solid red;
}
span {
 background:pink;
}
span:last-child {
  font-size:2em;
}
<div class="box">
<span>text</span><span>big text</span>
</div>
<div class="box">
<span style="vertical-align:middle;">text</span><span >big text</span>
</div>
<div class="box">
<span style="vertical-align:top;">text</span><span>big text</span>
</div>
<div class="box">
<span style="vertical-align:bottom;">text</span><span >big text</span>
</div>
<div class="box">
<span style="vertical-align:text-top;">text</span><span >big text</span>
</div>
<div class="box">
<span style="vertical-align:text-bottom;">text</span><span >big text</span>
</div>

As you can see the line box is defined by the bigger text and now you can align the small text with within it.



This is a very simplified explanation using simple wording, refer to the specification for a more accurate and complete explanation.

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
0

As it states here you cannot use vertical-align in block-level elements. Your code isn't working because div is such a block-level element. In order for your code to work you must use some other kind of element.

Damian Peralta has done this by using table-cell on your parent. The other problem is that you applied vertical-align to the child, which is by default just as high and wide as it needs to be. So effectively your code is working, it centers the contents of your span (the text), you just dont't see it because the span is exactly as high as the text itself.

So you have two options:

1) Use some non block-element as parent and apply vertical-align to the parent

.parent{
  height:100px;
  background-color:red;
  vertical-align:middle;
  display: table-cell;
}
.text{
  background-color:green;
}

2) Or make the text element higher:

.parent{
  height:100px;
  background-color:red;
}
.text{
  background-color:green;
  // You need to use line-height here because the height of inline elements cannot be changed
  line-height: 100px;
  vertical-align:middle;
}
Aram Becker
  • 2,026
  • 1
  • 20
  • 32
-1

Try this

.parent{
  height:100px;
  background-color:red;
  width:100%;
  display:table;
}
.text{
  vertical-align:middle;
  background-color:green;
  display:table-cell;
}
<div class="parent">
  <span class="text">Some text centered here</span>
</div>
Saravana
  • 3,389
  • 4
  • 21
  • 37
-2

There are many ways to align element on center vertically and/or horizontally. I find this guidelines very useful.

My favourite is to use flexbox technique since most of the time I don't want to fix the height and width.

Wei-jye
  • 412
  • 1
  • 6
  • 23