【问题标题】:Rotate text 270° in HTML/inlineSVG without fixed height?在没有固定高度的 HTML/inlineSVG 中将文本旋转 270°?
【发布时间】:2016-03-08 08:27:18
【问题描述】:

我想在 HTML5 中有这样的表格:

也就是说,第 2 列的标题旋转 270°,垂直对齐底部,水平居中,黑色背景上的白色字体,但没有为标题行/列设置明确的高度,最好没有诉诸使用 JavaScript 进行布局......

现在,直到现在,我都是通过使用服务器端图像生成来实现的,例如
<img src="handler.ashx?text=bla&fg=FFFFFF&bg=000000" />
不幸的是,这会禁用使用CTRL + F 搜索文本,这是相当不幸的,因为有很多组(数百个)。

现在有一些关于 SO 的帖子,例如
Rotate HTML SVG Text by 270 degrees
How to use CSS Rotate() in TH Table Tags
Rotating table header text with CSS transforms
https://jsfiddle.net/t5GgE/1/

但是它们要么明确地(或间接地)设置高度,要么在表头中使用背景颜色时无法正常工作。

现在我所拥有的是:
https://jsfiddle.net/kn46f38n/6/

垂直对齐底部不能正常工作,高度不能自动调整的问题(除非我添加了画布图像)。

所有这些都令人沮丧,这基本上意味着唯一的进展是用画布替换处理程序,这减轻了服务器的负担,但在可搜索性方面没有任何进展,最糟糕的是,使用 JS 进行布局虽然仍然有不支持画布的浏览器。

真的没有办法在 HTML/inlineSVG 中做到这一点,而不必设置显式高度(任何类型的高度,如包括变换原点)并且不必求助于 javascript 吗?

没有 jQuery:

var maxH = 0;
// Find the column label with the tallest height
var hdrs = document.querySelectorAll(".hdr")
for (i = 0; i < hdrs.length; i++)
{
    var bbox = hdrs[i].getBoundingClientRect();
    if (bbox.height > maxH)
        maxH = bbox.height;
}


// Make all the label cells that height
var cols = document.querySelectorAll(".col")
for (i = 0; i < cols.length; i++)
    cols[i].style.height = maxH + "px";

