219

ページにブロック要素のコレクションがあります。それらはすべてCSSルールの空白、オーバーフロー、テキストオーバーフローが設定されているため、オーバーフローしたテキストはトリミングされ、省略記号が使用されます。

ただし、すべての要素がオーバーフローするわけではありません。

とにかく、JavaScriptを使用してどの要素がオーバーフローしているのかを検出できますか?

ありがとう。

追加:私が使用しているHTML構造の例。

<td><span>Normal text</span></td>
<td><span>Long text that will be trimmed text</span></td>

SPAN要素は常にセルに収まり、省略記号の規則が適用されます。省略記号がSPANのテキストコンテンツにいつ適用されるかを検出したいと思います。

4

15 に答える 15

359

引数としてspan要素を渡して、このJS関数を試してください。

function isEllipsisActive(e) {
     return (e.offsetWidth < e.scrollWidth);
}
于 2012-04-04T18:42:30.827 に答える
130

昔々、私はこれを行う必要がありました、そして私が出くわした唯一のクロスブラウザの信頼できる解決策はハックの仕事でした。私はこのようなソリューションの最大のファンではありませんが、それは確かに何度も正しい結果を生み出します。

要素を複製し、境界幅を削除して、複製された要素が元の要素よりも広いかどうかをテストするという考え方です。もしそうなら、あなたはそれが切り捨てられるだろうということを知っています。

たとえば、jQueryを使用します。

var $element = $('#element-to-test');
var $c = $element
           .clone()
           .css({display: 'inline', width: 'auto', visibility: 'hidden'})
           .appendTo('body');

if( $c.width() > $element.width() ) {
    // text was truncated. 
    // do what you need to do
}

$c.remove();

これを実証するためにjsFiddleを作成しました。http ://jsfiddle.net/cgzW8/2/

jQuery用に独自のカスタム疑似セレクターを作成することもできます。

$.expr[':'].truncated = function(obj) {
  var $this = $(obj);
  var $c = $this
             .clone()
             .css({display: 'inline', width: 'auto', visibility: 'hidden'})
             .appendTo('body');

  var c_width = $c.width();
  $c.remove();

  if ( c_width > $this.width() )
    return true;
  else
    return false;
};

次に、それを使用して要素を検索します

$truncated_elements = $('.my-selector:truncated');

デモ: http: //jsfiddle.net/cgzW8/293/

うまくいけば、これはそのままハッキーです。

于 2011-10-12T11:08:34.437 に答える
16

italoの答えに加えて、jQueryを使用してこれを行うこともできます。

function isEllipsisActive($jQueryObject) {
    return ($jQueryObject.width() < $jQueryObject[0].scrollWidth);
}

また、Smokyが指摘したように、width()の代わりにjQueryのouterWidth()を使用することもできます。

function isEllipsisActive($jQueryObject) {
    return ($jQueryObject.outerWidth() < $jQueryObject[0].scrollWidth);
}
于 2013-10-10T19:06:10.337 に答える
14

Christian Vargaから受け入れられた回答を使用している(または使用を計画している)場合は、パフォーマンスの問題に注意してください。

このような方法でDOMを複製/操作すると、非常にリソースを大量に消費するDOMリフロー( DOMリフローの説明を参照)が発生します。

ページ上の100以上の要素にChristianVargaのソリューションを使用すると、JSスレッドがロックされる間に4秒のリフロー遅延が発生しました。JSがシングルスレッドであることを考えると、これはエンドユーザーにとって大きなUX遅延を意味します。

Italo Borssattoの答えは受け入れられるはずです、それは私のプロファイリング中に約10倍速かったです。

于 2017-06-08T08:09:21.670 に答える
7

italoからの回答はとても良いです!ただし、少し洗練させてください。

function isEllipsisActive(e) {
   var tolerance = 2; // In px. Depends on the font you are using
   return e.offsetWidth + tolerance < e.scrollWidth;
}

クロスブラウザの互換性

実際、上記のコードを試してとconsole.logの値を出力するために使用するe.offsetWidthe.scrollWidth、IEで、テキストの切り捨てがない場合でも、1pxまたはの値の違いが2px発生することに気付くでしょう。

したがって、使用するフォントサイズに応じて、一定の許容範囲を設定してください。

于 2016-02-02T15:53:47.797 に答える
6

elem.offsetWdith VS ele.scrollWidthこれは私にとってはうまくいきます! https://jsfiddle.net/gustavojuan/210to9p1/

$(function() {
  $('.endtext').each(function(index, elem) {
    debugger;
    if(elem.offsetWidth !== elem.scrollWidth){
      $(this).css({color: '#FF0000'})
    }
  });
});
于 2016-02-08T16:59:20.467 に答える
4

このサンプルは、テキストが切り捨てられたセルテーブルのツールチップを示しています。テーブル幅に基づいて動的です:

$.expr[':'].truncated = function (obj) {
    var element = $(obj);

    return (element[0].scrollHeight > (element.innerHeight() + 1)) || (element[0].scrollWidth > (element.innerWidth() + 1));
};

$(document).ready(function () {
    $("td").mouseenter(function () {
        var cella = $(this);
        var isTruncated = cella.filter(":truncated").length > 0;
        if (isTruncated) 
            cella.attr("title", cella.text());
        else 
            cella.attr("title", null);
    });
});

デモ:https ://jsfiddle.net/t4qs3tqs/

すべてのバージョンのjQueryで動作します

于 2015-08-07T07:41:17.393 に答える
3

