【问题标题】:HTML - how can I show tooltip ONLY when ellipsis is activatedHTML - 如何仅在激活省略号时显示工具提示
【发布时间】:2011-07-25 09:30:50
【问题描述】:

我的页面中有一个包含动态数据的跨度,采用ellipsis 样式。

.my-class
{
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;  
  width: 71px;
}
<span id="myId" class="my-class"></span>
document.getElementById('myId').innerText = "...";

我想在此元素工具提示中添加相同的内容,但我希望它仅在内容较长且省略号出现在屏幕上时出现。

有什么办法吗?
激活ellipsis时浏览器会抛出事件吗?

*浏览器:Internet Explorer

【问题讨论】:

  • 请记住,text-overflow:ellipsis; 在 Firefox 中根本不起作用——请参阅此问题了解更多信息:stackoverflow.com/questions/4927257/…
  • 我只需要做类似的事情。到目前为止,根据this answer 检查element.offsetWidth &lt; element.scrollWidth 是否有效。
  • 后人注意:text-overflow:ellipsis; 现在可以在 Firefox 中使用;它是在 Firefox 7(2011 年 9 月发布)中添加的。

标签: javascript html css tooltip ellipsis


【解决方案1】:

这是一种使用内置省略号设置的方法,并根据 Martin Smith 的评论按需添加 title 属性(使用 jQuery):

$('.mightOverflow').bind('mouseenter', function(){
    var $this = $(this);

    if(this.offsetWidth < this.scrollWidth && !$this.attr('title')){
        $this.attr('title', $this.text());
    }
});

【讨论】:

  • 谢谢,就像一个魅力!但是,如果您想提高效率,可以考虑将 bind() 替换为 on() ,如下所示: $(document).on('mouseenter', '.mightOverflow', function() { ... });
  • 如果您希望在文本不再溢出时自动删除工具提示,请修改为: $(document).on('mouseenter', '.mightOverflow', function() { var $t = $ (this); var title = $t.attr('title'); if (!title){ if (this.offsetWidth = this.scrollWidth && title == $t.text()) $t.removeAttr('title') } });
  • mouseenter 是我们绑定或监听的事件。在有人真正将鼠标悬停在元素上之前,我们实际上不必将工具提示添加到元素上。因此,我们将添加推迟到具有“mightoverflow”类的任何一个 DOM 元素上的 mouseenter 点。即时工具提示
  • "As of jQuery 1.7, the .on() method is the preferred method for attaching event handlers to a document" 了解更多信息,请参阅 api.jquery.com/bindapi.jquery.com/on
  • 它在 IE10 上不起作用 - offsetWidth 与 scrollWidth 相同,都给了我截断的宽度。
【解决方案2】:

这是一个纯 CSS 解决方案。不需要 jQuery。 它不会显示工具提示,而是只会在鼠标悬停时将内容扩展至完整长度。

如果您有被替换的内容,效果会很好。这样你就不必每次都运行一个 jQuery 函数了。

.might-overflow {
    text-overflow: ellipsis;
    overflow : hidden;
    white-space: nowrap;
}

.might-overflow:hover {
    text-overflow: clip;
    white-space: normal;
    word-break: break-all;
}

【讨论】:

  • 它不如tooltip,因为它可能会破坏布局。
  • 工具提示的问题是它们不能在移动设备上工作,至少目前是这样。这个答案可能(阅读:可能会)破坏布局,但它可以适应,例如,悬停元素具有不同的背景颜色。这仍然不适用于移动设备,但它是桌面设备的另一种选择。
  • 感谢这个完美满足我需求的绝佳答案。使用一些 JavaScript,我们可以想象使块绝对定位,这样它就不会破坏布局。
  • 这是一个很好的答案,比在 css 问题上臃肿的 javascript 更好。显然,省略号应该有一个自动标题选项,目前它的实现方式缺乏意义。太糟糕的 CSS 不允许仅 :hover 如果最后一个字符是 '...'
  • 当页面上有水平滚动条时,工具提示内容显示在页面的不同位置而不是悬停元素附近。有什么建议吗?
【解决方案3】:

这里有另外两个纯 CSS 解决方案:

  1. 在适当位置显示截断的文本:

