在 HTML 中对小数点

我有一个在一列中包含十进制数的表。我希望以类似于文字处理器的“十进制标签”功能的方式对齐它们,这样所有的点都在一条垂直线上。

我现在有两个可能的解决方案,但我希望能有更好的..。

解决方案1: 拆分 HTML 中的数字,例如。

<td><div>1234</div><div class='dp'>.5</div></td>

.dp { width: 3em; }

(是的,这个解决方案并不完全按原样工作。但是,这个概念是有效的。)

解决方案2: 我发现提到

<col align="char" char=".">

根据参考页面,这是 HTML4的一部分,但是它不能在 FF3.5、 Safari 4或 IE7中工作,这些浏览器是我必须使用的。它还存在一个问题,即无法将数字格式转换为 CSS 格式(不过,由于它会影响整个列,我想这并不太令人惊讶)。

因此,有人有更好的主意吗?

64748 次浏览

你能不能把这些数字打印出来,这样它们的小数位数就一直保持不变,然后右对齐?

如果数字是等间距的,则可以使用 javascript 来调整单元格上的填充(在 ems 中) ,这取决于小数点前的数字数量。否则,就麻烦了。

请参阅 本文作者: Krijn Hoetmer了解您的选项以及如何实现这一点。这个解决方案的实质是使用 CSS 和 JS 来实现这一点:

(function() {
var currencies = /(\$|€|&euro;)/;
var leftWidth = 0, rightWidth = 0;
for(var tableCounter = 0, tables = document.getElementsByTagName("table");
tableCounter < tables.length; tableCounter++) {
if(tables[tableCounter].className.indexOf("fix-align-char") != -1) {
var fCols = [], leftPart, rightPart, parts;
for(var i = 0, cols = tables[tableCounter].getElementsByTagName("col"); i < cols.length; i++) {
if(cols[i].getAttribute("char")) {
fCols[i] = cols[i].getAttribute("char");
}
}
for(var i = 0, trs = tables[tableCounter].rows; i < trs.length; i++) {
for(var j = 0, tds = trs[i].getElementsByTagName("td"); j < tds.length; j++) {
if(fCols[j]) {
if(tds[j].innerHTML.indexOf(fCols[j]) != -1) {
parts = tds[j].innerHTML.split(fCols[j]);
leftPart = parts.slice(0, parts.length -1).join(fCols[j]);
leftPart = leftPart.replace(currencies, "<span class='currency'>$1</span>");
rightPart = fCols[j] + parts.pop();
tds[j].innerHTML = "<span class='left'>" + leftPart + "</span><span class='right'>" + rightPart + "</span>";
} else {
tds[j].innerHTML = tds[j].innerHTML.replace(currencies, "<span class='currency'>$1</span>");
tds[j].innerHTML = "<span class='left'>" + tds[j].innerHTML + "</span>";
}
tds[j].className = "char-align";
var txt = document.createTextNode(tds[j].firstChild.offsetWidth);
if(leftWidth < tds[j].firstChild.offsetWidth) {
leftWidth = tds[j].firstChild.offsetWidth;
}
if(tds[j].childNodes[1]) {
txt = document.createTextNode(tds[j].childNodes[1].offsetWidth);
if(rightWidth < tds[j].childNodes[1].offsetWidth) {
rightWidth = tds[j].childNodes[1].offsetWidth;
}
}
}
}
}
}
}
// This is ugly and should be improved (amongst other parts of the code ;)
var styleText = "\n" +
"<style type='text/css'>\n" +
"  .fix-align-char td.char-align { width: " + (leftWidth + rightWidth) + "px; }\n" +
"  .fix-align-char span.left { float: left; text-align: right; width: " + leftWidth + "px; }\n" +
"  .fix-align-char span.currency { text-align: left; float: left; }\n" +
"  .fix-align-char span.right { float: right; text-align: left; width: " + rightWidth + "px; }\n" +
"</style>\n";
document.body.innerHTML += styleText;
})();
table {
border-collapse: collapse;
width: 600px;
}
th {
padding: .5em;
background: #eee;
text-align: left;
}
td {
padding: .5em;
}
#only-css td.char-align {
width: 7em;
}
#only-css span.left {
float: left;
width: 4em;
text-align: right;
}
#only-css span.currency {
float: left;
width: 2em;
text-align: left;
}
#only-css span.right {
float: right;
width: 3em;
text-align: left;
}
<table id="only-css">
<thead>
<tr>
<th>Number</th>
<th>Description</th>
<th>Costs</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Lorem ipsum dolor sit amet</td>
<td class="char-align">
<span class="left">
<span class="currency">$</span>3
</span>
<span class="right">,99</span>
</td>
</tr>
<tr>
<td>2</td>
<td>Consectetuer adipiscing elit</td>
<td class="char-align">
<span class="left">
<span class="currency">$</span>13
</span>
<span class="right">,95</span>
</td>
</tr>
<tr>
<td>3</td>
<td>Pellentesque fringilla nisl ac mi</td>
<td class="char-align">
<span class="left">
<span class="currency">$</span>4
</span>
<span class="right"></span>
</td>
</tr>
<tr>
<td>4</td>
<td>Aenean egestas gravida magna</td>
<td class="char-align">
<span class="left">
<span class="currency">$</span>123
</span>
<span class="right">,999</span>
</td>
</tr>
</tbody>
</table>

