9

I am building a wordpress plugin which is generating an HTML table and sending to gravityforms html block via shortcode.

My problem is that cell contents can contain:

  • 23.24
  • 1,234.665
  • 123.4

etc...

Notice the differing number of decimal places.

Is there a non-hack & best practice way of aligning this column data by decimal point? In this case, Aligning right will not work.

Inserting 0s is not acceptable because this indicates a degree of accuracy which is not there.

As you can see, I have attempted to use align="char" char="." inside the td elements with no luck.

Any help anybody can help with this would be much appreciated.

Many thanks.

Is there a way of using printf("%8.3f",d1) or similar without actually printing to the screen? e.g. structuring the variable d1 for later use but not actually printing it?

Gravy
  • 11,344
  • 21
  • 112
  • 184

7 Answers7

5

There is no direct way to do this. HTML 4.01 has align=char, but without any browser support. CSS 2.0 had a counterpart, using the text-align property, with equal lack of support, so it was dropped from CSS 2.1. CSS3 drafts have a nice system for such alignment, but indicated as being in danger of being cut from the spec if there are no (correct) implementations.

As a workaround, you could right-pad the values with something invisible (blank) so that when the values aligned to the right, the decimal markers get aligned. There are several ways to try to achieve this:

1) Use digit 0 but set a style on it, making it invisible, e.g.

123.4<span class=s>00</span>

with

.s { visibility: hidden; }

2) Use FIGURE SPACE U+2007, defined to have the same width as digits (when digits are of equal width), e.g.

123.4&#x2007;&#x2007;

For this to work, you need to set the font so that it contains U+2007. According to http://www.fileformat.info/info/unicode/char/2007/fontsupport.htm even Arial contains it, but I’m afraid this might not apply to old versions of Arial still in use.

3) Use a no-break space and set its width to the desired number of digits, using the ch unit (define to have the width of digit 0), though this unit is relatively new and not supported by old browsers. Example:

123.4<span class=d2>&nbsp;</span>

with

.d2 { width: 2ch; display: inline-block; }

I would probably use the first method. As a matter of principle, it has the drawback that when CSS is off, the data contains zeroes, which imply wrong information about accuracy, whereas in other methods, switching CSS off “only” messes up the layout.

(It’s probably obvious that digits must be of equal advance width, so that you can align numeric data at all. This just means that the font used for the values must have that property. Most fonts will do in this respect, but e.g. Georgia, Constantia, and Corbel won’t.)

Jukka K. Korpela
  • 178,198
  • 33
  • 241
  • 350
4

I wrote a jQuery plugin that solves this. It's found here: https://github.com/ndp/align-column

Using your raw HTML table, it will align a column by decimal points:

$('table').alignColumn(3);

It does this by adding another column, but does its best to not corrupt the other spacing. There's also a reference to a different solution on the Github page.

ndp
  • 19,946
  • 4
  • 33
  • 48
  • 1
    Adding a column changes the structure of the table. This may have a serious impact on styling (e.g., if `td:nth-child(...)` has been used) and on accessibility. – Jukka K. Korpela Dec 15 '13 at 08:00
  • Yes, definitely. But most solutions will have some effect on the markup. The repo has links to a different solution that uses spans (I believe). – ndp Jan 12 '14 at 03:20
1

Would it be acceptable to put the value into two columns?

Use sprintf() to convert the value into a string, and then put the bits up to the decimal point in the left column (but right aligned), and the decimal places in the second column.

See http://jsfiddle.net/alnitak/p4BhB/, but ignore the JS bit...

Alnitak
  • 313,276
  • 69
  • 379
  • 466
  • See my post below for a jQuery plugin that does this unobtrusively... https://github.com/ndp/align-column – ndp Apr 10 '13 at 18:56
0

The thing is, you've gotta ensure that they all have the same number of digits after the decimal.

Once you do that, use text-align. All it will take is a: style='text-align: right'

Better still, you could use a css class instead of inline styles. Your markup would look like this:

 <tr><td>Item 1</td><td>15</td><td class='price'>&pound;123.25</td></tr>

Then in your stylesheet:

td.price{
  text-align: right;
}

With php, you can format a number as a string with number_format. You don't have to echo it or print it, just wrap your variable in that function. For example:

$table .= "<td class='price'>&pound;" . $price . "</td></tr>";

becomes:

$table .= "<td class='price'>&pound;" . number_format($price,3) . "</td></tr>";
Joe Flynn
  • 6,164
  • 6
  • 28
  • 43
  • I am already aware of this solution, but Is that the ONLY way of doing it? I was hoping for a justify by decimal point kind of solution as the table fills the div and I don't want to muck about with paddings, margins etc... – Gravy Jul 22 '12 at 13:58
  • I believe this is the best you're going to find. This is not hacky in the slightest, there's no padding or margin mucking. You want it right aligned, one css declaration is all it takes. – Joe Flynn Jul 22 '12 at 14:04
  • Ok... Maybe the example I gave was incorrect. I think I need to clarify myself. The reason I need to justify by decimal point is because I cannot guarantee the accuracy of the decimal places. e.g. some values may have an accuracy of 2dp, some an accuracy of 3 dp. My bad - I will re-phrase question. This is why I need it aligned by decimal point. Real data will not be for currency. – Gravy Jul 22 '12 at 14:10
0

It might be overkill but I needed the same thing and just solved with a length of the output and adding whitespace based on that length.

I.e.:

if (strlen($meal_retail) == 5) {
echo "&nbsp;&nbsp;&nbsp;&nbsp;";
}
else (strlen($meal_retail) == 6) {
    echo "&nbsp;&nbsp;";
}

This lined up my decimals correctly with a bit of extra doing, and i'm sure an array could clean the above code up even nicer.

Additionally, i've been conforming my numbers adjusting with:

echo money_format('%i',$meal_retail)  (makes it a two decimal money number)

Just wanted to provide my solution as I was looking at this page before coming up with my own resolution.

0

this is my solution, hope it help!!

<style type="text/css">
td{
    font-family: arial;
}
.f{
    width: 10px;
    color: white;
    -moz-user-select: none;
}
</style>

<table>
<tr><td><span class="f">00</span>1.1<span class="f">00</span></td></tr>
<tr><td><span class="f">0</span>12.34<span class="f">0</span></td></tr>
<tr><td>123.456</td></tr>
</table>

with this, you can't see the zeros and can't select them!

0

I have used javascript for this, I hope this will help.......

</tr>
</table>

</body>
for(var i=0; i<numarray.length; i++){
    var n = numarray[i].toString();
  var res= n.split(".");
  n = res[0];

  if(highetlen < n.length){
    highetlen = n.length;
  }

}

for(var j=0; j<numarray.length; j++){
    var s = numarray[j].toString();
  var res= s.split(".");
  s = res[0];

    if(highetlen > s.length){
  var finallevel = highetlen - s.length;

  var finalhigh = "";
  for(k=0;k<finallevel;k++){
  finalhigh = finalhigh+ '&#160; ';
  }
    numarray[j] = finalhigh + numarray[j];
  }
  var nadiss = document.getElementById("nadis");
  nadiss.innerHTML += "<tr><td>" + numarray[j] + "</td></tr>";
}