1

I am trying to create an HTML 'numeric keypad', like those found on some keyboards. I am stumped on how to do the layout without using a table.

enter image description here

I am using Bootstrap (v3.1.1) so my first instinct was to attempt to use its col- classes to reproduce the 4 columns of keys found on a keypad. This was awkward though and I couldn't easily get the sizing of the buttons to be consistent between the different levels of nested div containers. I failed fast.

I knew I could use a <table> based layout to accomplish this easily with colspans and rowspans. But it didn't feel right using a table layout for this, because it is clearly not tabular data.

I tried to get the benefits of tables by using the CSS display property's table* values. This was cleaner than my first attempt and the classes I used were more meaningful than the Bootstrap ones I was attempting to use before. Unfortunately, I learned that display:table does not support colspan/rowspan. Here is a JSFiddle of that attempt. I tried to fake a rowspan on the tall-keys by using height: 144px; but that just increased the height of the entire row.

I gave up and ultimately created the layout with a <table>. Here is the JSFiddle.

Is there a way to create a numeric keypad without using an HTML <table>?

Note: The heights of keys can be static values (e.g. 70px) but the widths cannot. The width of the entire keypad is a variable percentage of the container, because responsive.

Community
  • 1
  • 1
Jesse Webb
  • 43,135
  • 27
  • 106
  • 143

1 Answers1

11

By using float behavior, you can create this with a bunch of inline-blocks. Each of the blocks are floated to the right (because the big vertical elements are on the right).

So the buttons on the numpad are placed in the HTML from the top right corner going left. E.g. the first block is the - button, followed by *, /, Num-Lock, +, and so on.

In order to make a double-sized vertical button, I attached the attribute v2 (you could've used classes for this, but I felt like being different), and to make a double-sized horizontal button, I attached the attribute h2.


For a responsive layout, scroll down to the edit.


CSS:

container {
    width: 442px;
    border: 1px solid black;
    display: inline-block;
}

block {
    display: inline-block;
    width: 100px;
    height: 100px;
    margin: 5px;
    background: red;
    float: right;
}

block[v2] {
    height: 210px;
}

block[h2] {
    width: 210px;
}

HTML:

<container>
    <block></block>
    <block></block>
    <block></block>
    <block></block>
    <block v2=""></block>
    <block></block>
    <block></block>
    <block></block>
    <block></block>
    <block></block>
    <block></block>
    <block v2=""></block>
    <block></block>
    <block></block>
    <block></block>
    <block></block>
    <block h2=""></block>
</container>

JSFiddle


Edit:

If it has to be responsive, you can use calc and percentages to make the widths fit:

block
{
    width: calc(25% - 10px);
    margin: 5px;
}

block[h2]
{
    width: calc(50% - 10px);
}

JSFiddle

Liftoff
  • 24,717
  • 13
  • 66
  • 119
  • This is very slick! I especially like the fact that my ` – Jesse Webb Apr 15 '14 at 15:35
  • I tried to edit your fiddle to see if I could use a `float:left` instead, because using `right` seemed a bit awkward. [Here is my modified JSFiddle](http://jsfiddle.net/gweebz/2YzAA/5/). I changed the order of the keys to flow left-to-right/top-to-bottom. I don't understand though why the tall red blocks are causing other blocks to act like there is a `clear` applied. – Jesse Webb Apr 15 '14 at 16:08
  • @JesseWebb Yeah that is why I used `float:right` because the big elements are on the right and they push the baseline down for all future elements. The only way I could think of to fix that would be to apply a custom class to each element that would need to use margins (negative and positive) to move them into the right place. [**The result works**](http://jsfiddle.net/2YzAA/7/), but the code isn't really nice. – Liftoff Apr 15 '14 at 20:01