我在一列中有一个包含十进制数的表。我希望以类似于文字处理器的“十进制标签”功能的方式对齐它们,以便所有点都位于垂直线上。
目前我有两种可能的解决方案,但我希望有更好的解决方案......
解决方案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(虽然,因为它影响整个列,我想这并不太令人惊讶)。
因此,任何人都有更好的主意吗?
答案 0 :(得分:21)
有关您的选项以及如何实现此目的,请参阅this article by Krijn Hoetmer 。这个解决方案的本质是使用CSS和JS来实现这个目标:
(function() {
var currencies = /(\$|€|€)/;
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>
答案 1 :(得分:14)
格式化数字的另一种方法是:35<span style="visibility: hidden">.000</span>
。也就是说,用完整的十进制扩展写出来,但是用隐形墨水写下尾随小数。这样你就不用担心小数点的宽度了。
答案 2 :(得分:9)
作弊;此解决方案的好处:也适用于比例字体。有一个额外的列并从小数分隔符和小数分割整数部分。然后使用此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>
答案 3 :(得分:8)
我玩jQuery&amp;想出了这个......
$(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>
似乎有效。
答案 4 :(得分:4)
你能打印这些数字,以便它们总是有相同的小数位数,然后右对齐它们吗?
答案 5 :(得分:4)
对于这个问题的十年答案,我感到惊讶的是,没有人提到Unicode字符“ FIGURE SPACE”(U + 2007, 
)
这是一个空白字符,它被设计(如果字体作者遵循标准,则由字体作者设计)使其与数字相同,并保持其间距,就像其更著名的表亲No-Break Space。您可以使用它在左侧或右侧将数字填充为特定的字符串大小,注意将列或div对齐在同一侧。
示例,左对齐和左填充图形空间:
<p style="font-family: sans-serif">
10000 <br>
  123.4 <br>
    3.141592
</p>
<p style="font-family: serif">
10000 <br>
  123.4 <br>
    3.141592
</p>
答案 6 :(得分:1)
几千年前(或2-3)我写了一个jQuery shim,它模仿了align =“char”,但它似乎仍然有效。它使用CSS填充和帐户的colspans,所以它是适度的聪明,但它真的不是很漂亮的代码(我当时刚开始在javascript中)。我喜欢有人重写它(并且取得所有功劳)。
同时,看看这是否对您有所帮助:https://gist.github.com/inanimatt/f27ffd25c174e9d8a0907455395d147d
琐事:浏览器不能正确支持列样式的原因是表是2D数据结构和DOM(这是Javascript和CSS操作的,以及HTML5的定义方式)是纯粹是分层的,因此不能代表列和行。相反,它只是定义行和单元格,而根本不代表列。
答案 7 :(得分:1)
我喜欢简短的答案,即使长篇文章也很重要,所以我很喜欢;
35<span style="color:transparent">.000</span>
并且只想添加;
<TD><div style='float:right;'><?php echo number_format($totalAmount,2); ?></div></TD>
只是把php扔进混音。很大程度上取决于固定宽度字体,但后者适用于我。由于数据已经是表格式的,因此在单元格中添加另一个表格只是输入太多而且难以维护。
答案 8 :(得分:0)
如果数字是等宽的,则javascript可用于调整单元格上的填充(以ems为单位),具体取决于小数点前的位数。否则,它可能会很棘手。
答案 9 :(得分:0)
Krijn Hoetmer所做的功能干扰了prettyPhoto(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();
});
答案 10 :(得分:0)
我用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+ '  ';
}
numarray[j] = finalhigh + numarray[j];
}
var nadiss = document.getElementById("nadis");
nadiss.innerHTML += "<tr><td>" + numarray[j] + "</td></tr>";
}
答案 11 :(得分:0)
之前方法的一个严重问题是只考虑视觉,而不考虑其他需要或使用表格作为排序或过滤< /strong>,纯数据很重要。
不幸的是,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/