すべてのソリューションが実際には機能しませんでした。機能したのは、要素をその親(またはトリガーを持つ要素によっては子)の要素と比較することでした。scrollWidthscrollWidth

子供のscrollWidthが親よりも高い場合、それ.text-ellipsisはアクティブであることを意味します。


el親要素はいつですか

function isEllipsisActive(el) {
    let width       = el.offsetWidth;
    let widthChild  = el.firstChild.offsetWidth;
    return (widthChild >= width);
}

el子要素はいつですか

function isEllipsisActive(event) {
    let width       = el.offsetWidth;
    let widthParent = el.parentElement.scrollWidth;
    return (width >= widthParent);
}
于 2017-10-20T13:43:28.277 に答える
1

それを検出するためのより良い方法は使用だと思います。getClientRects()各長方形は同じ高さであるように見えるので、異なるtop値の数で行数を計算できます。

getClientRectsこのように動作します

function getRowRects(element) {
    var rects = [],
        clientRects = element.getClientRects(),
        len = clientRects.length,
        clientRect, top, rectsLen, rect, i;

    for(i=0; i<len; i++) {
        has = false;
        rectsLen = rects.length;
        clientRect = clientRects[i];
        top = clientRect.top;
        while(rectsLen--) {
            rect = rects[rectsLen];
            if (rect.top == top) {
                has = true;
                break;
            }
        }
        if(has) {
            rect.right = rect.right > clientRect.right ? rect.right : clientRect.right;
            rect.width = rect.right - rect.left;
        }
        else {
            rects.push({
                top: clientRect.top,
                right: clientRect.right,
                bottom: clientRect.bottom,
                left: clientRect.left,
                width: clientRect.width,
                height: clientRect.height
            });
        }
    }
    return rects;
}

getRowRectsこのように動作します

あなたはこのように検出することができます

于 2016-03-07T09:35:58.023 に答える
1

私の実装)

const items = Array.from(document.querySelectorAll('.item'));
items.forEach(item =>{
    item.style.color = checkEllipsis(item) ? 'red': 'black'
})

function checkEllipsis(el){
  const styles = getComputedStyle(el);
  const widthEl = parseFloat(styles.width);
  const ctx = document.createElement('canvas').getContext('2d');
  ctx.font = `${styles.fontSize} ${styles.fontFamily}`;
  const text = ctx.measureText(el.innerText);
  return text.width > widthEl;
}
.item{
  width: 60px;
  overflow: hidden;
  text-overflow: ellipsis;
}
      <div class="item">Short</div>
      <div class="item">Loooooooooooong</div>

于 2020-02-05T10:00:52.853 に答える
1

どのソリューションもうまくいかなかったので、まったく異なるアプローチを選択しました。省略記号でCSSソリューションを使用する代わりに、特定の文字列の長さからテキストを切り取ります。

  if (!this.isFullTextShown && this.text.length > 350) {
    return this.text.substring(0, 350) + '...'
  }
  return this.text

長さを超えた場合は「more/less」ボタンを表示します。

  <span
    v-if="text.length > 350"
    @click="isFullTextShown = !isFullTextShown"
  >
    {{ isFullTextShown ? 'show less' : 'show more' }}
  </span>
于 2021-07-30T16:51:28.370 に答える
0

e.offsetWidth < e.scrollWidthソリューションが常に機能しているとは限りません。

また、純粋なJavaScriptを使用する場合は、次の方法を使用することをお勧めします。

(タイプスクリプト)

public isEllipsisActive(element: HTMLElement): boolean {
    element.style.overflow = 'initial';
    const noEllipsisWidth = element.offsetWidth;
    element.style.overflow = 'hidden';
    const ellipsisWidth = element.offsetWidth;

    if (ellipsisWidth < noEllipsisWidth) {
      return true;
    } else {
      return false;
    }
}
于 2019-08-01T12:15:53.103 に答える
0

ソリューション@ItaloBorssattoは完璧です。しかし、SOを見る前に-私は自分の決断をしました。ここにあります :)

const elems = document.querySelectorAll('span');
elems.forEach(elem => {
  checkEllipsis(elem);
});

function checkEllipsis(elem){
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  const styles = getComputedStyle(elem);
  ctx.font = `${styles.fontWeight} ${styles.fontSize} ${styles.fontFamily}`;
  const widthTxt = ctx.measureText(elem.innerText).width;
  if (widthTxt > parseFloat(styles.width)){
    elem.style.color = 'red'
  }
}
span.cat {
    display: block;
    border: 1px solid black;
    white-space: nowrap;
    width: 100px;
    overflow: hidden;
    text-overflow: ellipsis;
}
 <span class="cat">Small Cat</span>
      <span class="cat">Looooooooooooooong Cat</span>

于 2020-01-17T17:32:27.390 に答える
0

https://stackoverflow.com/users/241142/iconoclastで言及されているデモhttp://jsfiddle.net/brandonzylstra/hjk9mvcy/にはいくつかのミスタスクがあります。

彼のデモでは、次のコードを追加すると機能します。

setTimeout(() => {      
  console.log(EntryElm[0].offsetWidth)
}, 0)
于 2020-04-09T05:42:27.870 に答える
0

あなたが反応をしているなら、これが私がそれをした方法です。

<div 
  ref={ref => {
    if (!ref) return
    const isOverflowing = ref.scrollWidth > ref.clientWidth
    if (isOverflowing) {
      // handle what to do next here
    }
  }}
/>
于 2021-11-15T02:19:03.000 に答える