在 HTML 中对齐小数点

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1363239/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 00:47:02  来源:igfitidea点击:

Aligning decimal points in HTML

htmlcss

提问by ijw

I have a table containing decimal numbers in one column. I'm looking to align them in a manner similar to a word processor's "decimal tab" feature, so that all the points sit on a vertical line.

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

I have two possible solutions at the moment but I'm hoping for something better...

目前我有两种可能的解决方案,但我希望有更好的解决方案......

Solution 1: Split the numbers within the HTML, e.g.

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

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

with

.dp { width: 3em; }

(Yes, this solution doesn't quite work as-is. The concept is, however, valid.)

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

Solution 2: I found mention of

解决方案 2:我发现提到

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

This is part of HTML4 according to the reference page, but it doesn't work in FF3.5, Safari 4 or IE7, which are the browsers I have to hand. It also has the problem that you can't pull out the numeric formatting to CSS (although, since it's affecting a whole column, I suppose that's not too surprising).

根据参考页面,这是 HTML4 的一部分,但它在 FF3.5、Safari 4 或 IE7 中不起作用,这是我必须使用的浏览器。它还存在一个问题,即您无法将数字格式提取到 CSS 中(尽管因为它影响了整个列,我认为这并不奇怪)。

Thus, anyone have a better idea?

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

采纳答案by Dan Diplo

See this article by Krijn Hoetmer for your options and how to achieve this. The essence of this solution is to use CSS and JS to achieve this:

请参阅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'></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'></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>

回答by David Leppik

Another way to format a number would be like this: 35<span style="visibility: hidden">.000</span>. That is, write it out with the full decimal expansion, but write the trailing decimals in invisible ink. That way you don't have to worry about the width of the decimal point.

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

回答by ard jonker

Cheat; benefit of this solution: also works for proportional fonts. Have one extra column and split the integer part from the decimal separator and the decimals. Then use this css and combine two columns in the header row:

欺骗; 此解决方案的好处:也适用于比例字体。多出一列并将整数部分与小数分隔符和小数分开。然后使用此 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>

回答by ard jonker

I played around with jQuery & came up with this...

我玩弄了 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>

It seemed to work.

它似乎奏效了。

回答by Rob Fonseca-Ensor

can you just print the numbers so that they always have the same number of decimal places, and right align them?

你能不能打印这些数字,让它们总是有相同的小数位数,并正确对齐它们?

回答by Tobia

I'm surprised that in 10 years of answers to this question, nobody ever mentioned the Unicode character 'FIGURE SPACE' (U+2007, &#8199;)

我很惊讶在这个问题的 10 年答案中,没有人提到过 Unicode 字符“FIGURE SPACE”(U+2007, &#8199;

It's a whitespace character that is designed (by font authors, if they follow the standard) to be the same width as digits and to keep its spacing, like its more famous cousin the No-Break Space. You can use it to pad numbers to a certain string size, either on the left or on the right hand side, taking care of aligning the column or div on the same side.

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

Examples, both left-aligned and left-padded with figure spaces:

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

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

回答by Soup Cup

I love short answers, even though the long ones are important too, so I liked;

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

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

and would just like to add;

并想补充;

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

just to throw php into the mix. Much depends on fixed width fonts, still, but the latter works for me. Since data oft is already tabular, adding another table within a cell is just too much typing and hard to maintain.

只是为了将 php 混入其中。仍然很大程度上取决于固定宽度的字体,但后者对我有用。由于数据通常已经是表格形式,因此在单元格中添加另一个表格太繁琐且难以维护。

回答by inanimatt

Thousands of years ago (or 2-3) I wrote a jQuery shim that emulates align="char" which still seems to work. It uses CSS padding and accounts for colspans, so it's moderately clever, but it's really not very pretty code (I was just starting out in javascript back then). I'd love for someone to rewrite it (and take all the credit).

数千年前(或 2-3 年)我写了一个 jQuery shim 来模拟 align="char" ,它似乎仍然有效。它使用 CSS 填充并考虑 colspans,所以它相当聪明,但它确实不是很漂亮的代码(当时我刚刚开始使用 javascript)。我希望有人重写它(并获得所有荣誉)。

In the mean time, see if this helps you: https://gist.github.com/inanimatt/f27ffd25c174e9d8a0907455395d147d

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

Trivia:The reason that browsers don't properly support column styles is that tables are 2D data structures and the DOM (which is what Javascript and CSS operate on, and how HTML5 is defined) is purely hierarchical and therefore can't represent both columns and rows. Instead it simply defines rows and cells, and doesn't represent columns at all.

琐事:浏览器不正确支持列样式的原因是表格是 2D 数据结构,而 DOM(这是 Javascript 和 CSS 操作的内容,以及 HTML5 的定义方式)是纯粹的层次结构,因此不能表示两列和行。相反,它只是定义行和单元格,根本不代表列。

回答by Mondane

The function made by Krijn Hoetmer interferes with prettyPhoto ( http://www.no-margin-for-errors.com/projects/prettyphoto-jquery-lightbox-clone/) so I made a jQuery version. The currency part is removed as it should be made dynamic instead of replacing strings based on predefined currencies.

Krijn Hoetmer 制作的功能会干扰到prettyPhoto ( http://www.no-margin-for-errors.com/projects/prettyphoto-jquery-lightbox-clone/) 所以我制作了一个jQuery 版本。货币部分被删除,因为它应该是动态的,而不是根据预定义的货币替换字符串。

Needed is the empty function from phpjs: http://phpjs.org/functions/empty:392.

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

The jQuery used, is version 1.6.

使用的 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();
});

回答by Eric

If the numbers are monospaced, javascript could be used to adjust the padding on the cell (in ems), depending on the number of digits before the decimal point. Otherwise, it could be tricky.

如果数字是等宽的,则可以使用 javascript 来调整单元格上的填充(以 em 为单位),具体取决于小数点前的位数。否则,它可能会很棘手。