Here is my code:
* { vertical-align: top; margin: 0; }
td { vertical-align: middle; border: 1px solid red; }
td:nth-child(1) { line-height: 3em; }
td:nth-child(2) { line-height: 4em; }
td:nth-child(3) { line-height: 0.1em; }
p, input { outline: 1px solid green; }
<table>
<tr>
<td>
<p>
Some vertically centered text.
</p>
</td>
<td>
<input type="text">
</td>
<td>
<input type="text">
</td>
</tr>
</table>
As one can see, the p
is neatly vertically centered, as well as the input
with line-height: .1em
, while the input
with line-height: 4em
is moved to the top.
I did not find an explanation for this behaviour after lengthy research.
I set up a jsfiddle: https://jsfiddle.net/dlenne/8xapwz11/14/.
You've set vertical-align: middle
on the td
, each of which is a parent of an input
element.
But the vertical-align
property is not inherited (source).
So, one solution is to apply the rule directly to the inputs:
* { vertical-align: top; margin: 0; }
td { vertical-align: middle; border: 1px solid red; }
td:nth-child(1) { line-height: 3em; }
td:nth-child(2) { line-height: 4em; }
td:nth-child(3) { line-height: .1em; }
p, input { outline: 1px solid green; }
input { vertical-align: middle; } /* new */
<table>
<tr>
<td>
<p>Some vertically centered text.</p>
</td>
<td>
<input type="text">
</td>
<td>
<input type="text">
</td>
</tr>
</table>
An alternative solution simply bypasses the line-height
rules by switching the display
value of the inputs from inline
to block
.
* { vertical-align: top; margin: 0; }
td { vertical-align: middle; border: 1px solid red; }
td:nth-child(1) { line-height: 3em; }
td:nth-child(2) { line-height: 4em; }
td:nth-child(3) { line-height: .1em; }
p, input { outline: 1px solid green; }
input { display: block; } /* new */
<table>
<tr>
<td>
<p>Some vertically centered text.</p>
</td>
<td>
<input type="text">
</td>
<td>
<input type="text">
</td>
</tr>
</table>
References:
- Understanding
vertical-align
, or "How (Not) To Vertically Center Content"
- 10.8.1 Leading and half-leading (W3C definitions for
line-height
and vertical-align
)
- Line-height inheritance
Since the cell has vertical-align: middle
, its contents will be aligned to the middle of the cell.
But in this case it's not noticeable, because the contents occupy all the cell vertically.
That's because the line-height
property sets the minimum height of a line box, and you use a very tall value
td:nth-child(2) {
line-height: 4em;
}
Then, the input is an inline-level element. So its vertical alignment with respect to that line box will be given by the vertical-align
of the input.
* {
vertical-align: top;
}
If you want to align the input at the middle of the cell, you should use vertical-align: middle
on the input to align it to the middle of its line box, which is aligned to the middle of the cell.
input {
vertical-align: middle;
}
* {
vertical-align: top;
margin: 0;
}
td, input {
vertical-align: middle;
border: 1px solid red;
}
td:nth-child(1) {
line-height: 3em;
}
td:nth-child(2) {
line-height: 4em;
}
td:nth-child(3) {
line-height: 0.1em;
}
p, input {
outline: 1px solid green;
}
<table>
<tr>
<td>
<p>
Some vertically centered text.
</p>
</td>
<td>
<input type="text">
</td>
<td>
<input type="text">
</td>
</tr>
</table>
I think its because of this :
*{vertical-align: top;}
When you make the line height bigger than the td(parent) it i.e. input
(child) scales out and hence follows: vertical-align: top;
rather than vertical-align: center;