Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Minimal CSS for form elements and links to have same height

Tags:

html

css

A problem that seems to pop up again and again in my projects is styling form elements and links to have the same height.

Here's an simple example (fiddle):

HTML:

<select><option>one</option></select>
<input type="text">
<button>foo</button>
<a href="foo">test</a>

CSS:

select,
input,
button,
a {
  padding: 0.5rem;
  margin: 0.25rem;
  border: 1px solid red;
}

All elements receive the exact same styling with a padding, a margin and a border. But they all differ slightly in height and I don't really understand why.

Can someone

  1. explain where the difference comes from? Chrome inspector tells me that the actual inner element of each has different sizes - shouldn't it be the same?
  2. tell me what minimal changes I need to do to my CSS to achieve what I want without styling each of the elements slightly different? My goal is to pick the padding, margin and border sizes freely (using variables) and still have consistent heights.

Updated fiddle with solution

like image 552
Andreas Gohr Avatar asked Oct 17 '22 12:10

Andreas Gohr


2 Answers

The minimal version:

You'll need to add the additional rules like below:

select,
input,
button,
a {
  padding: 0.5rem;
  margin: 0.25rem;
  border: 1px solid red;
  display: inline-block; /*new*/
  font: inherit;         /*new*/
}

But that will still not guarantee they receive the same height for certain input types in certain browsers. You can also reset the appearance but I would not recommend to do it globally, unless it's required by design.

-webkit-appearance: none;
appearance: none;

The non-minimal version:

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

::-moz-focus-inner {
  border-style: none;
  padding: 0;
}

::-webkit-file-upload-button {
  font: inherit;
  -webkit-appearance: button;
}

::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
  height: auto;
}

::-webkit-search-cancel-button,
::-webkit-search-decoration {
  -webkit-appearance: none;
}

button,
input,
optgroup,
select,
textarea {
  font-family: inherit;
  font-size: 1rem;
  line-height: 1.15;
  margin: 0;
}

button,
input {
  overflow: visible;
}

button,
select {
  text-transform: none;
}

[type="checkbox"],
[type="radio"] {
  padding: 0;
}

[type="search"] {
  outline-offset: -2px;
  -webkit-appearance: textfield;
}

[type="color"],
[type="date"],
[type="datetime"],
[type="datetime-local"],
[type="email"],
[type="month"],
[type="number"],
[type="password"],
[type="search"],
[type="tel"],
[type="text"],
[type="time"],
[type="url"],
[type="week"],
select,
textarea,
button,
[type="button"],
[type="reset"],
[type="submit"] {
  display: inline-block;
  vertical-align: middle;
  height: calc(2.25rem + 2px);
  color: #333;
  border: 1px solid #ccc;
  border-radius: 3px;
}

[type="color"],
[type="date"],
[type="datetime"],
[type="datetime-local"],
[type="email"],
[type="month"],
[type="number"],
[type="password"],
[type="search"],
[type="tel"],
[type="text"],
[type="time"],
[type="url"],
[type="week"],
select,
textarea {
  max-width: 100%;
  padding: 0.5rem;
  background-clip: padding-box;
  background-color: #fff;
  box-shadow: inset 1px 1px 2px rgba(0, 0, 0, 0.1);
}

[type="color"]:focus,
[type="date"]:focus,
[type="datetime"]:focus,
[type="datetime-local"]:focus,
[type="email"]:focus,
[type="month"]:focus,
[type="number"]:focus,
[type="password"]:focus,
[type="search"]:focus,
[type="tel"]:focus,
[type="text"]:focus,
[type="time"]:focus,
[type="url"]:focus,
[type="week"]:focus,
select:focus,
textarea:focus {
  border-color: rgb(30, 144, 255);
  box-shadow: 0 0 2px rgba(30, 144, 255, 0.8);
  outline: 0;
}

