HTML Object overflow 감지
HTML 내 요소에서 자식요소가 부모요소보다 클 때 css 상에서 overflow
속성을 정의해 처리를 할 수 있습니다.
하지만 이를 javascript에서 동적으로 처리를 하고 싶다면 다른 방법을 이용해야 합니다.
이때 2가지 방법을 이용할 수 있습니다.
1. scrollWidth 이용
위 이미지를 참고하면 clientWidth
와 scrollWidth
를 비교하여 scrollWidth
가 clientWidth
보다 크다면 overflow
가 발생했음을 알 수 있습니다.
아래의 예제를 따라 해보면 문제없이 결과를 얻을 수 있습니다.
<div class="wrap">
<!-- short는 200px 미만으로 overflow가 발생하지 않는다. -->
<div id="short">Lorem ipsum dolor sit amet</div>
<div id="long">consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
</div>
<style>
.wrap > div {
width: 200px;
white-space: nowrap;
}
</style>
const short = document.getElementById('short');
const long = document.getElementById('long');
// └ getElementById를 이용해 Element 객체 가져오기
const isOverflow = element => {
const {clientWidth, scrollWidth} = element;
// └ 구조분해 할당으로 clientWidth, scrollWidth 값 가져오기
return clientWidth < scrollWidth;
}
console.log(`is overflow? ${isOverflow(short)}`);
// 출력: is overflow? false
console.log(`is overflow? ${isOverflow(long)}`);
// 출력: is overflow? true
좀 더 응용해 보면
const short = document.getElementById('short');
const long = document.getElementById('long');
const getDiff = element => {
const {clientWidth, scrollWidth} = element;
const diff = scrollWidth - clientWidth;
return diff ? `overflow ${diff}px` : 'not overflow';
}
console.log(getDiff(short));
// 출력: not overflow
console.log(getDiff(long));
// 출력: overflow 439px
이렇게 얼마나 콘텐츠가 넘치는지 체크할 수 있습니다.
2. cloneNode 이용
두 번째 방법은 Node
객체의 instance methods 중 하나인 cloneNode
를 이용한 방법입니다.
Element
객체는 Node
객체를 상속받은 객체로 Node
객체의 instance methods를 이용 가능합니다.cloneNode
는 한 Node
객체를 그대로 복사해오는 method로 parameter로 boolean을 받아 자식요소들도 복제할지 선택할 수 있습니다.
복제해온 Node
의 style에 길이를 max-content
로 지정해 길이를 구하고 제거하는 방식으로 overflow
를 감지할 수 있습니다.
<div class="wrap">
<!-- short는 200px 미만으로 overflow가 발생하지 않는다. -->
<div id="short">Lorem ipsum dolor sit amet</div>
<div id="long">consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
</div>
<style>
.wrap > div {
width: 200px;
white-space: nowrap;
}
</style>
바로 1번 방식
의 응용 예제를 따라 해보면
const short = document.getElementById('short');
const long = document.getElementById('long');
// └ getElementById를 이용해 Element 객체 가져오기
const getCloneWidth = element => {
const clone = element.cloneNode(true);
// └ parameter로 true를 전달해 자식요소를 함께 복사
clone.style.width = 'max-content';
// └ 콘텐츠가 최대로 커질 수 있는 너비로 변경
element.parentNode.appendChild(clone);
// └ 원본 요소의 부모요소에 append해 상속받는 style도 적용하기
const cloneWidth = clone.clientWidth;
// └ 복제된 요소의 길이 구하기
element.parentNode.removeChild(clone);
// └ 복제된 요소 제거
return cloneWidth;
}
const getDiff = element => {
const width = element.clientWidth;
const cloneWidth = getCloneWidth(element);
const diff = cloneWidth - width;
return diff ? `overflow ${diff}px` : 'not overflow';
}
console.log(getDiff(short));
// 출력: overflow -15px
console.log(getDiff(long));
// 출력: overflow 439px
long의 결과는 1번 방식
과 같은 결과를 보이나 short의 경우가 -15px로 나타남을 볼 수 있습니다.
차이는 콘텐츠의 최대 너비를 구하는 과정에서 발생하는데 scrollWidth
는 요소가 아무리 작아도 clientWidth
보다 작아지지 않습니다.
그러나 cloneNode
방식을 이용했을 때는 복제된 Node의 너비 자체를 콘텐츠의 크기로 변경한 것으로 getCloneWidth
에서 반환된 크기는 콘텐츠의 크기가 됩니다.
즉, Lorem ipsum dolor sit amet
의 길이가 185px일 때 scrollWidth
는 200px이 되는것이고 getCloneWidth
의 반환 값은 185px이 되는 것입니다.
추가로 콘텐츠 크기를 구할 수 있는 cloneNode
방식을 Element에 바인딩할 수 있습니다.
Object.defineProperty(Element.prototype, 'contentWidth', {get() {
const clone = this.cloneNode(true);
clone.style.width = 'max-content';
this.parentNode.appendChild(clone);
const cloneWidth = clone.clientWidth;
this.parentNode.removeChild(clone);
return cloneWidth;
}});
위와 같이 작업해두면 아래처럼 간단하게 이용 가능합니다.
const element = document.getElementById('someId');
console.log(element.contentWidth);
const elements = document.querySelectorAll('someSelector');
elements.forEach(element => console.log(element.contentWidth));
마무리로 두가지 방법을 요약하자면
감지방식 | scrollWidth |
cloneNode |
---|---|---|
콘텐츠 크기 < clientWidth |
clientWidth |
콘텐츠 크기 |
성능 | 빠름(scrollWidth 값을 읽기만 하면 됨) |
느림(DOM 에 cloneNode 를 그려야함) |
추천 상황 | 일반적으로 사용 | 정확한 콘텐츠 크기를 비교해야할 때 |
로 볼 수 있습니다.
위 방법들을 이용해 Javascript에서 HTML Element에 Overflow가 발생했는지 간단히 알아볼 수 있습니다.
'개발일지 > Front-end' 카테고리의 다른 글
Javascript Closure를 이용해 Private 한 Class 만들기 (0) | 2023.02.20 |
---|---|
Throttling(스로틀링)과 Debouncing(디바운싱) (0) | 2023.02.12 |
Javascript 배열 용도에 맞게 순회하기 (0) | 2023.01.29 |
Javascript 숫자와 관련된 사소한 팁 (2) | 2023.01.22 |
Web API Javascript IntersectionObserver (0) | 2023.01.09 |