HTML-仅在激活省略号时如何显示工具提示


205

我的页面上有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


1
请记住,text-overflow:ellipsis;没有在所有的工作在Firefox -看到这个问题更多:stackoverflow.com/questions/4927257/...
Spudley

2
我只需要做类似的事情。到目前为止element.offsetWidth < element.scrollWidth,根据此答案检查是否可行。
马丁·史密斯


7
后代注意事项:text-overflow:ellipsis;现在可以在Firefox中使用;它是在Firefox 7(2011年9月发布)中添加的。
sleske '16

Answers:


161

这是一种使用内置省略号设置的方法,并title在马丁·史密斯的评论中添加了按需(使用jQuery)属性:

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

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

4
谢谢,作品就像一个魅力!但是,如果您想提高效率,可以考虑用on()替换bind(),如下所示:$(document).on('mouseenter','.mightOverflow',function(){...});
Ziad

17
如果希望文本不再溢出时自动删除工具提示,请修改为:$(document).on('mouseenter','.mightOverflow',function(){var $ t = $(this); var title = $ t.attr('title'); if(!title){if(this.offsetWidth <this.scrollWidth)$ t.attr('title',$ t.text())} else {if(this.offsetWidth> = this.scrollWidth && title == $ t.text())$ t.removeAttr('title')}});
克里斯·詹森

1
mouseenter是我们绑定或监听的事件。实际上,直到有人将鼠标悬停在元素上时,我们才需要在元素上添加工具提示。因此,我们将添加项推迟到具有“ mightoverflow”类的任何DOM元素上的mouseenter为止。即时工具提示
Jason Kleban

2
"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
Adrien是

2
它在IE10上不起作用-offsetWidth与scrollWidth相同,都给了我截短的宽度。
SsjCosty

59

这是一个纯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;
}

18
它不如工具提示好,因为它可能会破坏布局。
亚历山大

2
工具提示的问题在于,至少在目前,它们无法在移动设备上运行。这个答案可能(读:可能会)破坏布局,但可以进行调整,例如,使所悬停的元素具有不同的背景颜色。这仍然无法在移动设备上使用,但这是台式机的另一种选择。
trysis

1
非常感谢您的答复,该答复完全满足了我的需求。通过使用一些JavaScript,我们可以想象将块定位在绝对位置,从而不会破坏布局。
Niavlys

2
这是一个很好的答案,比在CSS问题上膨胀JavaScript更好。显然,省略号应该有一个自动标题选项,目前这种实现方式缺乏意义。太糟糕了,CSS犯规允许只:悬停如果最后的字符是“...”
约翰

32

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,在页面加载时执行起来似乎更简单,但也提供了更多的可能性。即。您可能需要设置带有工具提示的元素的样式,该元素带有带下划线的虚线,以“提示”工具提示。例如$(".mightOverflow").each(function() { if( $(this).offsetWidth < $(this).scrollWidth && !$(this).attr('title')){ $(this).attr('title', $(this).text()); $(this).css('border-bottom', '1px dotted #A8A8A8'); } });
Adrien Be

“每次将鼠标悬停在上面”是错误的(至少现在是-我不知道答案是否已更新)它会检查它以前是否计算过'&&!$ this.attr('title')'
符文·杰普森

不,这只是阻止它再次添加title属性。确定是否需要的计算仍在进行。this.offsetWidth < this.scrollWidth甚至!$this.attr('title')每次将鼠标悬停在元素上时,都将执行检查。
Elezar

9
这种方法的问题在于,所有元素都会被一次检查(可能会影响性能),并且只计算一次,因此,如果用户缩小浏览器,导致事物被截断或扩展,从而导致它们不再被截断,则无法更新工具提示的存在。再次将代码附加到窗口调整大小会出现性能问题,因为每个项目都会检查其大小。通过使用事件委托“ $(document).on('mouseenter','.mightOverflow',...”)并延迟检查直到将鼠标悬停在元素上,您可以即时更新,并且一次只检查1个元素
克里斯·詹森(Chris Janssen)2015年

