[Javascript] text-overflow: ellipsis 활성 여부를 JS로 판단하는 방법

박기영·2023년 3월 30일
2

Javascript

목록 보기
34/45

텍스트가 길어지면 ... 표시로 축약하도록 만드는 CSS 활용법이 있다.
주어진 width를 넘어가면 자동적으로 적용이 되는데, 이게 적용이 된건지 안된건지 그 여부를
알고싶을 때가 있다.
필자의 경우 ...로 축약된 텍스트에 대해서만 이벤트를 적용하고 싶었다.
방법을 알아보자.

문제 상황

참고 이미지

위 예시를 보자.
버튼의 넓이를 넘어가는 텍스트에는 ...으로 축약 표시가 발생하는 것을 확인할 수 있다.
이 때, 텍스트 부분에 적용된 CSS 코드는 다음과 같다.

.frequent_text {
  width: 90%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

이 CSS 속성들은 주어진 width를 넘어가는 텍스트를 ... 표시로 축약할 수 있게 해준다.

그런데, 문제가 있다.

그럼...축약된 텍스트의 완전한 내용은 어떻게 확인하지..?
게시글 목록을 보여주는 기능이었다면, 완전한 내용을 확인시켜줄 필요는 굳이 필요하지 않지만,
필자가 구현하고자 하는 기능은 저 버튼을 클릭하여 ToDo-List에 추가하는 기능이다.
어떤 ToDo인지도 모르는데 추가할 수는 없지 않은가..?
그렇다고 게시글 목록처럼 보여지는 칸이 길어서 모두 확인하지 않아도 큰 문제가 없는 것도 아니라
더욱 더 전체 내용을 확인할 필요성이 있다.

해결 방법

...을 생성하는 가장 큰 역할을 하는 CSS 속성은 바로 text-overflow이다.
그렇다면 이 속성이 기능을 하고 있는지 하고 있지 않는지를 판단하는 것이 중요하다.

기능을 하고 있다면, 축약된 텍스트를 보여줘야하고
기능을 하지 않고 있다면, 축약 기능이 실행되지 않은 것이므로, 아무런 기능을 하지 않아도 된다.

이제 JavaScript로 이를 동적으로 파악하는 방법을 알아보자.

JS로 text-overflow 검사하기

필자는 mouseover 이벤트가 발생했을 때, 검사를 진행하고 싶다.
따라서 아래와 같은 이벤트를 등록했다.

// getDetailFromHover.js

// 버튼 내부 텍스트에 대한 html 태그 정보 얻기
const frequent = document.getElementsByClassName("frequent_text");

// 이벤트 등록 및 제거를 위한 함수
export const addEventToEachFrequent = () => {
  for (let i = 0; i < frequent.length; i++) {
    // 마우스가 올려졌을 때
    frequent[i].addEventListener("mouseover", getDetailFromHover);

    // 마우스가 나갔을 때
    frequent[i].addEventListener("mouseout", clearDetailFromHover);
  }
};

mouseover 이벤트가 발생하면 아래와 같은 함수가 실행된다.
모달을 생성하여 축약되었던 텍스트를 모두 보여주는 기능이다.

// getDetailFromHover.js

// mouseover 이벤트 발생 시 실행되는 함수
const getDetailFromHover = (e) => {
  // text-overflow가 발생하지 않은 컴포넌트라면 기능 정지
  if (!checkTextOveflow(e)) {
    return;
  }

  // 모달 형식으로 축약 전 텍스트를 보여주게 된다.
  const detailModal = document.getElementById("frequent_detail_modal");

  const parentId = e.target.parentNode.id;
  const parentBtn = document.getElementById(parentId);

  const text = e.target.innerText;

  const div = document.createElement("div");
  div.innerHTML = text;
  div.classList.add("frequent_detail");
  div.id = `frequent_detail_${parentId}`;

  div.style.backgroundColor = parentBtn.style.backgroundColor;
  div.style.borderColor = parentBtn.style.borderColor;

  detailModal.appendChild(div);

  detailModal.style.top = `${parentBtn.getBoundingClientRect().top + 25}px`;
  detailModal.style.left = `${parentBtn.getBoundingClientRect().left + 20}px`;
};

기능을 실행하기 전에 text-overflow가 효력을 발휘하고 있는지를 체크해야한다.
축약 기능이 발생하지 않았음에도 기능을 실행하면 오히려 UX를 저해할 것이기 때문이다.

// getDetailFromHover.js

// text-overflow가 발생했는지 여부를 체크하는 함수
const checkTextOveflow = (e) => {
  // text-overflow가 발생하지 않은 경우
  if (e.target.clientWidth >= e.target.scrollWidth) {
    return false;
  }

  return true;
};

scrollWidthclientWidth보다 큰 경우라면 text-overflow가 효력을 발휘하는 상황이다.
이를 활용하여 분기 처리를 해줬다.

원리

scrollWidthclientWidth를 비교해서 text-overflow를 알아낼 수 있다는 것은 알겠다.
그런데...scrollWidthclientWidth는 무엇을 의미하는걸까?

참고 이미지

(출처 : http://jsfiddle.net/y8Y32/25/)

필자의 상황에 대입해서 간단하게 설명을 해보자면...

scrollWidth는 보이는 것과 상관없이 컨텐츠가 가지고 있는 실제 영역,
즉, 텍스트가 가지고 있는 넓이를 의미한다.

clientWidth는 보이는 부분에서 컨텐츠가 가지고 있는 영역,
즉, 버튼이 가지고 있는 넓이를 의미한다.

필자는 이벤트 객체를 통해 텍스트라는 컨텐츠가 담겨 있는 HTML 태그의 정보를 가져왔고,
scrollWidth는 텍스트가 가지고 있는 실제 영역의 넓이를 알려줬으며,
clientWidthtext-overflow가 처리된 텍스트가 가지고 있는 영역의 넓이를 보여준다.

따라서, scrollWidthclientWidth를 비교했을 때 다음과 같이 해석할 수 있다.

// text-overflow가 발생하지 않는 상황
e.target.clientWidth >= e.target.scrollWidth

// text-overflow가 발생하는 상황
e.target.clientWidth < e.target.scrollWidth

적용 예

참고 동영상

text-overflow로 인해 ...로 축약이 발생한 텍스트에 대해서만 모달이 발생한다!
정확히는 모달이라는 표현을 쓰면 안될 것 같지만

참고 자료

stackoverflow 질문글
dirask 게시글
ohgyun님 블로그

profile
나를 믿는 사람들을, 실망시키지 않도록

0개의 댓글