Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix inconsistent height of HTML5 input boxes?

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>
like image 384
Stickers Avatar asked Feb 04 '23 21:02

Stickers


2 Answers

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>
like image 50
Temani Afif Avatar answered Feb 06 '23 12:02

Temani Afif


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.

like image 36
tao Avatar answered Feb 06 '23 12:02

tao