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

11,942

Solution 1

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.

<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>

<style>
    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;
    }
</style>

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.

Solution 2

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.

Share:
11,942
user1645764
Author by

user1645764

Updated on June 17, 2022

Comments

  • user1645764
    user1645764 almost 2 years

    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".