HTML 텍스트 오버플로 줄임표 감지


176

페이지에 블록 요소 모음이 있습니다. 모두 CSS 규칙 공백, 오버플로, 텍스트 오버플로가 설정되어 오버플로 텍스트가 잘리고 줄임표가 사용됩니다.

그러나 모든 요소가 오버플로되지는 않습니다.

어쨌든 자바 스크립트를 사용하여 어떤 요소가 오버플로하는지 감지 할 수 있습니까?

감사.

추가 된 예제 HTML 구조.

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

SPAN 요소는 항상 셀에 맞으며 줄임표 규칙이 적용됩니다. 줄임표가 SPAN의 텍스트 내용에 적용되는시기를 감지하고 싶습니다.



10
중복되지 않습니다! 그 질문은 다른 부모 요소의 한 요소에 관한 것입니다. 단일 요소 내에서 텍스트에 대해 이야기하고 있습니다. 필자의 경우 TD의 SPAN은 TD를 오버플로하지 않으며 SPAN 내의 텍스트가 오버플로되어 잘립니다. 그것이 내가 감지하려고하는 것입니다! 죄송합니다.이 질문을 더 잘 인정할 수있었습니다.
deanoj

아, 추가하는 것을 잊어 버렸습니다. 도움이되는 경우에만 웹킷에서 작동하면됩니다.
deanoj

나는 그것이 효과가 있었는지 확인하기 위해 Ghommey를했다 ... 그렇지 않았다.
deanoj

줄임표 측면은 관련이 없습니다. 오버플로 여부 만 감지하면됩니다.
Spudley

답변:


114

옛날 옛적에 나는 이것을해야했고, 내가 찾은 유일한 크로스 브라우저 신뢰할 수있는 솔루션은 해킹 작업이었습니다. 나는 이와 같은 솔루션의 가장 큰 팬은 아니지만 확실히 정확한 결과를 반복해서 산출합니다.

아이디어는 요소를 복제하고 경계 너비를 제거하고 복제 된 요소가 원본보다 넓은 지 테스트하는 것입니다. 그렇다면 잘릴 것입니다.

예를 들어, 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/

잘만되면 이것이 도움이 될 것입니다.


1
@Lauri 아니오; CSS 잘림은 상자 의 실제 텍스트를 변경하지 않으므로 내용이 잘 리거나 표시되거나 숨겨 지더라도 내용은 항상 동일합니다. 잘린 텍스트를 프로그래밍 방식으로 얻을 수있는 방법은 여전히 ​​없습니다. 처음에는 요소를 복제 할 필요가 없습니다!
Christian

1
이없는 상황에서는 이것이 작동하지 않는 것 같습니다 white-space: nowrap.
Jakub Hampl

2
인터넷에서 LOT을 검색하고 많은 솔루션을 구현하려고 시도한 후에 이것이 내가 찾은 가장 신뢰할 수있는 솔루션이라고 말해야합니다. 이 솔루션은 element.innerWidth 또는 element.OffsetWidth와 같은 브라우저간에 다른 결과를 제공하지 않습니다. 여백이나 패딩을 사용할 때 문제가 발생합니다. 훌륭한 솔루션입니다.
Scription

1
나를 위해, 이것은 어디서나 작동하지 않았습니다. 잘 모르겠습니다. CSS에 어떻게 의존하는지 (입력 컨트롤에 사용하려고했지만 아래 솔루션은 적어도 Chrome 및 Firefox에서 작동했습니다 (IE11에서는 아님)) ...
Alexander

3
특히 jQuery 의사 선택기를 사용하는 훌륭한 솔루션입니다. 그러나 요소 텍스트의 스타일 (글꼴 크기, 문자 간격, 내부 요소의 여백)이 다른 경우 너비가 잘못 계산되기 때문에 때때로 작동하지 않을 수 있습니다. 이 경우 'body'대신 $ this.parent ()에 clone 요소를 추가하는 것이 좋습니다. 이렇게하면 요소의 정확한 사본이 제공되고 계산이 정확합니다. 어쨌든 감사합니다
Alex

286

