【问题标题】:CSS overflow detection in JavaScriptJavaScript 中的 CSS 溢出检测
【发布时间】:2010-12-30 04:49:23
【问题描述】:

为了显示一行文本(如在论坛中),如果文本溢出该行(不使用 CSS overflow 属性截断),则以“...”结束该行,有一个方式数。我仍在寻求最佳解决方案。例如,

在 CSS 中添加“...”作为背景图像是可能的,但它会一直出现,这不是一个好的解决方案。

有些网站只计算字符数,如果超过 - 比如说 - 100,则截断字符串以仅保留 100(或 97)个字符并在末尾添加“...”。但是字体通常不成比例,所以结果并不漂亮。例如空间 - 以像素为单位 - 由

  • “AAA”和“iii”明显不同
  • "AAA""iii" 通过比例字体具有相同的宽度

还有另一种方法可以获取字符串的确切大小(以像素为单位):

  • 在 Javascript 中创建一个 DIV
  • 在其中插入文本(例如通过 innerHTML)
  • 测量宽度(通过 .offsetWidth)

尚未实施。不过不知道会不会是浏览器兼容性问题呢?
有没有人尝试过这个解决方案?欢迎其他建议。

【问题讨论】:

  • 我喜欢使用 DIV 将字符串的宽度识别为 HTML 元素
  • @Cyber​​nate:DIV 不是一个好的解决方案,因为它默认继承父级的宽度,不允许它随着内容“增长”。最好使用SPANcase in point
  • @Brad 在 JavaScript 中创建一个 DIV 而不将其附加到任何父级不是解决方案吗?
  • 没有。如果未附加,您将始终获得 0 宽度。自己试试:var d = $('<div>');/*$('body').append(d);*/d.text('Hello,World!');var w1 = d.width();d.text('Longer string goes here');var w2 = d.width();alert('Short: '+w1+'\nLong: '+w2);(注释和取消注释附加语句 [使用 jQuery 为简单起见])

标签: javascript css


【解决方案1】:

所以,我用一点 JS 就能让它工作:http://jsfiddle.net/ug8Fc/3/

基本上,它使用隐藏在背景中的虚拟跨度来计算“内容”的宽度(这应该允许使用几乎任何类型的字体,因为跨度会相应地扩展)。然后如果内容超出容器,它会为省略号腾出空间并不断删除字符,直到合适为止。最后,重新添加修改后的内容和省略号。

如果有人变得精力充沛,也许你可以把它做成一个 jquery 函数,可以更容易地应用于任何选择器。

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title> - jsFiddle demo</title>
  <script type='text/javascript' src='http://code.jquery.com/jquery-1.4.4.min.js'></script>
  <link rel="stylesheet" type="text/css" href="/css/normalize.css">
  <link rel="stylesheet" type="text/css" href="/css/result-light.css">  
  <style type='text/css'>
    table {
      border: 1px solid #000;
      border-collapse: collapse;
      border-spacing: 0;
      width: 800px;
    }
    table thead {
      background-color: #AAA;
      color: #333;
    }
    table tbody tr {
      border: 1px solid #000;
    }
    table tbody td {
      padding: 2px;
    }
    .from {
      width: 100px;
    }
    .preview {
    }
    .date {
      width: 90px;
    }
  </style>
  <script type='text/javascript'>
  //<![CDATA[ 
  $(window).load(function(){
    // Create a span we can use just to test the widths of strings
    var spanTest = $('<span>').css('display','none').attr('id','span-test-tester');
    $('body').append(spanTest);

    // function to get the length of a string
    function getLength(txt){
        return spanTest.text(txt).width();
    }

    // now make all the previews fit
    $('table tbody .preview').each(function(){
        // build a bench-mark to gauge it from
        var roomWidth = $(this).innerWidth();

        // now, get the width and play with it until it fits (if it doesn't)
        var txt = $(this).text();
        var contentsWidth = getLength(txt);
        if (contentsWidth > roomWidth){ // bigger than we have to work with
            roomWidth -= getLength('...'); // work within confines of room + the ellipsis
            while (contentsWidth > roomWidth){ 
                txt = txt.substring(0,txt.length-1);
                contentsWidth = getLength(txt);
            }
            // set the text to this
            $(this).text(spanTest.text()).append($('<span>').text('...'));
        }
    });

  });
  //]]> 
  </script>
</head>
<body>
  <table>
    <thead>
      <tr>
        <th class="from">From</th>
        <th class="preview">Subject</th>
        <th class="date">Date</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td class="from">Joe Smith</td>
        <td class="preview">Hello bob, I just wanted to check in and see how things were going.
            I know we spoke last week about etc. etc. etc.</td>
        <td class="date">Dec 1, 2010</td>
      </tr>
      <tr>
        <td class="from">John Doe</td>
        <td class="preview">Hey bob, got any plans for new years yet?</td>
        <td class="date">Dec 28, 2010</td>
      </tr>
      <tr>
        <td class="from">Ben Franklin</td>
        <td class="preview">Happy New Year! Hope you had a great time at the casinos (and didn't
            spend too much money (haha)). Hope to see you this Memorial day blah blah blah
      </tr>
    </tbody>
  </table>
