Why are the buttons with text being pushed down?
So there's a bit at play here. Text and inline elements vertically-align to the baseline by default. The baseline is a value determined by the line-height of the element, though an element without a line-height will determine a "reasonable" value[1] - in the case of an empty element, this will be 0. However when you add text, the element is then given a line-height and moved down by that amount.[2]
A simple solution is to force the inputs to render with the same alignment, text or not, by applying vertical-align: top.
Why is there space between the buttons?
Inline elements (and inline-block elements like your inputs) will naturally align side-by-side, however they behave similarly to text[3]. Much like if you were to put a line-break between two letters in your HTML, a line-break between inline elements will add a single space between them.
Hypothetically, if you were to put all of your inputs on one line (without spaces), it would solve your issue:
<input type="button" value="these" /><input type="button" value="are" /><input type="button" value="touching" />
<br><br>
<input type="button" value="these" />
<input type="button" value="are" />
<input type="button" value="not" />
Though I don't suggest that method - it's merely for demonstration purposes.
So what's the solution?
Well, you have some options. Choose the one that you think would work best for you.
Solution 1: Wrap the inputs in a container and apply font-size: 0 to it. The spaces will still be there, but the font-size: 0 ensures they aren't visible.
input {
background-color: #e7e7e7;
border: solid;
border-width: 1px;
text-align: center;
height: 50px;
width: 50px;
padding: 0px;
margin: 0px;
vertical-align: top;
font-size: 12px;
}
.container {
font-size: 0;
}
<div class="container">
<input type="button" value="foo">
<input type="button" value="">
<input type="button" value="">
<br/>
<input type="button" value="">
<input type="button" value="">
<input type="button" value="">
<br/>
<input type="button" value="">
<input type="button" value="">
<input type="button" value="">
</div>
Solution 2: Bypass the triviality of inline elements and make use of display: block with float.
input {
background-color: #e7e7e7;
border: solid;
border-width: 1px;
text-align: center;
height: 50px;
width: 50px;
padding: 0px;
margin: 0px;
font-size: 12px;
float: left;
display: block;
}
.row {display: block;}
.row::after {
display: block;
content: '';
clear: both;
}
<div class="row">
<input type="button" value="foo">
<input type="button" value="">
<input type="button" value="">
</div>
<div class="row">
<input type="button" value="">
<input type="button" value="">
<input type="button" value="">
</div>
<div class="row">
<input type="button" value="">
<input type="button" value="">
<input type="button" value="">
</div>
Solution 3: Use a more modern approach, like flexbox.
input {
background-color: #e7e7e7;
border: solid;
border-width: 1px;
text-align: center;
height: 50px;
width: 50px;
padding: 0px;
margin: 0px;
vertical-align: top;
font-size: 12px;
}
.container {
display: flex;
flex-wrap: wrap;
width: 150px;
}
<div class="container">
<input type="button" value="foo">
<input type="button" value="">
<input type="button" value="">
<input type="button" value="">
<input type="button" value="">
<input type="button" value="">
<input type="button" value="">
<input type="button" value="">
<input type="button" value="">
</div>
Sources
1: "normal: Tells user agents to set the computed value to a "reasonable" value"
2: "For inline non-replaced elements, the box used for alignment is the box whose height is the 'line-height'.
3: "Inline-level elements generate inline-level boxes, which are boxes that participate in an inline formatting context."