代码之家  ›  专栏  ›  技术社区  ›  ijw

在HTML中对齐小数点

  •  67
  • ijw  · 技术社区  · 15 年前

    我有一张表,列中有十进制数。我希望以类似于字处理程序的“十进制制表符”功能的方式对齐它们,以便所有点都位于垂直线上。

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

    解决方案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中(尽管,由于它会影响整个列,所以我认为这并不太令人惊讶)。

    因此,有人有更好的想法吗?

    10 回复  |  直到 6 年前
        1
  •  21
  •   Nhan Jonesinator    8 年前

    this article by 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>
        2
  •  12
  •   David Leppik    6 年前

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

        3
  •  9
  •   ard jonker    13 年前

    作弊;这个解决方案的好处:也适用于比例字体。有一个额外的列,并将整数部分从十进制分隔符和小数中拆分。然后使用这个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>
    
        4
  •  8
  •   milar    15 年前

    我玩过jquery,想出了这个……

    HTML

    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>
    

    JavaScript

    $(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); 
      })
    })
    

    CSS

    .right {
        text-align: left;
    }
    .left {
        float:left;
        text-align: right;
        width:10em;
    }
    

    它似乎起作用了

        5
  •  4
  •   Rob Fonseca-Ensor    15 年前

    你能把这些数字打印出来,使它们总是有相同的小数位数,然后右对齐吗?

        6
  •  1
  •   Soup Cup    11 年前

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

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

    只是想补充一下;

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

    只是把PHP加入到混合中。很大程度上还是取决于固定宽度的字体,但后者对我有用。由于OFT的数据已经是表格式的,所以在一个单元格中添加另一个表太多了,难以维护。

        7
  •  1
  •   inanimatt    8 年前

    数千年前(或2-3年前),我编写了一个jquery填充程序,它模拟align=“char”,但似乎仍然有效。它使用了CSS填充和对colspans的解释,所以它有点聪明,但它实际上不是很好的代码(那时我刚开始使用javascript)。我希望有人能重写它(并获得所有的荣誉)。

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

    琐事: 浏览器不正确支持列样式的原因是表是二维数据结构,而DOM(这是JavaScript和CSS操作的对象,以及如何定义HTML5)是纯层次结构的,因此不能同时表示列和行。相反,它只定义行和单元格,根本不表示列。

        8
  •  0
  •   Eric    15 年前

    如果数字是单空格的,则可以使用javascript根据小数点前的位数来调整单元格的填充(在ems中)。否则,可能会很棘手。

        9
  •  0
  •   Mondane    13 年前

    Krijn-Hoetmer的功能干扰了斑疹前病变( 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
  •   Narendra Sagadevan    7 年前

    我用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>";
    }