【问题讨论】:

    标签: html css svg


    【解决方案1】:

    啊,没关系,我自己搞定的。
    秘诀是让它垂直lr,所以宽度和高度已经是正确的。
    然后你所要做的就是将文本旋转 180 度,以 transform-origin 为中心...

    适用于 Chrome 和 Firefox 以及 IE 11 和 10(根据 MDN 向后兼容 IE9,但由于 ms-transform-rotate 不能正常工作,如果您省略它,它会优雅地降级为仅写入模式 vertical-lr毫秒转换)。

    https://developer.mozilla.org/en-US/docs/Web/CSS/text-orientation
    https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode#Browser_compatibility
    https://web.archive.org/web/20160320101147/https://msdn.microsoft.com/en-us/library/ms531187(v=vs.85).aspx

    .blackhd
    {
        vertical-align: bottom;
        width: 40px;
        #height: 100px;
        border: 1px solid hotpink;
        background-color: black;
        text-align: center;
    }
    
    .vert
    {
        display: inline-block;
        color: white;
        #font-weight: bold;
        font-size: 15px;
        writing-mode: vertical-lr;
        #writing-mode: vertical-rl;
        -ms-writing-mode: tb-rl;
        transform-origin: center;
        transform: rotate(180deg);
        padding-top: 2mm;
        padding-bottom: 3mm;
    }
    
    
    <table>
        <tr>
            <td class="blackhd"><span class="vert">abc</span></td>
            <td class="blackhd"><span class="vert">defghijkl</span></td>
        </tr>
        <tr>
            <td>abc</td>
            <td>defghijklmnopqr</td>
        </tr>
    </table>
    

    【讨论】:

      【解决方案2】:

      jQuery 和 SASS 都不是必需的,但似乎至少需要 Javascript:https://jsfiddle.net/yy3pgvoy/

      这是一个最小的解决方案。首先 HTML 可以是这样的:

          <table>
              <tr id="headers">
                  <td>Test</td>
                  <td>Test 2</td>
                  <td>Objektübersicht</td>
                  <td>Test3</td>
                  <td>Veni vidi vici</td>
              </tr>
              <tr>
                  <td>1</td><td>2</td><td>3</td><td>4</td><td>5</td>
              </tr>
          </table>
      

      标题的文字直接放在TD里面,然后Ctrl-F就可以正常工作了。

      然后,这个小脚本将根据旋转前 TD 的最大宽度来计算标题的高度。

      var size = 0;
      var cells = document.querySelectorAll("#headers > td");
      Array.prototype.forEach.call(cells, function(e) {
          var rect = e.getBoundingClientRect();
          size = Math.max( size, rect.width );
          e.innerHTML = "<div class='rot'><span>" + e.textContent + "</span></div>";
      });
      var headers = document.querySelector("#headers");
      headers.style.height = Math.ceil( size ) + "px";
      headers.className = "rotate";
      

      最后,你可以拥有这个 CSS:

      td { width: 32px; text-align: center; }
      #headers > td {
          position: relative;
          line-height: 32px;
          font-weight: bold;
          color: #fff;
          background: #000;
          white-space: nowrap;
          padding: 0 1ex;
          text-align: center;
          vertical-align: bottom;
      }
      #headers.rotate > td { width: 32px; max-width: 32px; white-space: normal; padding: 0; }
      #headers.rotate > td > div
      {
          position: relative;
          display: block;
          width: 32px;
          max-width: 32px;
          height: 32px;
          line-height: 32px;
          text-align: center;
          overflow: show;
          transform: rotate(-90deg);
      }
      #headers.rotate > td > div > span
      {
          position: absolute;
          left: 1ex;
          display: inline-block;
          white-space: nowrap;
          line-height: 32px;
      }
      

      我只是使用transform,所有浏览器都没有例外,但是添加所有供应商前缀很容易。

      【讨论】:

      • 不,这不是必需的。查看我的解决方案。
      【解决方案3】:

      下面的呢?只使用了相当少的 jQuery。

      // Find the column label with the tallest height
      var maxH = 0;
      $(".hdr").each(function(i, item) {
        var bbox = $(item).get(0).getBoundingClientRect();
        if (bbox.height > maxH) {
          maxH = bbox.height;
        }
      });
      
      // Make all the label cells that height
      $(".col").css('height', maxH + 'px');
      .col
      {
        background-color:black;
        width: 2em;
        line-height: 2em;
        vertical-align: bottom;
      }
      
      .hdr
      {
        transform: rotate(270deg);
        transform-origin: left top 0;
        color: white;
        position: absolute;
      }
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
      <table>
      <tr>
        <td class="col"><div class="hdr">Test</div></td>
        <td class="col"><div class="hdr">Test 2</div></td>
        <td class="col"><div class="hdr">Objekt&uuml;bersicht</div></td>
        <td class="col"><div class="hdr">Test3</div></td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      </table>

      【讨论】:

      • 是的,JavaScript 用于布局,绝对位置,为 3 行代码添加对 jQuery 的依赖项,并且必须在 2 个位置定义宽度,这意味着我可以选择添加 less 或 SASS 作为依赖。正是我不想要的那种东西。当您使用绝对位置时,问题不在于是否,而在于它何时中断。顺便说一句,我用它玩了大约 2 分钟,当我把边框折叠放在桌子上并从底部给它一个 2 毫米的填充时,它在 Chrome 中以 1 像素的差异打破了。看起来必须使用显示内联框而不是显示块。
      • 此外,一旦表格单元格内容的宽度比标题列长,标题列就不再在中间...
      • 非常感谢您讽刺的 cmets。批评我的解决方案没有满足您未说明的秘密要求是不公平的。您的示例图像具有固定宽度的列,所以我认为这就是您所需要的。为了简单起见,我在回答中使用了 jQuery。我从来没有说过你不能使用 vanilla JS。并且可以避免两个位置的宽度(我刚刚修改了我的示例)。
      • 好的,尽管我在表格中放了一些较长的文本进行测试时才意识到这个要求是不公平的。我已经删除了 jQuery。不过,问题是如何在不必求助于 JavaScript 的情况下做到这一点。无论如何,经过数小时的尝试,我找到了答案。基本上它非常简单,一旦你意识到它首先需要离开垂直文本来完成。
      • 您说“最好不要 JS”,而您对链接方法的主要反对意见似乎是它们都将高度设置为特定的预定大小。我想你可能会对一些自动计算出正确大小的简单 JS 感到满意。
      猜你喜欢
      • 2016-03-27
      • 2023-04-04
      • 1970-01-01
      • 2011-12-01
      • 1970-01-01
      • 2011-01-28
      • 2013-04-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多