.overflow {
  overflow: hidden;
  -ms-text-overflow: ellipsis;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.overflow:hover {
  overflow: visible;
}

.overflow:hover span {
  position: relative;
  background-color: white;

  box-shadow: 0 0 4px 0 black;
  border-radius: 1px;
}
<div>
  <span class="overflow" style="float: left; width: 50px">
    <span>Long text that might overflow.</span>
  </span>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad recusandae perspiciatis accusantium quas aut explicabo ab. Doloremque quam eos, alias dolore, iusto pariatur earum, ullam, quidem dolores deleniti perspiciatis omnis.
</div>
  1. Show an arbitrary "tooltip":

.wrap {
  position: relative;
}

.overflow {
  white-space: nowrap; 
  overflow: hidden;
  text-overflow: ellipsis;
  
  pointer-events:none;
}

.overflow:after {
  content:"";
  display: block;
  position: absolute;
  top: 0;
  right: 0;
  width: 20px;
  height: 15px;
  z-index: 1;
  border: 1px solid red; /* for visualization only */
  pointer-events:initial;

}

.overflow:hover:after{
  cursor: pointer;
}

.tooltip {
  /* visibility: hidden; */
  display: none;
  position: absolute;
  top: 10;
  left: 0;
  background-color: #fff;
  padding: 10px;
  -webkit-box-shadow: 0 0 50px 0 rgba(0,0,0,0.3);
  opacity: 0;
  transition: opacity 0.5s ease;
}


.overflow:hover + .tooltip {
  /*visibility: visible; */
  display: initial;
  transition: opacity 0.5s ease;
  opacity: 1;
}
<div>
  <span class="wrap">
    <span class="overflow" style="float: left; width: 50px">Long text that might overflow</span>
    <span class='tooltip'>Long text that might overflow.</span>
  </span>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad recusandae perspiciatis accusantium quas aut explicabo ab. Doloremque quam eos, alias dolore, iusto pariatur earum, ullam, quidem dolores deleniti perspiciatis omnis.
</div>

【讨论】:

  • 这正是我想要的!
  • 优秀的解决方案,正是我所需要的。谢谢!
【解决方案4】:

uosɐſ 的回答基本上是正确的,但您可能不想在 mouseenter 事件中这样做。每次将鼠标悬停在元素上时,这将导致它进行计算以确定是否需要它。除非元素的大小发生变化,否则没有理由这样做。

最好在元素添加到 DOM 后立即调用此代码:

var $ele = $('#mightOverflow');
var ele = $ele.eq(0);
if (ele.offsetWidth < ele.scrollWidth)
    $ele.attr('title', $ele.text());

或者,如果您不知道添加的确切时间,请在页面加载完成后调用该代码。

如果您需要使用多个元素来执行此操作,那么您可以为它们提供所有相同的类(例如“mightOverflow”),并使用此代码来更新它们:

$('.mightOverflow').each(function() {
    var $ele = $(this);
    if (this.offsetWidth < this.scrollWidth)
        $ele.attr('title', $ele.text());
});

【讨论】:

  • +1,在页面加载时执行此操作似乎更简单,但也提供了更多可能性。 IE。您可能希望为这个具有带有虚线下划线的工具提示的元素设置样式,以“发出”工具提示的“信号”。比如$(".mightOverflow").each(function() { if( $(this).offsetWidth &lt; $(this).scrollWidth &amp;&amp; !$(this).attr('title')){ $(this).attr('title', $(this).text()); $(this).css('border-bottom', '1px dotted #A8A8A8'); } });
  • '每次鼠标悬停'是错误的(至少现在 - 我不知道答案是否已更新)它确实检查它是否以前计算过 '&& !$this.attr('标题')'
  • 不,这只是阻止它再次添加标题属性。 计算以确定是否需要它仍然完成。 this.offsetWidth &lt; this.scrollWidth 甚至可能会在您每次将鼠标悬停在元素上时执行对 !$this.attr('title') 的检查。
  • 这种方法的问题是所有元素都被一次性检查(潜在的性能影响)并且它只计算一次,所以如果用户缩小浏览器导致东西被截断或扩展,导致它们不再被截断,您无法更新工具提示的存在。再次将代码附加到窗口调整大小会出现性能问题,因为每个项目都会检查其大小。通过使用事件委托 "$(document).on('mouseenter', '.mightOverflow', ..." 并延迟检查直到您将鼠标悬停在元素上,您可以即时更新并且每次只检查 1 个元素
  • 它在 IE10 上不起作用 - offsetWidth 与 scrollWidth 相同,都给了我截断的宽度。
【解决方案5】:

这是我的 jQuery 插件:

(function($) {
    'use strict';
    $.fn.tooltipOnOverflow = function() {
        $(this).on("mouseenter", function() {
            if (this.offsetWidth < this.scrollWidth) {
                $(this).attr('title', $(this).text());
            } else {
                $(this).removeAttr("title");
            }
        });
    };
})(jQuery);

用法:

$("td, th").tooltipOnOverflow();

编辑:

我已经为这个插件做了一个要点。 https://gist.github.com/UziTech/d45102cdffb1039d4415

【讨论】:

  • 它在 IE10 上不起作用 - offsetWidth 与 scrollWidth 相同,都给了我截断的宽度。
  • @SsjCosty 为什么要在 IE 10 上进行测试?此时应该没有人使用 IE 10,因为任何可以安装 IE 10 的人都可以安装 IE 11。
  • 嗯,我们有一个公司政策,我们支持的最低 IE 版本是 10。另外因为我们的很多客户(一些银行和各种机构)仍然使用 IE10。哦,好吧。
  • @SsjCosty 是的,这是大公司的问题。 IT 部门没有钱摆脱 5 年不兼容的浏览器。不过别担心,管理层会收到很多奖金... :-)) 有点跑题了,我知道。
