Text input on Chrome: line-height seems to have a

2020-03-01 03:50发布

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:

Text input with value, text input with placeholder, and span

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.

8条回答
你好瞎i
2楼-- · 2020-03-01 04:17

Updated base on comments below

In order to use the same line-height for each of the elements I updated the CSS to this:

*,
*:before,
*:after {
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
}

div {
  line-height: 50px;
  font-family: Arial;
}

input, span {
    border: 2px solid red;
    display: inline-block;
    font: 50px Arial;
    height: 60px;
    line-height: 60px;
    padding: 0;
    vertical-align: middle;
    width: 100px;
}
input {
    padding-top: 3px;
}

Basically you if use the same contain height and line-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.

查看更多
冷血范
3楼-- · 2020-03-01 04:18

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.

  input, span {
    padding: 0;
    margin: 0;
    width: 100px;
    padding: 0;
    min-height: 0;
    display: inline-block;
    font-family: inherit;
    border: 2px solid red;
    vertical-align: middle;
  }

  input, input::-webkit-input-placeholder, span {
    line-height: 50px;
    font-size: 50px;
  }
  

<input type="text" value="Text">
<input type="text" placeholder="Text">
<span>Text</span>

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:

  input, span {
    padding: 0;
    margin: 0;
    width: 100px;
    padding: 0;
    min-height: 0;
    display: inline-block;
    font-family: inherit;
    border: 2px solid red;
    vertical-align: middle;
  }

  input, input::-webkit-input-placeholder, span {
    line-height: 50px;
    font-size: 45px;
  }
   
  

<input type="text" value="Text">
<input type="text" placeholder="Text">
<span>Text</span>

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!

查看更多
Fickle 薄情
4楼-- · 2020-03-01 04:26

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.

Fig 1. Font-size 86% of 50px line-height. Things line up but are not honouring the 50px font size requested by OP.

input, span {
    border: 2px solid red;
    display: inline-block;
    font: 43px Arial;
    line-height: 50px;
    padding: 0;
    vertical-align: middle;
	width: 100px;
    outline-style:none;
    box-shadow:none;
    overflow:hidden;
    /* optional - to include the borders in the element size: 
    box-sizing:border-box;
    */
}
<input type="text" value="Text">
<input type="text" placeholder="Text">
<span>Text</span>

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

Fig 2. 50px text forcing a line height of 58px which is clipped with overflow hidden.

input, span {
    border: 2px solid red;
    display: inline-block;
    font: 50px Arial;
    line-height: 58px;
    padding: 0;  
    height:50px;
    vertical-align: top;
    width: 100px;
    outline-style:none;
    box-shadow:none;
    overflow:hidden;
    /* optional - to include the borders in the element size: 
    box-sizing:border-box;
    */
}
<input type="text" value="Text">
<input type="text" placeholder="Text">
<span>Text</span>

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 an input and that this will respect the height, font size, line-height and vertical alignment!

Thus voilà!

First-line pseudo element

Fig 3. First-line pseudo element for the win!

input, span {
    border: 2px solid red;
    display: inline-block;
    font: 50px Arial;
    line-height: 50px;
    height: 50px;
    padding: 0;
    vertical-align: middle;
    width: 100px;
    outline-style:none;
    box-shadow:none;
    overflow:hidden;
    /* optional - to include the borders in the element size: 
    box-sizing:border-box;
    */
}
input::first-line, span::first-line {
    vertical-align: middle;
}
/* weirdly the placeholder goes black so we have to recolour the first-line */
input::-webkit-input-placeholder::first-line {
    color:grey;
}
<input type="text" value="Text">
<input type="text" placeholder="Text">
<span>Text</span>

Here's a jsFiddle of the lot so you can see my working out. ;)

https://jsfiddle.net/romz58cc/4/

查看更多
女痞
5楼-- · 2020-03-01 04:27

Line height to 1.2 value (that's 120% of font size) works perfectly in chrome

http://plnkr.co/edit/rJmXLRrGFpi46Vv5THm5?p=preview

  div, input, span {
      line-height: 1.2;
  }

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.

查看更多
够拽才男人
6楼-- · 2020-03-01 04:29

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).

查看更多
【Aperson】
7楼-- · 2020-03-01 04:34

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

html {
  height: 100vh;
  width: 100vw;
  font: 400 10px'Arial';
}
body {
  height: 100%;
  width: 100%;
  background-color: grey;
  color: #111;
}
#form {
  display: inline-table;
}
.box {
  display: table-row;
}
span,
input {
  font: inherit;
  font-size: 40px;
  /* */
  height: 50px;
  /* */
  line-height: 50px;
  /* */
  width: 100px;
  display: table-cell;
  outline: 2px solid red;
  border: 5px solid transparent;
  /* */
  padding: 0;
}
<!DOCTYPE html>
<html>

<head>
  <link rel="stylesheet" href="style.css">

</head>

<body>
  <form id="form">
    <div class="box">
      <input id="in1" type="text" placeholder="Text" value="Text">
      <input id="in2" type="text" placeholder="Text" value="">
      <span>Text</span>
    </div>
  </form>
</body>

</html>

  1. Set the height, and line-height of <input>s equally. (e.g. 50px)

  2. Set the font-size to a size less than height and line-height. (e.g. 40px)

  3. Set either top and bottom of padding or border to the difference of the previous values divided by 2. (e.g. ((50px - 40px) / 2) = 5px)
查看更多
登录 后发表回答