button,
[type="button"],
[type="reset"],
[type="submit"] {
  padding: 0.5rem 0.75rem;
  background-color: #f7f7f7;
  box-shadow: 0 1px 0 #ccc;
  cursor: pointer;
  -webkit-appearance: button;
}

button:hover,
[type="button"]:hover,
[type="reset"]:hover,
[type="submit"]:hover {
  background-color: #fafafa;
  border-color: #999;
}

button:focus,
[type="button"]:focus,
[type="reset"]:focus,
[type="submit"]:focus {
  border-color: rgb(30, 144, 255);
  box-shadow: 0 0 2px rgba(30, 144, 255, 0.8);
  outline: 0;
}

button:active,
[type="button"]:active,
[type="reset"]:active,
[type="submit"]:active {
  background-color: #eee;
  border-color: #999;
  box-shadow: inset 0 2px 5px -3px rgba(0, 0, 0, 0.5);
}

button:disabled,
[type="button"]:disabled,
[type="reset"]:disabled,
[type="submit"]:disabled {
  background-color: #f7f7f7;
  color: #a0a5aa;
  border-color: #ddd;
  box-shadow: none;
  text-shadow: 0 1px 0 #fff;
  cursor: default;
}

select {
  -moz-appearance: textfield;
  -webkit-appearance: textfield;
}

select::-ms-expand {
  display: none;
}

select[multiple],
select[size]:not([size="1"]) {
  height: auto;
  padding: 0;
}

select[multiple] option,
select[size]:not([size="1"]) option {
  padding: 0.5rem;
}

select:not([multiple]):not([size]),
select:not([multiple])[size="1"] {
  padding-right: 2rem;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z'/%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3C/svg%3E") right 0.25rem center no-repeat;
}

textarea {
  height: auto;
  overflow: auto;
}
<select>
  <option>one</option>
</select>
<input type="text" placeholder="text">
<button>foo</button>

Most of the code above doesn't answer the question directly or even unrelated, and it doesn't include the <a> tag. But in a real web application, it's likely end up having more or less the same amount of CSS.

like image 106
Stickers Avatar answered Oct 20 '22 01:10

Stickers


(Tested with Chrome only)

explain where the difference comes from?

It comes from user agent stylesheet which apply different style as default for each tag.
Those styles change according to the browser.


tell me what minimal changes I need to do to my CSS

input, select and button tags have a default font size which doesn't inherit from your body font-size declaration. Set their font-size value to inherit.

input, select, button { 
  font-size: inherit; 
}

a tag is inline by default. Set its value to inline-block.
Also, set its box-sizing value to border-box.

a { 
  display: inline-block; 
  box-sizing: border-box;
}

select has a biggest height content because of its the dropdown icon.
You could fix it by removing its default appearance, but I wouldn't recommend it.

select {
  -webkit-appearance: none;
}

Demo

body {
  font-size: 16px
}

select,
input,
button,
a {
  padding: 0.5rem;
  margin: 0.25rem;
  border: 1px solid red;
  vertical-align: top;
}

input,
select,
button {
  font-size: inherit;
}

a {
  display: inline-block;
  box-sizing: border-box;
}

/* Bad practice */
select {
  -webkit-appearance: none;
}
<select>
  <option>Select</option> 
</select>
<input type="text" value="Input">
<button>Button</button>
<a href="#">Link</a>

An other solution would be to use height + line-height properties for centering your elements and give them the same height.

body {
  font-size: 16px
}

select,
input,
button,
a {
  height: 40px;
  line-height: 40px;
  display: inline-block;
  vertical-align: top;
  margin: 0.25rem;
  padding: 0 0.5rem;
  border: 1px solid red;
  font-size: inherit;
  box-sizing: border-box;
}
<select>
  <option>Select</option> 
</select>
<input type="text" value="Input">
<button>Button</button>
<a href="#">Link</a>
like image 24
Quentin Veron Avatar answered Oct 20 '22 02:10

Quentin Veron