I'm trying to style a text input with a value, text input with a placeholder, and a span, identically in Chrome. Specifically, I would like to control the line-height independently of the font size.
However, there seems to be some sort of minimum line-height (or something causing a similar affect) on the input value, that seems to push the text down somehow that prevents the identical styling.
Example HTML:
<div>
<input type="text" value="Text">
<input type="text" placeholder="Text">
<span>Text</span>
</div>
CSS:
div {
line-height: 50px;
font-family: Arial;
}
input,
span {
font-size: 50px;
line-height: 50px;
height: 50px;
width: 100px;
padding: 0;
min-height: 0;
display: inline-block;
font-family: inherit;
border: 2px solid red;
overflow: hidden;
vertical-align: top;
}
And the results can be seen at
http://plnkr.co/edit/oHbhKDSPTha8ShWVOC7N?p=preview and in the following screen shot from Chrome 44.0.2403.155 (64-bit) on Linux:
Strangely, the placeholder seems to be styled with the desired line-height, while the text value of the input is positioned differently. I'm not concerned with the colour of the placeholder at this point.
How can I style all 3 elements so the text is in the same position, where I'm using a custom line-height?
I understand I can just set the line-height to normal
or 1.2
, or reduce the font size, to make the elements appear identically, but they would not have the visual appearance I'm looking for.
Updated base on comments below
In order to use the same
line-height
for each of the elements I updated the CSS to this:Basically you if use the same contain
height
andline-height
the text will show correctly next to each other even if you change the font sizes. The font size must be at least 10px or so bigger than the height and line-height otherwise it will become skewed again.You can see my updated JS.Fiddle here. Hope that helps.
I've done a bit of experimenting with line-heights within input boxes and think I've come to some sort of conclusion.
It appears that if the size of the font in an input box equals or exceeds the line height, then the box changes size and its content (but not placeholder) changes also to fit. This is obvious if you remove the heights from your example.
If you set the
font-size
to smaller than the line height, you no longer see the weird line-height effect and all the text sits on the same line:Here's a side-by-side example: http://codepen.io/Jivings/pen/OyOKOV
I hope this helps, and at least brings you closer to a solution in your own CSS!
I think I've done it!!!
In my testing it seems that line-height must be at least ~115% of font-size, so if you want 50px high element you must have ~43px for things to all line up:
Fig 1. Font-size 86% of 50px line-height. Things line up but are not honouring the 50px font size requested by OP.
If you increase the font size to the desired 50px then the minimum line-height respected by the input box is ~58px. Any attempt to offset this with vertical alignment had no affect in the input but we can fix the element height and hide the overflow to give a consistent (albeit not entirely respectable) appearance:
Fig 2. 50px text forcing a line height of 58px which is clipped with overflow hidden.
Close, but no cigar. But that got me thinking - perhaps a pseudo element might be less restrictive? I found that that you can style the
input::first-line
pseudo even within aninput
and that this will respect the height, font size, line-height and vertical alignment!Thus voilà!
Fig 3. First-line pseudo element for the win!
Here's a jsFiddle of the lot so you can see my working out. ;)
https://jsfiddle.net/romz58cc/4/
Line height to 1.2 value (that's 120% of font size) works perfectly in chrome
http://plnkr.co/edit/rJmXLRrGFpi46Vv5THm5?p=preview
The only change that I make it's change the two line heights of 50 pixels to 1.2. It doesn't breaks the layout and the three elements are aligned fine.
So your original code works fine in firefox.
Because diacritics are not part of the traditional definition of font size, you can't ever have line height = font size. Even ASCII includes some diacritics (for example U0060). Diacritics can be applied to capitalized letters too, you don't even need obscure unicode extensions, latin1 is sufficient (U00C0 for example).
When a font is correctly designed and includes the box drawing block this can be easily checked – box drawing lines are supposed to be jointive so U2502 for example will give you the actual exact maximum height used by the font. Its height will be more than A or one of the other latin caps usually used to define font size. (unfortunately because horizontal lines are also supposed to be jointive the box drawing block can only be found in monospace fonts).
After allocating font height the text stack still has to reserve some place where to put diacritics (there are metadata in font formats that define how much a particular font will consume in addition to font size for diacritics). Usually this place overlaps with line spacing. When there is a single line, it shows up as line height > font size
Computing the exact minimal line height for a font size requires deep knowledge of the font used (via a specific lib, something like opentype.js) and the characteristics of the text engine used to render each element. Depending on the advancement of this text engine it will use more (or less) of the tricks permitted by the opentype spec to minimize space wastage in complex international situations.
For example unless a text stack implements handling of the opentype base table opentype spec the actual added spacing can grow to huge values (more than the 15/20% typical of western latin and given in other answers) as soon as one uses a font with support for Vietnamese, or other scripts that like to stack many diacritics on top of one other (even if your browser manages to render this page with a generic font it will probably compress diacritics vertically compared to when a vietnamese font is installed)
Likewise the text stack knows whether the text you put on a page includes or not complex diacritics. But for an input element it has no such information, that depends on what the user will type. So it needs to be conservative and reserve the worst-case line height for the scripts supported by the font you chose.
Broken web site designs where vertical input height has been under-allocated are very common, because web site/js lib/browser authors live in a 96dpi no-diacritics latin world, and think minimizing vertical height is beautiful. That breaks as soon as the site is viewed in another language, with slightly more complex unicode glyphs, slightly different fonts, or slightly different text zoom levels (due to hidpi or just user near-sightness). Normal text is usually fine since the designer didn't try to force it inside an undersized fixed-pixel box.
It is also common for input field sizing to be broken, when it uses monospace fonts for one reason or another, and the web designer assumed some ratio between sans serif and monospace and tried to "fix" it (usually by enlarging monospace since some browsers ship with a small default monospace for obscure legacy reasons, even though it is not a general rule).
SO Question - 33185205
OP
DEMO
FORK
Explination:
<input>
is a replaced element so it's content does not get rendered by the user agent.For details refer to: HTML5: Non-replaced vs. replaced element?
Solution:
See FORK or Snippet
Set the
height
, andline-height
of<input>
s equally. (e.g. 50px)Set the
font-size
to a size less thanheight
andline-height
. (e.g. 40px)top
andbottom
ofpadding
orborder
to the difference of the previous values divided by 2. (e.g. ((50px - 40px) / 2) = 5px)