user1645764
user1645764

Reputation: 61

Aligning decimal point of numbers in a table, with appearance of pseudo-"centre" alignment in cell

I want a table containing a column of decimal numbers, of varying length before and after the decimal, with the decimal points all aligned.

The column width must have a "liquid" size, expanding as necessary to accomodate EITHER a very long number in ANY of the data cells, OR a very long HEADER pertaining to that column.

Cells containing integers (no decimal point) should still display the numbers with the digits aligned in the same position as if a decimal character was present. (eg. The number 512 should still have its digits aligned correctly with the cell containing only "512" instead of "512.")

The font should be irrelevant; monospaced should not be a requirement.

Finally, the numbers must also be centred in the column as best as possible, while keeping the decimals (visible and implied!) aligned. Specifically, the "left-side blank gap" of the cell with the most characters before the decimal character (or simply most characters if there is no decimal character present) must be of equal width as the "right-side blank gap" of the cell with the most characters after the first decimal character.

I specifically say "characters" instead of "numerals" for the final requirement, because the table layout should handle symbolic characters such as positive/negative signs prepending the numerals, and letters such as measurement unit acronyms appending the numerals.

The HTML 4.01 specification, "by the book", allows such a layout to be done very easily with a simple HTML table. (Split the data on its decimal character across the two inner cells of a 4-column colgroup, with the outer two col width="*" and inner two col width="0*". Right-align the cell with the integer-portion of the number, and left-align the cell with the decimal character and fractional-portion of the number. Set both those cells to nowrap, then set the table's cellpadding="0" cellspacing="0" rules="groups".)

But a number of people say this is bad, and that CSS should be used instead of tables for formatting purposes. I also understand that a table with semantically-correct data should keep these numbers intact in a single cell. But I have not found any CSS method of acheiving the desired formatting!

Simply setting a single column's text alignment to "center" doesn't keep the decimal points aligned.

Unless I am mistaken, using align="char" can't handle integer numbers that don't have an explicit decimal point, but still need to be aligned as if they did.

Appending a decimal character to integer numbers, even if hiding it, technically breaks the data integrity.

Padding the data with non-breaking spaces doesn't work with proportional (non-monospaced) fonts. And this hack too would break the data integrity.

Specifying position by fixed pixel offsets doesn't permit the column to have a truly "liquid" width, rendered as necessary to fit the contents of all cells in the column, including the header cell, which could contain data of any length at any time.

JavaScript that reads the resulting width of the table after it is rendered, then dynamically calculates pixel offsets, and then rewrites the formatting via DOM to "slide" the data into alignment is slow, and visually disrupting as the data jumps around. And it's an outright dirty hack that's even dirtier than using tables for layout purposes!

It almost seems to me like the "purist's" CSS-layout + HTML-semantic-data approach is incapable of doing this simple but often-desired layout! I'm hoping someone can please prove me wrong, and show me how to do this layout "properly".

Upvotes: 6

Views: 13851

Answers (4)

Robert Williams
Robert Williams

Reputation: 79

There is a pure html/css solution for this, but it's not pretty.
You need to separate the decimal aligned column into two columns, with no padding between them.
The first column has the integer value and is right aligned, the second has the decimal and the decimal value.

th 
  {
  text-align    : center;
  }
td:nth-child(2) 
  {
  text-align    : right;
  padding-right : 0;
  }
td:nth-child(3) 
  {
  position      : relative;
  left          : -0.2em;
  text-align    : left;
  padding-left  : 0;
  }
<table>
  <thead>
    <th>customers</th>
    <th colspan="2">balance</th>
  </thead>
  <tbody>
    <tr> <td>John</td> <td>4</td>     <td>.45</td> </tr>
    <tr> <td>Jane</td> <td>20</td>    <td></td>    </tr>
    <tr> <td>Jim</td>  <td>2,300</td> <td>.64</td> </tr>
  </tbody>
</table>

You could also use classes like .integer and .decimal as opposed to :nth-child selectors. That would be more robust, but I was trying to keep the markup short.

Upvotes: 5

ndp
ndp

Reputation: 21996

There is no way in raw HTML to do this. I wrote a jQuery plugin to solve just this problem. See https://github.com/ndp/align-column

It's simple to use with your uncorrupted table:

$('table').alignColumn(3); aligns column index 3.

Upvotes: 1

DanielBlazquez
DanielBlazquez

Reputation: 1055

I think the "charoff" attribute is what you need. Unfortunately, many browsers don't support it ...

http://www.w3.org/TR/1999/REC-html401-19991224/struct/tables.html#adef-charoff

Have you tried to divide each number into 2 strings? For example

"1234.567" will be "1234." and "567"

Then you can put the first string in a cell (right aligned), and the other part in the next cell (left aligned)

Upvotes: 0

Jukka K. Korpela
Jukka K. Korpela

Reputation: 201758

Given your requirements, there is no solution (even to the simpler issue of aligning to the decimal point).

Upvotes: 1

Related Questions