</body>
</html>

【讨论】:

  • 谢谢。如果其他人变得精力充沛,她可以在所有主流浏览器上进行测试:-)
  • @ring0:作为说明,我注意到在该表的某些宽度上,它偏离了一些固定线(给我留下了一条意外的换行线)。这是因为 roomWidth -= getLength('...'); 不够用。如果它看起来很常见,请尝试将该行更改为 roomWidth -= getLength('...') + 5; 以给自己更多的缓冲。
【解决方案2】:

这可以通过 css 使用 text-overflow: ellipsis 轻松完成。无需 hacky javascript。

http://www.w3schools.com/cssref/css3_pr_text-overflow.asp

【讨论】:

  • 不确定问题是否在您发布后更新,但目前问题包括“(不使用 CSS 溢出属性截断)。”这意味着他们考虑过并且不想使用您的建议(尽管显然这是最简单的方法)。
【解决方案3】:

这段代码对我很有帮助,谢谢!

但我注意到一些改进:

1/ 解决某些情况下宽度不够的问题

替换:

<td class="preview">Hey bob, got any plans for new years yet?</td>

与:

<td><div class="preview">Hey bob, got any plans for new years yet?</div></td>

2/ 该脚本不适用于特定字体(大小、重量、系列...)

您需要将字体应用到用于计算文本大小的“不可见”范围。例如(必要时完成所有需要的字体属性):

    (...)
    // build a bench-mark to gauge it from
    var roomWidth = $(this).innerWidth();

    // now, get the width and play with it until it fits (if it doesn't)
    var fontSize=$(this).css("font-size");
    spanTest.css("font-size", fontSize);
    var fontStyle=$(this).css("font-style");
    spanTest.css("font-style", fontStyle);
    var fontWeight=$(this).css("font-weight");
    spanTest.css("font-weight", fontWeight);
    var fontFamily=$(this).css("font-family");
    spanTest.css("font-family", fontFamily);
    (...)

3/ 表演

我用 1000 个元素进行了测试,每个元素都有 25 个额外字符要删除(在 Firefox 7 上) 您的脚本需要将近 40 秒才能完成工作。

看来问题出在“display:none”跨度上。

使用“position:absolute;top:-100px”将跨度放在窗口外会带来更好的性能:处理 1000 个元素大约需要 11 秒!

所以替换:

var spanTest = $('<span>').css('display','none').attr('id','span-test-tester');

与:

var spanTest = $('<span>').attr('id','span-test-tester').css('position','absolute').css('top','-100px');

总结:

再次感谢您提供此脚本...非常有用!

这是我完整的代码改编,如果它可以帮助某人......:

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title> - jsFiddle demo</title>
  <script type='text/javascript' src='http://code.jquery.com/jquery-1.4.4.min.js'></script>
  <link rel="stylesheet" type="text/css" href="/css/normalize.css">
  <link rel="stylesheet" type="text/css" href="/css/result-light.css">  
  <style type='text/css'>

    .preview {    
    }

    .backg{
      background:red;
      margin: 20px 0;
      border:1px solid blue;
      width:200px;
      padding:10px;
      font-size:14px;  // change it to test with other fonts
      font-weight:bold;
    }

  </style>
  <script type='text/javascript'>
  //<![CDATA[ 
  $(window).load(function(){
   truncate();
  });


  function truncate(){

    // Create a span we can use just to test the widths of strings
    var spanTest = $('<span>').attr('id','span-test-tester').css('position','absolute').css('top','-100px');
    $('body').append(spanTest);

    // function to get the length of a string
    function getLength(txt){
        return spanTest.text(txt).width();
    }

    var nb =0;
    // now make all the previews fit
    $('.preview').each(function(){
        nb++;

        // Get the current font and apply it to hidden span tester
        var fontSize=$(this).css("font-size");
        spanTest.css("font-size", fontSize);
        var fontStyle=$(this).css("font-style");
        spanTest.css("font-style", fontStyle);
        var fontWeight=$(this).css("font-weight");
        spanTest.css("font-weight", fontWeight);
        var fontFamily=$(this).css("font-family");
        spanTest.css("font-family", fontFamily);

        // build a bench-mark to gauge it from
        var roomWidth = $(this).innerWidth();

        // now, get the width and play with it until it fits (if it doesn't)
        var txt = $(this).text();
        var contentsWidth = getLength(txt);
        if (contentsWidth > roomWidth){ // bigger than we have to work with
            roomWidth -= getLength('...'); // work within confines of room + the ellipsis
            while (contentsWidth > roomWidth){ 
                txt = txt.substring(0,txt.length-1);
                contentsWidth = getLength(txt);
            }

            // set the text to this
            $(this).text(txt).append($('<span>').text('...'));
        }
    });

    }

  //]]> 

  </script>
</head>
<body>
      <div class="backg"><div class="preview">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ</div></div>
      (... repeat 1000 times ...)
      <div class="backg"><div class="preview">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ</div></div>

</body>
</html>

再见!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-21
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 2013-01-16
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多