4

How do I vertically align the characters/text inside an input without changing the height of the input (it has to be exactly 28px)? The input has this CSS, so I don't understand why it has some padding-top (?):

input {
    font-family: arial;
    font-size: 28px;
    line-height: 28px;
    height: 28px;
    padding: 0;  
    border: none;
    outline: none;
    background-color:#cdcdcd;
}
<input value="asdg">

Some letters like g, p and q get cut off

Removing the margin-bottom doesn't help.

https://jsfiddle.net/4rtL6415/

Martin
  • 19,815
  • 6
  • 53
  • 104
tobbe
  • 1,576
  • 4
  • 21
  • 37
  • 1
    I think your font-size is too big for your line-height/height. can you maybe provide a simple js fiddle for this to let us test around a little bit? – FKutsche Feb 05 '16 at 12:48
  • 1
    Yeah, you need to increase the line height. Some custom fonts don't match up as well as others. – Jay Feb 05 '16 at 12:52
  • @jay increasing line-height didnt help im afraid :( And I need to set the height. I have to be exact. im using arial – tobbe Feb 05 '16 at 13:00
  • @tobbe Check my answer – Jay Feb 05 '16 at 13:03
  • Your question is a duplicate of [this](http://stackoverflow.com/questions/79461/vertical-alignment-of-elements-in-a-div) – Alfabravo Feb 08 '16 at 14:19
  • 1
    @Alfabravo no. That question wants to center a

    inside a div. I want to center characters inside a input (only one element)

    – tobbe Feb 08 '16 at 15:01
  • This will be an interesting read for you: http://stackoverflow.com/questions/20695333/why-does-unitless-line-height-behave-differently-from-percentage-or-em-in-this-e – Martin Feb 08 '16 at 15:36
  • Does it need to use 28px font? Characters that go below the line (eg. 'p', 'q', 'g', 'y') will go beyond sight. Could use a shorter size without changing the input size. Also, check for margin, padding and border settings. – Alfabravo Feb 08 '16 at 16:31
  • A nice post regarding the font structure here http://stackoverflow.com/questions/16488373/embedded-padding-margin-in-fonts – DebRaj Feb 09 '16 at 11:23
  • Why do you need to have the same height, line-height and font-size? ... roughly speaking, height affects what's outside the input, line-height/font-size affects what's inside the input. – Ason Feb 09 '16 at 11:57

9 Answers9

5

There is no padding top, it's about font size. I've changed your snippet input with a special char that fit the whole height (I'll explain below):

input {
    font-family: arial;
    font-size: 28px;
    line-height: 28px;
    height: 28px;
    padding: 0;  
    border: none;
    outline: none;
    background-color:#cdcdcd;
}
<input value="ᅡgs">

This image:

enter image description here

Explain how a font is construct. 99% of the time you'll see characters with Body < EM and that's why we may think that there is a sort of padding-top.

Sometimes, you'll cross characters for which Body == EM, that's the case of (and a lot of others).

What you are seeing is not a bug but a feature. From here you have 3 choices:

  1. Changing the font-size;
  2. Changing the input height;
  3. Changing the font-family for one that doesn't "overflow".

The choice is all yours.

Thomas Ayoub
  • 27,208
  • 15
  • 85
  • 130
4

The Problem

In some fonts, characters with descenders, like g, p, q, and y, "overflow" the vertical space defined by the font-size property. Normally, that's not a problem, because the line-height property provides enough extra space to accommodate the descenders. However, if the characters are placed in a container element with a fixed height that's less than the line-height, the descenders may get clipped if that's how the container handles overflow (text inputs being one example of such).

If you were hoping to bump the text up a few notches to avoid the clipping, then you'll be disappointed to know that there is currently no way to reposition text within its own line-height. (vertical-align, in case you were wondering, positions an inline element relative to its parent.) However, there are a few CSS tricks that we can use to achieve the same visual effect...

Solution 1 (Webkit only)

This one works by giving the input a large enough height to fit the font's lower extremities, and then using clip-path to trim it back down to 28px. This is probably the most elegant solution, but unfortunately, clip-path isn't well supported outside of Webkit browsers (Chrome, Safari, Opera).

input {
  display: inline-block;
  padding: 0;
  border: none;
  height: 32px;
  font-size: 28px;
  line-height: 32px;
  font-family: arial;
  background: #cdcdcd;
  vertical-align: baseline;
  -webkit-clip-path: inset(4px 0px 0px 0px);
  clip-path: inset(4px 0px 0px 0px);
}
input: <input value="asdg">

Solution 2

This one was inspired by DebRaj's answer, but mine uses an inline-block wrapper instead of a block (not sure how you would use it otherwise). Like the previous solution, it increases the height of the input, but instead of using clip-path to trim it back down, it uses a container element with overflow: hidden;. This is probably the most practical approach until support for clip-path improves.

.text {
  display: inline-block;
  vertical-align: baseline;
  overflow: hidden;
  margin: 7px 0 -7px 0;
  height: 28px;
}
.text > input {
  margin-top: -4px;
  border: none;
  padding: 0;
  background: #cdcdcd;
  font-size: 28px;
  line-height: 32px;
  font-family: arial;
}
input:<span class="text"><input value="asdg"></span>

Solution 3

Although you can't reposition text within its own line-height, this may be the next best thing. If you set the line-height to something less than the font-size, the text will indeed move upward relative to its normal baseline. That means you can bring the clipped parts into view without changing the container height. Unfortunately, if you try this with a text input, you'll discover a strange quirk: line-height is completely ignored if it's less than the input's height. So we'll have to substitute a different element, and turn it into an editable textbox somehow. That can be accomplished with the contenteditable attribute.

.fauxTextInput {
  display: inline-block;
  vertical-align: baseline;
  margin: 6px 0 -6px 0;
  padding: 0 3px 0 3px;
  width: 9em;
  height: 28px;
  overflow: hidden;
  font-size: 28px;
  line-height: 23px;
  font-family: arial;
  background: #cdcdcd;
}
Faux input: <span class="fauxTextInput" contenteditable>asdg</span>
Community
  • 1
  • 1
DoctorDestructo
  • 3,884
  • 22
  • 38
3

As @Thomas mentioned there is a default spacing as per font construction rules. If we concentrate the output you want to achieve is make font exact same height at the input area, you can wrap your input into a div and give that a height to adjust the input into it using as a mask.

Here is the code:

<div class="input-wrapper">
  <input value="asdg">
</div>

CSS:

.input-wrapper{
  position: relative;
  font-family: arial;
  width: 100%;
  height: 90%;
  padding: 0;
  background-color: #fff;
  overflow: hidden;
}
.input-wrapper input {
    display: block;
    width: 100%;
    height: 124%;
    margin-top: -0.19em;
    margin-bottom: 0em;
    font-size: 28px;
    padding: 0;
    outline-offset: 0;
    border: none;
}
.input-wrapper input:focus{
   outline-offset: 0;
   outline: 0;
   border: none;
   box-shadow: none;
}

fiddle: https://jsfiddle.net/x8jmLp8m/12/

Hope that helps.

DebRaj
  • 559
  • 3
  • 15
  • oh! this looks promising! Is it possible to make it dynamic to all font-sizes? If I change the font-size to ex 58px, it gets cut of again. – tobbe Feb 08 '16 at 16:14
  • Here is another variation where you can mention `height` `line-height` and `font-size` with same value: https://jsfiddle.net/8Lc1uqrh/1/ But the above solution is more dynamic. You can update only `font-size` and all will fit automatically. – DebRaj Feb 09 '16 at 11:21
1

Although there have been plenty of answers. I thought I'd add my solution to the bunch.

In this Fiddle, you can see how I managed to create an input field with a span tag, and the contenteditable attribute. The pros of taking this route are that the input field can stretch and wrap and that we can make it exactly 28px high.

In the CSS, I've added the following rules that are important:

span{
  display: inline-block;
  font-size: 25px; /*higher than 25px simply doesn't fit a 28px container*/
  line-height: 1;
  padding: calc(-.5em + 14px) 0;
}
  1. display, of course, to style the bunch
  2. font-size to declare the height of the font
  3. line-height of 1 to make sure the text actually takes up 25px by default.
  4. a padding of calc(-.5em + 14px) 0. And that's the tricky part

Because of this padding, the element will stay 28px high, while still centering the text. See the table below to see how the calculation works. The font-size and output * 2 always add up to a minimum of 28.

font-size | calculation          | output |
--------------------------------------
50px      | calc(  -25px + 14px) |  -11px | a negative padding translates to a padding of 0
25px      | calc(-12.5px + 14px) |  1.5px |
20px      | calc(  -10px + 14px) |    4px |
15px      | calc( -7.5px + 14px) |  6.5px |
10px      | calc(   -5px + 14px) |    9px |

With this code, you can edit the span's height by editing the 14px part in the calc, and edit the font-size without having to recalculate yourself

Hope this helps

Gust van de Wal
  • 4,519
  • 18
  • 39
  • This approach *can* work (it's essentially the same as [my answer](http://stackoverflow.com/a/35306904/2759272)), but looking at your fiddle, the lower-case "y" in the 28px textbox is still getting cut off, which is what the OP was trying to avoid. Also, in a normal text input, the baseline of the inner text aligns with the baseline of external text on the same line, even if the font sizes are different. This is necessary for proper alignment of labels. I do like the idea of being able to change font sizes without recalculating the padding, though. – DoctorDestructo Feb 10 '16 at 17:53
  • I've only now noticed that with Arial, the font-size has to be 25px to fit a 28px container. Edited my answer – Gust van de Wal Feb 12 '16 at 13:35
0

Edited your fiddle here

The problem is your font is larger than the height of the element enclosing it. So you just need to set both the height and line-height to a couple of px larger than the font size you're using.

Hope this helps.

Jay
  • 1,669
  • 4
  • 18
  • 34
  • Im afraid I cant change the height. Im using this for a configurator and the input must have a precise fixed height. But it might be ok to make the font a bit smaller.. – tobbe Feb 05 '16 at 13:10
  • @tobbe Yeah, aslong as the size of the font is less than the height, you'll be fine. I missed the bit in your question where you said you can't change the height. My bad! – Jay Feb 05 '16 at 13:22
0

Just decrease the font-size:

input {
    font-family: arial;
    font-size: 20px;
    line-height: 28px;
    height: 28px;
    padding: 0;  
    border: none;
    outline: none;
    background-color:#cdcdcd;
}
<input value="asdg">
JamieC
  • 447
  • 2
  • 10
0

I hope this will help you know what you want to achieve

enter image description here

In CSS, the line-height property sets the height of an entire line of text, so the difference between the font- size and the line-height is equivalent to the leading (as shown in the diagram above).

And our css is this

input {
font-family: arial;
font-size: 28px;
line-height: 28px;
height: 28px;
padding: 0;  
border: none;
outline: none;
background-color:#cdcdcd;

}

Here we have set line-height and font size equal and because of that decent is getting cut.So you either need to decrease font-size or increase line-height.

WitVault
  • 19,604
  • 18
  • 88
  • 116
-4
  input {

  height:34px;

    }
aarzoo
  • 19
  • 5
-4

Just change height and line-height to 40px or more. https://jsfiddle.net/525raf3L/

input {
    font-family: arial;
    font-size: 28px;
    line-height: 40px;
    height: 40px;
    padding: 0 12px;  
    border: none;
    outline: none;
    background: yellow;
}
<input value="asdg">
reatlat
  • 70
  • 5