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

后端 未结 8 692
無奈伤痛
無奈伤痛 2021-01-03 17:40

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 indep

相关标签:
8条回答
  • 2021-01-03 18:19

    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)

    0 讨论(0)
  • 2021-01-03 18:21

    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.

    0 讨论(0)
  • 2021-01-03 18:25

    Why is this happening?

    This misalignment is being caused by the caret and as such I don't think you will find a way to align the text if the font-size and line-height are the same.

    Why is the caret at fault?

    The caret has a height greater than the text which is causing the alignment to be skewed.

    There are a few things which support this:

    1. You can see the size of the caret

    • Click into the input and hold the left mouse button. Drag up and down and you will see that the text will move
    • Remove height: 50px; from input, span. The size of the input will now increase to the height of the caret

    div {
      line-height: 50px;
      font-family: Arial;
    }
    input, span {
      font-size: 45px;
      line-height: 50px;
      width: 100px;
      padding: 0;
      min-height: 0;
      display: inline-block;
      font-family: inherit;
      border: 2px solid red;
      overflow: hidden;
      vertical-align: top;
    }
    <div>
      <input type="text" value="Text">
      <input type="text" placeholder="Text">
      <span>Text</span>
    </div>

    2. The placeholder text is correctly aligned

    • The placeholder text is not effected by the caret so is correctly aligned
    • As soon as text is added to the input the alignment is thrown off

    The result of the caret having a greater height is that the line-height is being artificially increased causing the text to be out of line.

    This can be proven by:

    • Changing line-height to 58px. The alignment of the placeholder text and span will be the same as the input

    div {
      line-height: 50px;
      font-family: Arial;
    }
    input, span {
      font-size: 50px;
      line-height: 58px;
      height: 50px;
      width: 100px;
      padding: 0;
      min-height: 0;
      display: inline-block;
      font-family: inherit;
      border: 2px solid red;
      overflow: hidden;
      vertical-align: top;
    }
    <div>
      <input type="text" value="Text">
      <input type="text" placeholder="Text">
      <span>Text</span>
    </div>

    • Changing font-size to 45px. The caret will now fit in the 50px height

    div {
      line-height: 50px;
      font-family: Arial;
    }
    input, span {
      font-size: 45px;
      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;
    }
    <div>
      <input type="text" value="Text">
      <input type="text" placeholder="Text">
      <span>Text</span>
    </div>

    What can be done?

    As there is no way to style the caret itself (to make it smaller) the most efficient way of ensuring the text is aligned would be to use a font-size which is smaller than the line-height. This will in turn make the caret smaller and stop it from artificially increasing the line-height of the input.

    div {
      line-height: 50px;
      font-family: Arial;
    }
    input, span {
      font-size: 45px;
      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;
    }
    <div>
      <input type="text" value="Text">
      <input type="text" placeholder="Text">
      <span>Text</span>
    </div>

    Alternatively you could remove height and just specify a line-height equal to the height of the caret:

    div {
      line-height: 50px;
      font-family: Arial;
    }
    input, span {
      font-size: 50px;
      line-height: 58px;
      width: 100px;
      padding: 0;
      min-height: 0;
      display: inline-block;
      font-family: inherit;
      border: 2px solid red;
      overflow: hidden;
      vertical-align: top;
    }
    <div>
      <input type="text" value="Text">
      <input type="text" placeholder="Text">
      <span>Text</span>
    </div>

    0 讨论(0)
  • 2021-01-03 18:28

    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!

    0 讨论(0)
  • 2021-01-03 18: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).

    0 讨论(0)
  • 2021-01-03 18:33

    Try like this

    As per the link:Firefox line-height issue with input fields

    line-height on input won't change unless you change the font-size

    so reduce the font-size:50px to 45px it will look fine.

    Code Below

       div { 
    line-height: 50px; 
    font-family: Arial; 
    } 
    
    span,input[type="text"],input[placeholder]{ 
    height: 50px; 
    width: 100px; 
    padding: 0; 
    min-height: 0; 
    display: inline-block; 
    font-family: inherit; 
    border: 2px solid red; 
    overflow: hidden; 
    vertical-align: top; 
    font-size:45px; 
    
    } 
    
    ::-webkit-input-placeholder { 
    color:#000000; 
    
    }
    
    0 讨论(0)
提交回复
热议问题