span 요소를 인수로 전달하여이 JS 함수를 시도하십시오.

function isEllipsisActive(e) {
     return (e.offsetWidth < e.scrollWidth);
}

10
대답은 매우 우아해야하며 Chrome 및 IE에서 작동합니다 (9)
Roy Truelove

14
이 답변과 Alex의 답변은 IE8에서 작동하지 않습니다. 스크롤 너비와 바깥 너비가 같은 이상한 경우가 있지만 줄임표가 있고 같은 경우에는 줄임표가 없습니다. 다시 말해, 첫 번째 솔루션은 모든 브라우저에서 작동하는 유일한 솔루션입니다.

3
의 offsetWidth, scrollWidth 및 clientWidth을 이해하는 데 필요한 사람들을 위해, 여기에 아주 좋은 설명입니다 : stackoverflow.com/a/21064102/1815779
린 댐

4
text-overflow:ellipsis그것이 있어야e.offsetWidth <= e.scrollWidth
oriadam

4
그들은 플렉스 어린이에서 항상 서로 동일하므로 작동하지 않습니다.
Kevin Beal

14

italo의 답변에 추가하여 jQuery를 사용 하여이 작업을 수행 할 수도 있습니다.

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

또한 Smoky가 지적했듯이 width () 대신 jQuery outerWidth ()를 사용할 수 있습니다.

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

9

Christian Varga의 대답을 사용하거나 사용하려는 사람들은 성능 문제를 알고 있어야합니다.

이러한 방식으로 DOM을 복제 / 조작하면 리소스를 많이 사용하는 DOM 리플 로우 ( DOM 리플 로우에 대한 설명 참조) 발생 합니다 .

페이지의 100 개 이상의 요소에 Christian Varga의 솔루션을 사용하면 JS 스레드가 잠기는 동안 4 초의 리플 로우 지연이 발생했습니다. JS가 단일 스레드임을 고려하면 이는 최종 사용자에게 상당한 UX 지연을 의미합니다.

Italo Borssatto의 답변 이 인정되어야합니다. 프로파일 링 중에 약 10 배 더 빠릅니다.


2
불행히도 모든 시나리오에서 작동하지는 않습니다 (원합니다). 또한 mouseenter툴팁을 표시해야하는 경우 에만 확인해야하는 상황에서만 실행하여 여기에서 언급 한 성능 적중을 상쇄 할 수 있습니다 .
Jacob

5

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.offsetWidth하고 e.scrollWidth더 텍스트 잘림이없는 경우에도, 당신은 IE에 다음 사항을 통지합니다,의 값 차이 1px또는 2px경험이있다.

따라서 사용하는 글꼴 크기에 따라 특정 허용 오차를 허용하십시오!


IE10에서는 작동하지 않습니다. offsetWidth는 scrollWidth와 동일하므로 둘 다 잘린 너비를 제공합니다.
SsjCosty

1
Chrome 60 (최신) 에서도이 허용 오차가 필요합니다.
Jan Żankowski

5

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'})
    }
  });
});

현재 Chrome이나 Firefox에서는 작동하지 않습니다. 두 요소 모두 빨간색이됩니다.
xehpuk 2011

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에서 작동합니다.


1

나는 그것을 감지하는 더 좋은 방법은 use라고 생각합니다. getClientRects()각 rect의 높이가 같은 것 같아서 다른 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같은 일

당신은 같은 감지 할 수있는


1

모든 솔루션이 실제로 효과가 없었습니다. 작동 한 것은 요소 scrollWidthscrollWidth부모 의 요소 (또는 트리거가있는 요소에 따라 자식)와 비교하는 것이 었습니다 .

자녀 scrollWidth가 부모보다 높으면 .text-ellipsis활동적 임을 의미 합니다.


event부모 요소는 언제

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

event자식 요소는 언제 입니까

function isEllipsisActive(event) {
    let el          = event.currentTarget;
    let width       = el.offsetWidth;
    let widthParent = el.parentElement.scrollWidth;
    return (width >= widthParent);
}

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;
    }
}

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>


0

내 구현)

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>


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.