How to fix inconsistent height of HTML5 input boxes?
Asked Answered
P

7

12

Some new input types introduced in HTML5 such as <input type="date"> are taller in Google Chrome. Is there a way to fix the inconsistent height without setting fixed height?

The goal is making all input types listed below including the submit button to all have the same height. Reasons:

  • Match the design especially when they are laid out horizontally.
  • Flexibility, when I need some of input boxes to have larger font size.

$("input").each(function() {
  h = $(this).outerHeight();
  $(this).parent().append(h);
});
input {
  font: inherit;
  display: inline-block;
  vertical-align: middle;
  box-sizing: border-box;
  border: 1px solid silver;
  padding: 0.5rem;
  margin: 0;
}

[type="search"] {
  -webkit-appearance: textfield;
}

button,
[type="button"],
[type="reset"],
[type="submit"] {
  background-color: silver;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Input Heights</h1>
<p><input type="text" placeholder="text"></p>
<p><input type="search" placeholder="search"></p>
<p><input type="tel" placeholder="tel"></p>
<p><input type="url" placeholder="url"></p>
<p><input type="email" placeholder="email"></p>
<p><input type="datetime" placeholder="datetime"></p>
<p><input type="date" placeholder="date"></p>
<p><input type="month" placeholder="month"></p>
<p><input type="week" placeholder="week"></p>
<p><input type="time" placeholder="time"></p>
<p><input type="datetime-local" placeholder="datetime-local"></p>
<p><input type="number" placeholder="number"></p>
<!-- <p><input type="range" placeholder="range"></p> -->
<!-- <p><input type="color" placeholder="color"></p> -->
<p><input type="submit" value="submit"></p>
Paleolith answered 8/10, 2018 at 13:27 Comment(3)
How about min-height:1em; max-height:1em;, or is that cheating?Granulation
Specify the height and padding for the input element to make them all have the same heightCorydalis
input[type='date'] {padding-top:4px;}Granulation
P
11

The issue seems to be related to the arrows added by Chrome to the date input:

enter image description here

These arrows are taller than the text making the whole input taller than the other. They are also treated like text so they are affected by font-size and line-height which make it a bit tricky.

An idea is to apply a min-height to the content area of all the inputs in order to match the height of these arrows. After few tests, we can have equal height if we set min-height:1.5em and make box-sizing:content-box. The use of content-box will make sure the height won't shrink for the other inputs.

$("input").each(function() {
  h = $(this).outerHeight();
  $(this).parent().append(h);
});
input {
  font: inherit;
  vertical-align: middle;
  border: 1px solid silver;
  padding: 0.5rem;
  margin: 0;
  display:inline-block;
  min-height: 1.5em;
  box-sizing:content-box;
}

[type="search"] {
  -webkit-appearance: textfield;
}

button,
[type="button"],
[type="reset"],
[type="submit"] {
  background-color: silver;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Input Heights</h1>
<p><input type="text" placeholder="text"></p>
<p><input type="search" placeholder="search"></p>
<p><input type="tel" placeholder="tel"></p>
<p><input type="url" placeholder="url"></p>
<p><input type="email" placeholder="email"></p>
<p><input type="datetime" placeholder="datetime"></p>
<p><input type="date" placeholder="date"></p>
<p><input type="month" placeholder="month"></p>
<p><input type="week" placeholder="week"></p>
<p><input type="time" placeholder="time"></p>
<p><input type="datetime-local" placeholder="datetime-local"></p>
<p><input type="number" placeholder="number"></p>
<!-- <p><input type="range" placeholder="range"></p> -->
<!-- <p><input type="color" placeholder="color"></p> -->
<p><input type="submit" value="submit"></p>

We can then adjust padding, font-size, height etc and they will always keep the same height:

input {
  font: inherit;
  vertical-align: middle;
  border: 1px solid silver;
  padding: 0.5rem;
  margin: 0;
  display:inline-block;
  min-height: 1.5em;
  box-sizing:content-box;
}
.big input{
   padding:20px;
}
.small input{
   padding:2px;
}
.h-big input{
   height:50px;
}
.h-small input{
   height:10px;
}
<p><input type="text" placeholder="text"><input type="date" placeholder="date"></p>
<p style="font-size:25px;"><input type="text" placeholder="text"><input type="date" placeholder="date"></p>
<p style="font-size:10px;"><input type="text" placeholder="text"><input type="date" placeholder="date"></p>

<p class="big"><input type="text" placeholder="text"><input type="date" placeholder="date"></p>
<p class="small"><input type="text" placeholder="text"><input type="date" placeholder="date"></p>

<p class="h-big"><input type="text" placeholder="text"><input type="date" placeholder="date"></p>
<p class="h-small"><input type="text" placeholder="text"><input type="date" placeholder="date"></p>
Plod answered 12/10, 2018 at 20:16 Comment(4)
Looks promising, I wonder if we can keep the border-box, seems to be ok.Paleolith
@Paleolith we can keep it but it will fail in some cases .. try to put in the examples of the second snippet and you will see ... with border-box we have to change the min-height value to always have the same height.Plod
It will make other things very complicated without border-box. I guess it's simply not possible, yours is already very close. Let's wait and see.Paleolith
@Paleolith with border-box we have to always adjust the min-height which is also complicated in some case. We may probably introduce CSS variable and some complexe calculation with calc but not sure if it worth doing it ... for the downvotes, they are probably for the initial question where it's not clear that you are targeting Chrome, So the FF users don't see any issue.Plod
E
2

You could set the line height:

input {
  vertical-align: top;
  line-height: 22px;
}
<input type="text">
<input type="date">
Elenor answered 8/10, 2018 at 13:33 Comment(1)
It stops working as as soon as you apply some padding to the input.Paleolith
C
2

As MrLister pointed out, max-height and min-height, expressed in em, seems to be your best bet. I use it frequently on production systems and haven't had any complaints:

function updateInputs() {
  $("input").each(function() {
    $('span', $(this).parent()).remove();
    $('<span />', {
      text: $(this).outerHeight()
    }).appendTo($(this).parent())
  });
}
$('#fontSizer').on('input', function() {
  $('body').css('font-size', $(this).val() + 'px');
  updateInputs();
});
$(window).on('load',updateInputs);
body {
  font-size: 16px
}

input {
  font: inherit;
  display: inline-block;
  vertical-align: middle;
  box-sizing: border-box;
  border: 1px solid silver;
  padding: 0.5rem;
  margin: 0;
  max-height: 2.25em;
  min-height: 2.25em;
}

[type="search"] {
  -webkit-appearance: textfield;
}

button,
[type="button"],
[type="reset"],
[type="submit"] {
  background-color: silver;
}

.fixed-top {
  background-color: rgba(255, 255, 255, .85);
  display: flex;
  align-items: center;
  justify-content: center;
  top: 0;
  width: 100%;
  left: 0;
  position: fixed;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Input Heights</h1>
<p><input type="text" placeholder="text"></p>
<p><input type="search" placeholder="search"></p>
<p><input type="tel" placeholder="tel"></p>
<p><input type="url" placeholder="url"></p>
<p><input type="email" placeholder="email"></p>
<p><input type="datetime" placeholder="datetime"></p>
<p><input type="date" placeholder="date"></p>
<p><input type="month" placeholder="month"></p>
<p><input type="week" placeholder="week"></p>
<p><input type="time" placeholder="time"></p>
<p><input type="datetime-local" placeholder="datetime-local"></p>
<p><input type="number" placeholder="number"></p>
<!-- <p><input type="range" placeholder="range"></p> -->
<!-- <p><input type="color" placeholder="color"></p> -->
<p><input type="submit" value="submit"></p>

<div class="fixed-top">
  <input type="range" step="0.01" id="fontSizer" max="54" min="10" value="16">
</div>

Note the range slider only changes the font-size on <body> (and updates the size displayed, accordingly).


A completely different approach is to increase the padding value for the normal ones so they reach the same size as the ones having spinners. The closest I got to something decent is

:root {
  --input-padding: 0.5rem;
}
input {
  padding: calc(var(--input-padding) + .1475em) var(--input-padding);
  line-height: 1.225em
}
input[type="date" i], input[type="datetime-local" i], input[type="month" i], input[type="time" i], input[type="week" i] {
  padding: var(--input-padding)
}

function updateInputs() {
  $("input").each(function() {
    $('span', $(this).parent()).remove();
    $('<span />', {
      text: $(this).outerHeight()
    }).appendTo($(this).parent())
  });
}
$('#fontSizer').on('input', function() {
  $('body').css('font-size', $(this).val() + 'px');
  updateInputs();
});
$(window).on('load',updateInputs);
body {
  font-size: 16px
}
input {
  font: inherit;
  display: inline-block;
  vertical-align: middle;
  box-sizing: border-box;
  border: 1px solid silver;
  margin: 0;
}

[type="search"] {
  -webkit-appearance: textfield;
}

button,
[type="button"],
[type="reset"],
[type="submit"] {
  background-color: silver;
}

.fixed-top {
  background-color: rgba(255, 255, 255, .85);
  display: flex;
  align-items: center;
  justify-content: center;
  top: 0;
  width: 100%;
  left: 0;
  position: fixed;
}
:root {
  --input-padding: 0.5rem;
}
input {
  padding: calc(var(--input-padding) + .1475em) var(--input-padding);
  line-height: 1.225em
}
input[type="date" i], input[type="datetime-local" i], input[type="month" i], input[type="time" i], input[type="week" i] {
  padding: var(--input-padding)
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Input Heights</h1>
<p><input type="text" placeholder="text"></p>
<p><input type="search" placeholder="search"></p>
<p><input type="tel" placeholder="tel"></p>
<p><input type="url" placeholder="url"></p>
<p><input type="email" placeholder="email"></p>
<p><input type="datetime" placeholder="datetime"></p>
<p><input type="date" placeholder="date"></p>
<p><input type="month" placeholder="month"></p>
<p><input type="week" placeholder="week"></p>
<p><input type="time" placeholder="time"></p>
<p><input type="datetime-local" placeholder="datetime-local"></p>
<p><input type="number" placeholder="number"></p>
<!-- <p><input type="range" placeholder="range"></p> -->
<!-- <p><input type="color" placeholder="color"></p> -->
<p><input type="submit" value="submit"></p>

<div class="fixed-top">
  <input type="range" step="0.01" id="fontSizer" max="54" min="10" value="16">
</div>

However, it's not perfect. The errors are not linear and I suspect there's some rounding involved. Sometimes it goes above, sometimes below.

Camorra answered 13/10, 2018 at 22:7 Comment(4)
two small issues: the alignment of the arrows added by chrome are messed and when we want to add padding the content height will become technically 0 (visually it's not an issue btw)Plod
The alignment of the arrows is a completely different issue, @Temani. It's not fixed by Chrome themselves. How and why should i fix it in this answer? The question states clearly: equal heights on all inputs. Which is all my answer is about. Placement of spinners can be fixed by hiding them cross browser and drawing your own. They are drawn quite differently in different browsers.Camorra
the alignment was fine before you apply the max-height, that's why I commented .. I am not discussing a previous issue not fixed but an issue that appear in your code.Plod
@Temani, you're right. Luckily, most web pages use one size for all inputs, so the alignment can be fixed for that size alone.Camorra
O
1

Define height (and padding) in em unit, in this case input height will follow font size

$("input").each(function() {
  var span = $('<span>');
  $(this).parent().append(span);
  setInterval(() => span.text($(this).outerHeight()), 100);
});
$('#button').on('click', function(){
  $('form').css('font-size', 10 + Math.random() * 15);
});
input {
  font: inherit;
  display: inline-block;
  vertical-align: middle;
  box-sizing: border-box;
  border: 1px solid silver;
  margin: 0;

  padding: 0.5em;
  height: 2.5em;
}

[type="search"] {
  -webkit-appearance: textfield;
}

button,
[type="button"],
[type="reset"],
[type="submit"] {
  background-color: silver;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Input Heights</h1>
<button id="button">change font size</button>
<form>
<p><input type="text" placeholder="text"></p>
<p><input type="search" placeholder="search"></p>
<p><input type="tel" placeholder="tel"></p>
<p><input type="url" placeholder="url"></p>
<p><input type="email" placeholder="email"></p>
<p><input type="datetime" placeholder="datetime"></p>
<p><input type="date" placeholder="date"></p>
<p><input type="month" placeholder="month"></p>
<p><input type="week" placeholder="week"></p>
<p><input type="time" placeholder="time"></p>
<p><input type="datetime-local" placeholder="datetime-local"></p>
<p><input type="number" placeholder="number"></p>
<!-- <p><input type="range" placeholder="range"></p> -->
<!-- <p><input type="color" placeholder="color"></p> -->
<p><input type="submit" value="submit"></p>
</form>
Occidental answered 17/10, 2018 at 20:52 Comment(0)
F
1

This work for me:

input {
  height:100%
}
<input type="text">
<input type="date">
Faker answered 11/2, 2024 at 9:24 Comment(0)
W
0

Remove any vertical padding and add max-height Then replace the vertical padding with line-height (make sure to specify units, blank is a percentage).

All this combined with the box-sizing: border-box will fix most of the inputs.

Now, the input type submit and a real <button> are the only problem. The text is vertically aligned to the bottom. I can't seem to get that changed. I believe its an issue with default browser styling on those elements BUT appearance: none doesn't appear to help.

Perhaps someone can improve on this?

$("input").each(function() {
  h = $(this).outerHeight();
  $(this).parent().append(h);
});
input, button {
  font: inherit;
  display: inline-block;
  vertical-align: middle;
  box-sizing: border-box;
  border: 1px solid silver;
  padding: 0;
  margin: 0;
  line-height: 50px;
  max-height: 36px;
}

[type="search"] {
  -webkit-appearance: textfield;
}

button,
[type="button"],
[type="reset"],
[type="submit"] {
  background-color: silver;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Input Heights</h1>
<p><input type="text" placeholder="text"></p>
<p><input type="search" placeholder="search"></p>
<p><input type="tel" placeholder="tel"></p>
<p><input type="url" placeholder="url"></p>
<p><input type="email" placeholder="email"></p>
<p><input type="datetime" placeholder="datetime"></p>
<p><input type="date" placeholder="date"></p>
<p><input type="month" placeholder="month"></p>
<p><input type="week" placeholder="week"></p>
<p><input type="time" placeholder="time"></p>
<p><input type="datetime-local" placeholder="datetime-local"></p>
<p><input type="number" placeholder="number"></p>
<!-- <p><input type="range" placeholder="range"></p> -->
<!-- <p><input type="color" placeholder="color"></p> -->
<p><input type="submit" value="submit"></p>
<p><button>submit</button>
Windpollinated answered 12/10, 2018 at 20:30 Comment(3)
The point here is to allow various font sizes and all inputs to have same height, while having the native spinner buttons centered vertically. px won't get you too far on this one.Camorra
Look at the code. It's using variable font sizes. the pixel setting is to force a line-height AND container height. Those allow the box to stay fixed as you requestedWindpollinated
Place body {font-size: 60px} in your CSS and see what happens.Camorra
D
-1

You need to not only set the element height but also the font-size

input{
    height: 1em;
    font-family: Arial;
    font-size: 1em;
    font-size-adjust: 1;
    padding-top: 0.1em;
    padding-bottom: 0.1em;
}

Example fiddle: https://jsfiddle.net/rahulsalvi2k7/50otuem2/

Dionne answered 8/10, 2018 at 13:38 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.