我和 jQuery 一起玩过,然后想出了这个..。

$(document).ready(function() {
$('.aBDP').each(function() {
var wholePart, fractionPart;
wholePart = Math.floor($(this).text()-0);
fractionPart = Math.floor(($(this).text() % 1)*10000 + 0.5) / 10000 + "";
html  = '<span class="left">' + wholePart + '.' + '</span>';
html += '<span class="right">' + fractionPart.substring(2) + '</span>';
$(this).html(html);
})
})
.right {
text-align: left;
}
.left {
float:left;
text-align: right;
width:10em;
}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js" type="text/javascript"></script>


<table width="600" border="1">
<tr><th></th><th>Aligned Column</th></tr>
<tr><th>1st Row</th><td class='aBDP'>1.1</td></tr>
<tr><th>2nd Row</th><td class='aBDP'>10.01</td></tr>
<tr><th>3rd Row</th><td class='aBDP'>100.001</td></tr>
<tr><th>4th Row</th><td class='aBDP'>1000.0001</td></tr>
</table>

看起来挺管用的。

另一种格式化数字的方法是这样的: 35<span style="visibility: hidden">.000</span>。也就是说,用完整的小数展开式写出来,但是用看不见的墨水写出尾随的小数。这样你就不用担心小数点的宽度了。

欺骗; 这个解决方案的好处: 也适用于比例字体。有一个额外的列,把整数部分从小数点和小数中分离出来。然后使用 css 并在标题行中合并两列:

table {border-collapse:collapse;}
td {padding:0px;margin:0px;border:0px;}
td+td {text-align:right;}
td, td+td+td {text-align:left;}
<table>
<tr><th>Name</th><th colspan=2>Height</th></tr>
<tr><td>eiffeltower</td> <td>324</td> <td></td></tr>
<tr><td>giraffe</td> <td>5</td> <td>,30</td></tr>
<tr><td>deer</td> <td>1</td> <td></td></tr>
<tr><td>mouse</td> <td>0</td> <td>,03</td></tr>
</table>

注意: 这并不能保证一定有效。例如,在2021年的 Safari 14上:

几千年前(或者2-3年前) ,我写了一个 jQuery 垫片,它模拟了似乎仍然可以工作的里排 = “ char”。它使用 CSS 填充和 colspans 帐户,所以它相当聪明,但它真的不是非常漂亮的代码(我刚刚开始在 javascript 回来)。我希望有人能重写它(并把所有的功劳)。

同时,看看这是否对你有帮助: https://gist.github.com/mattattui/f27ffd25c174e9d8a0907455395d147d

花絮: 浏览器不支持列样式的原因是表是2D 数据结构,而 DOM (这是 Javascript 和 CSS 操作的方式,也是定义 HTML5的方式)是纯粹的层次结构,因此不能同时表示列和行。相反,它仅仅定义了行和单元格,并且根本不表示列。