它在IE10上不起作用-offsetWidth与scrollWidth相同,都给了我截短的宽度。
SsjCosty

18

这是另外两个纯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. 显示一个任意的“工具提示”

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


这正是我想要的!
Praneet Nadkar

出色的解决方案,正是我所需要的。谢谢 !
Agu V

17

这是我的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


1
它在IE10上不起作用-offsetWidth与scrollWidth相同,都给了我截短的宽度。
SsjCosty

@SsjCosty为什么要在IE 10上进行测试?不应该有一个在这一点上使用IE 10,因为任何人谁可以安装IE 10可以安装IE 11
托尼·白利糖度

嗯,我们有一项公司政策,支持的最低IE版本为10。也是因为我们的许多客户(某些银行和各种机构)仍在使用IE10。那好吧。
SsjCosty

12

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

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

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

  1. 首先比较“ this.offsetWidth < this.scrollWidth”,如果失败,请继续执行步骤2。
  2. 暂时将CSS样式切换为{'overflow':'visible','white-space':'normal','word-break':'break-all'}。
  3. 让浏览器进行中继。如果自动换行,元素将扩展其高度,这也意味着需要省略号。
  4. 恢复CSS样式。

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


10

我创建了一个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");
      }
    }
  });
};

简单而辉煌。谢谢!
GumZ

3

这就是我所做的。大多数工具提示脚本都要求您执行存储工具提示的功能。这是一个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());
});

为什么要下票?如果这样做,请发表评论,以便人们知道问题出在哪里。谢谢。
fanfavorite 2016年

2

如果您只想使用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将跨度插入DOM,则可以在插入内容之前将其保留在变量中。这样,您就不需要跨度上的content属性。

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


真好 由于我在本页面的其他部分中使用了JQuery-JQuery优雅的解决方案是什么?
蜘蛛侠

$("#myDataId").attr("title", function() { var innerText = $(this).text(); var content = $(this).attr("content"); if (innerText.length <= content.length) { return content; } return null; });
马克·科斯特洛

1
我用纯JavaScript尝试了您的第一个建议-它不起作用。即使文本不能在屏幕上完全显示,“ innerText”属性也可以保存文本的完整长度,因此请始终执行以下操作:elemInnerText.length == elemContent.length!
蜘蛛侠

您的跨度样式为width71。为什么不检查字符串的宽度是否大于该宽度?如果您想做一些真正时髦的事情,可以添加一个没有设置text-overflow:省略号的隐藏元素,然后比较两者的宽度。如果隐藏的内容比未隐藏的内容宽,请向可见的内容添加标题属性。
Mark Costello

2

我有CSS类,该类确定在何处放置省略号。基于此,我执行以下操作(元素集可能会有所不同,我在使用省略号的情况下编写了元素集,当然,它可能是一个单独的类选择器):

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

1
我的案子this是我的,anchor所以我用它this.text()代替了val()
Basheer AL-MOMANI

2

这是Vanilla JavaScript解决方案:

(function init() {

  var cells = document.getElementsByClassName("cell");

  for(let index = 0; index < cells.length; ++index) {
    let cell = cells.item(index);
    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

这是我的解决方案,很迷人!

    $(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进行一些算术计算。我该怎么办?
Kunal Tyagi

@KunalTyagi,您好,您可以使用2个单独的函数,我只写了一个带有输入和跨度的函数,但是您可以将此函数复制2次,例如,第一个函数仅带输入,第二个函数仅跨度。像这样:$(document).on('mouseover','input',function(){...}); 第二个$(document).on('mouseover','span',function(){...});
FarukT

0

上面的解决方案都不适合我,但是我找到了一个很好的解决方案。人们犯的最大错误是在页面加载时在元素上声明了所有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'
            });
        }
    });

0

您可以用另一个跨度包围跨度,然后简单地测试原始/内部跨度的宽度是否大于新/外部跨度的宽度。请注意,我可能会说-这大致取决于我在a的span内部的情况,td因此我实际上并不知道它是否可以在a的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());
            }
        }
    });
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.