【解决方案6】:

我们需要检测是否真的应用了省略号,然后显示一个工具提示来显示全文。当元素几乎保持其内容但仅缺少一两个像素的宽度时,仅比较“this.offsetWidth &lt; this.scrollWidth”是不够的,特别是对于全角中日韩字符的文本。

这里是一个例子:http://jsfiddle.net/28r5D/5/

我找到了一种改进省略号检测的方法:

  1. 首先比较“this.offsetWidth &lt; this.scrollWidth”,如果失败则继续第 2 步。
  2. 暂时将 css 样式切换为 {'overflow': 'visible', 'white-space': 'normal', 'word-break': 'break-all'}。
  3. 让浏览器重新布局。如果发生自动换行,元素将扩展其高度,这也意味着需要省略号。
  4. 恢复 CSS 样式。

这是我的改进:http://jsfiddle.net/28r5D/6/

【讨论】:

    【解决方案7】:

    我创建了一个 jQuery 插件,它使用 Bootstrap 的工具提示而不是浏览器的内置工具提示。请注意,这尚未在旧版浏览器上进行测试。

    JSFiddle:https://jsfiddle.net/0bhsoavy/4/

    $.fn.tooltipOnOverflow = function(options) {
        $(this).on("mouseenter", function() {
        if (this.offsetWidth < this.scrollWidth) {
            options = options || { placement: "auto"}
            options.title = $(this).text();
          $(this).tooltip(options);
          $(this).tooltip("show");
        } else {
          if ($(this).data("bs.tooltip")) {
            $tooltip.tooltip("hide");
            $tooltip.removeData("bs.tooltip");
          }
        }
      });
    };
    

    【讨论】:

      【解决方案8】:

      这是一个 Vanilla JavaScript 解决方案:

      var cells = document.getElementsByClassName("cell");
      
      for(const cell of cells) {
        cell.addEventListener('mouseenter', setTitleIfNecessary, false);
      }
      
      function setTitleIfNecessary() {
        if(this.offsetWidth < this.scrollWidth) {
          this.setAttribute('title', this.innerHTML);
        }
      }
      .cell {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        border: 1px;
        border-style: solid;
        width: 120px; 
      }
      <div class="cell">hello world!</div>
      <div class="cell">hello mars! kind regards, world</div>

      【讨论】:

      • 请注意,此解决方案仅适用于立即加载内容的静态网站(否则代码必须重新运行多次),并且仅在窗口/容器大小不减小时才有效。如果加载页面时文本没有截断,但容器的大小已调整,因此必须截断 - 这不会重新添加工具提示。仍然 - 一个优雅而简单的解决方案! +1
      【解决方案9】:

      这是我的解决方案,非常有魅力!

          $(document).on('mouseover', 'input, span', function() {
            var needEllipsis = $(this).css('text-overflow') && (this.offsetWidth < this.scrollWidth);
            var hasNotTitleAttr = typeof $(this).attr('title') === 'undefined';
            if (needEllipsis === true) {
                if(hasNotTitleAttr === true){
                  $(this).attr('title', $(this).val());
                }
            }
            if(needEllipsis === false && hasNotTitleAttr == false){
              $(this).removeAttr('title');
            }
        });
      

      【讨论】:

      • 嗨@FarukT,您的解决方案对我来说效果很好,非常感谢。我想问一下假设输入和跨度是否有两个 html 标签,我想同时计算这两个标签的 offsetWidth 以使用这些 offsetWidth 进行一些算术计算。我该怎么做?
      • 嗨@KunalTyagi,你可以用2个单独的函数来实现它,我只写了一个带有输入和跨度的函数,但你可以复制这个函数2次,例如第一个函数只有输入,第二个函数只有跨度。像这样: $(document).on('mouseover', 'input', function() {...});第二个 $(document).on('mouseover', 'span', function() {...});
      【解决方案10】:

      如果您只想使用 javascript 执行此操作,我会执行以下操作。给 span 一个 id 属性(以便可以很容易地从 DOM 中检索它)并将所有内容放在一个名为 'content' 的属性中:

      <span id='myDataId' style='text-overflow: ellipsis; overflow : hidden;
       white-space: nowrap; width: 71;' content='{$myData}'>${myData}</span>
      

      然后,在您的 javascript 中,您可以在将元素插入 DOM 后执行以下操作。

      var elemInnerText, elemContent;
      elemInnerText = document.getElementById("myDataId").innerText;
      elemContent = document.getElementById("myDataId").getAttribute('content')
      if(elemInnerText.length <= elemContent.length)
      {
         document.getElementById("myDataId").setAttribute('title', elemContent); 
      }
      

      当然,如果您使用 javascript 将 span 插入 DOM,您可以在插入之前将内容保存在变量中。这样您就不需要跨度上的内容属性。

      如果你想使用 jQuery,还有比这更优雅的解决方案。

      【讨论】:

      • 不错。由于我在此页面的其他部分使用 JQuery - JQuery 优雅的解决方案是什么??
      • $("#myDataId").attr("title", function() { var innerText = $(this).text(); var content = $(this).attr("content"); if (innerText.length &lt;= content.length) { return content; } return null; });
      • 我用纯 javascript 尝试了你的第一个建议 - 它不起作用。 'innerText' 属性保存文本的完整长度,即使它没有完全显示在屏幕上,所以总是这样:elemInnerText.length == elemContent.length !!
      • 你的span的样式是宽度71。为什么不检查字符串的宽度是否比那个长呢?如果你想做一些非常时髦的事情,你可以添加一个没有设置 text-overflow:ellipsis 的隐藏元素并比较两者的宽度。如果隐藏的比非隐藏的宽,给可见的加一个title属性。
      【解决方案11】:

      这就是我所做的。大多数工具提示脚本要求您执行存储工具提示的函数。这是一个 jQuery 示例:

      $.when($('*').filter(function() {
         return $(this).css('text-overflow') == 'ellipsis';
      }).each(function() {
         if (this.offsetWidth < this.scrollWidth && !$(this).attr('title')) {
            $(this).attr('title', $(this).text());
         }
      })).done(function(){ 
         setupTooltip();
      });
      

      如果您不想检查省略号 css,您可以简化如下:

      $.when($('*').filter(function() {
         return (this.offsetWidth < this.scrollWidth && !$(this).attr('title'));
      }).each(function() {
         $(this).attr('title', $(this).text());
      })).done(function(){ 
         setupTooltip();
      });
      

      我有“何时”围绕它,所以“setupTooltip”函数在所有标题都更新之前不会执行。将“setupTooltip”替换为您的工具提示功能,将 * 替换为您要检查的元素。 * 如果你离开它,它们将全部通过。

      如果您只是想使用浏览器工具提示更新标题属性,您可以简化如下:

      $('*').filter(function() {
         return $(this).css('text-overflow') == 'ellipsis';
      }).each(function() {
         if (this.offsetWidth < this.scrollWidth && !$(this).attr('title')) {
            $(this).attr('title', $(this).text());
         }
      });
      

      或者不检查省略号:

      $.when($('*').filter(function() {
         return (this.offsetWidth < this.scrollWidth && !$(this).attr('title'));
      }).each(function() {
         $(this).attr('title', $(this).text());
      });
      

      【讨论】:

      • 为什么投反对票?如果您这样做,请发表评论,以便人们知道问题所在。谢谢。
      【解决方案12】:

      这就是我最终基于https://stackoverflow.com/a/13259660/1714951 所做的事情,并在元素不再溢出时添加了 title 属性的删除。这是纯 JS (ES6),使用事件委托来提高性能(当使用具有相同类的多个元素时)和使用保护子句来提高可读性:

      // You may want to change document by an element closer to your target
      // so that the handler is not executed as much
      document.addEventListener( 'mouseenter', event => {
          let eventTarget = event.target;
          // This could be easily applied to text-truncate instead of my-class if you use bootstrap
          if ( !eventTarget.classList?.contains( 'my-class' ) ) {
              return;
          }
          if ( eventTarget.offsetWidth < eventTarget.scrollWidth ) {
              eventTarget.setAttribute( 'title', eventTarget.innerText );
              return;
          }
          eventTarget.removeAttribute( 'title' );
      }, true );
      

      【讨论】:

        【解决方案13】:

        我有 CSS 类,它决定在哪里放置省略号。在此基础上,我做了以下(元素集可能不同,我写那些,使用省略号的地方,当然它可以是一个单独的类选择器):

        $(document).on('mouseover', 'input, td, th', function() {
            if ($(this).css('text-overflow') && typeof $(this).attr('title') === 'undefined') {
                $(this).attr('title', $(this).val());
            }
        });
        

        【讨论】:

        • 我的情况 thisanchor 所以我使用 this.text() 而不是 val()
        【解决方案14】:

        以上解决方案都不适合我,但我想出了一个很好的解决方案。人们犯的最大错误是在页面加载时在元素上声明了所有 3 个 CSS 属性。您必须动态添加这些样式+工具提示,如果且仅当您想要椭圆的跨度大于其父级时。

            $('table').each(function(){
                var content = $(this).find('span').text();
                var span = $(this).find('span');
                var td = $(this).find('td');
                var styles = {
                    'text-overflow':'ellipsis',
                    'white-space':'nowrap',
                    'overflow':'hidden',
                    'display':'block',
                    'width': 'auto'
                };
                if (span.width() > td.width()){
                    span.css(styles)
                        .tooltip({
                        trigger: 'hover',
                        html: true,
                        title: content,
                        placement: 'bottom'
                    });
                }
            });
        

        【讨论】:

          【解决方案15】:

          您可以用另一个跨度包围跨度,然后简单地测试原始/内部跨度的宽度是否大于新/外部跨度的宽度。请注意,我说可能 - 它大致基于我在td 内部有一个span 的情况,所以我实际上并不知道它是否可以在span 内部使用span .

          这里是我的代码,供其他可能发现自己处于与我相似的位置的人使用;即使它在 Angular 上下文中,我也在不加修改地复制/粘贴它,我认为这不会减损可读性和基本概念。我将它编码为一种服务方法,因为我需要在多个地方应用它。我一直传入的选择器是一个可以匹配多个实例的类选择器。

          CaseService.applyTooltip = function(selector) {
              angular.element(selector).on('mouseenter', function(){
                  var td = $(this)
                  var span = td.find('span');
          
                  if (!span.attr('tooltip-computed')) {
                      //compute just once
                      span.attr('tooltip-computed','1');
          
                      if (span.width() > td.width()){
                          span.attr('data-toggle','tooltip');
                          span.attr('data-placement','right');
                          span.attr('title', span.html());
                      }
                  }
              });
          }
          

          【讨论】:

            猜你喜欢
            • 2013-10-08
            • 2019-02-28
            • 1970-01-01
            • 2019-10-28
            • 2019-01-06
            • 1970-01-01
            • 1970-01-01
            • 2023-02-02
            相关资源
            最近更新 更多