由 Krijn Hoetmer 创建的函数干扰了 pretty tyPhoto (http://www.no-margin-for-errors.com/projects/prettyphoto-jquery-lightbox-clone/) ,因此我创建了一个 jQuery 版本。货币部分被删除,因为它应该是动态的,而不是根据预定义的货币替换字符串。

需要的是 phpjs 的空函数: http://phpjs.org/functions/empty:392

使用的 jQuery 版本是1.6。

/* This function will align table columns on the char if in the col from the
* colgroup has the property 'align="char"' and a attribute 'char'. The alignment
* is done on the first occurence of the specified char.
*
* The function is inspired from:
*
* http://krijnhoetmer.nl/stuff/javascript/table-align-char/
* http://stackoverflow.com/questions/1363239/aligning-decimal-points-in-html
*/
function alignNumbers()
{
var table; /* This will store the table currently working on . */
var i = 0; /* Every column can have it's own width, the counter makes the class name unique. */


/* Get all tables for which the alignment fix must be done.
*
* Note: this could even be further optimized by just looking for tables where
* there is a a col with 'align="char"'.
*/
$('table.fix-align-char').each(function(index)
{
table = $(this);


/* All table columns are fetched to have a correct index, without it it's
* hard to get the correct table cells.
*/
$(this).find('col').each(function(index)
{
/* Only those table cells are changed for which the alignment is set to
* char and a char is given.
*/
if ($(this).prop('align') == 'char' && !empty($(this).attr('char')))
{
/* Variables for storing the width for the left and right part (in pixels). */
var left_width = 0, right_width = 0;
var col, left_part, right_part, parts, new_html;
i++; /* Increase the counter since we are working on a new column. */
col = $(this);


/* For the col index + 1 (nth-child starts counting at 1), find the table
* cells in the current table.
*/
table.find('> tbody > tr > td:nth-child('+ (index + 1) +')').each(function(index)
{
/* Split the html on the specified char. */
parts = $(this).html().split(col.attr('char'));
new_html = '';




/* The first element is always the left part. The remaining part(s) are
* the right part. Should there be more chars in the string, the right
* parts are rejoined again with the specified char.
*/
left_part = parts.shift();
right_part = parts.join(',');


/* Add a left part to the new html if the left part isn't empty*/
if (!empty(left_part))
{
new_html = new_html + '<span class="left">' + left_part + '</span>';
}


/* Add the specified char and the right part to the new html if
* the right part isn't empty*/
if (!empty(right_part))
{
new_html = new_html + col.attr('char') + '<span class="right">' + right_part + '</span>';
}


/* If there is a new html, the width must be determined and a class is
* added.
*
* Note: outerWidth is used instead of width so padding, margin and
* borders are taken into account.
*/
if (!empty(new_html))
{
$(this).html(new_html); /* Set the new html. */
$(this).addClass('char-align-' + i); /* Add a class to the table cell. */


/* Get the left span to determine its outer width. */
leftSpan = $(this).children('.left');


if (!empty(leftSpan) && left_width < leftSpan.outerWidth())
{
left_width = leftSpan.outerWidth();
}


/* Get the right span to determine its outer width. */
rightSpan = $(this).children('.right');


if (!empty(rightSpan) && right_width < rightSpan.outerWidth())
{
right_width = rightSpan.outerWidth();
}


}


});


/* Only if any width is larger then 0, add a style. */
if (left_width > 0 || right_width > 0)
{
style_text = '<style type="text/css">.fix-align-char td.char-align-' + (i) + ' span.left { float: left; text-align: right; width: ' + (left_width) + 'px; }\n.fix-align-char td.char-align-' + (i) + ' span.right { float: right; text-align: left; width: ' + right_width + 'px; }</style>';
$('head').append(style_text);
}


}
});
});


}


$(document).ready(function(){
alignNumbers();
});

我喜欢简短的回答,即使长的也很重要,所以我喜欢;

35<span style="color:transparent">.000</span>

我想补充一句

<TD><div style='float:right;'><?php echo number_format($totalAmount,2); ?></div></TD>

只是为了混淆视听。这在很大程度上依赖于固定宽度的字体,但后者对我很有用。由于数据往往已经是表格式的,在单元格中添加另一个表格只是太多的类型和难以维护。

我使用 JavaScript 来解决这个问题..。 这是我的 HTML。

<body>
<table id="nadis">


</tr>
</table>


</body>

这是我的 JavaScript。

var numarray = ["1.1", "12.20", "151.12", 1000.23,12451];
var highetlen = 0;
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>";
}

令我惊讶的是,在这个问题的10年回答中,从来没有人提到过 Unicode字符“图形空间”(u + 2007,&#8199;)

这个空白字符的设计(由字体设计者设计,如果他们遵循标准的话)与数字的宽度相同,并保持其间距,就像它更著名的表亲 No-Break Space 一样。您可以使用它将数字填充到特定的字符串大小,无论是在左侧还是右侧,要注意将列或 div 对齐到同一侧。

例如,左对齐和左填充的图形空间:

<p style="font-family: sans-serif">
10000 <br>
&#8199;&#8199;123.4 <br>
&#8199;&#8199;&#8199;&#8199;3.141592
</p>


<p style="font-family: serif">
10000 <br>
&#8199;&#8199;123.4 <br>
&#8199;&#8199;&#8199;&#8199;3.141592
</p>

在以前的方法中有一个严重的问题,那就是 只能用视觉思考,但是在其他需要或使用表的地方却不如 分类过滤,因为在 过滤中纯数据非常重要。

不幸的是,CSS4还不可用。然后有效的解决方案可以在 td 单元的数据属性中传递值和单元或类型单元。

<!-- HTML-->
<table>
<tbody>
<tr>
<td data-value="1876.67542" data-unit="USD"></td>
</tr>
</tbody>
</table>

如果一个单元格有一个数据值,它必须用 javascript 读取并更新为我们需要的十进制数。

// Javascript
let $td_value = document.querySelectorAll( 'td[data-item]' );
Array.from( $td_value ).forEach( $r => {
$r.textContent = parseFloat( $r.getAttribute('data-value') ).toFixed(2);
});

最后,当我们有规范化的数据,他们将看起来很棒与单字体和他们的单位放置使用 css 选择器之前或之后。

/* CSS */
td[data-value]{
font-family: monospace;
text-align: right;
}
td[data-unit]::after{
content: attr(data-unit]);
font-size: 85%;
padding-left: .2em;
opacity: .6;
}

我在 https://jsfiddle.net/jam65st/wbo63xpu/12/中放了一个扩展的例子

丑陋的变通方法,但是可以让你免于编写大量代码: 你可以在价格数组(列表)中找到最大数字,然后你可以取其数字并设置内嵌式样式 "width": (maxNumberDigits * 10)px-这是丑陋的部分! 此数据的容器(单元格,如果它的表)应该另外具有

display:flex;
justify-content: flex-end;

结果:

Result