Javascript 브라우저 크기 조절할 때, textarea 높이 자동 조절


textarea 높이 자동 조절

[ Javascript 목차 보기 ]

*인터넷 브라우저의 크기를 변동에 따라 오른쪽 textarea의 높이가 자동으로 변한다.

textarea의 크기 자동조절은 크게 2가지로 응용할 수 있다. 첫 번째의 경우는 위의 구현 결과처럼, 브라우저의 크기를 조절 할 때 내용물 크기로 높이를 자동 조절하는 것이다. 이렇게 함으로써 스크롤바없이 항상 모든 내용을 보여줄 수 있다. 이번 포스트에서는 어떻게 이를 구현할 수 있는지를 알아본다. 두 번째의 경우는 textarea에 글자를 입력할 때, 텍스트의 높이에 반응하여 textarea의 높이를 자동 조절하는 방식이다. 말이 어려우니 아래 데모를 직접 테스트해보자. 이와 관련해서는 다른 포스트에 자세히 다뤘다. [참고2. 텍스트 입력할 때, textarea 높이 자동 조절]

[1] 기본 구현 (HTML, CSS)

  • 예제 목표
    여기서는 먼저 HTML과 CSS의 기본 구현을 한다. 자바스크립트는 다음 섹션에서 구현한다.
  • HTML
    <div id=”wrapper”></div> <!– 예제 코드를 둘러싼 래퍼에 해당한다.[참고1. 래퍼란?] –>
    <textarea id=”target-textarea” disabled></textarea> <!– textarea를 생성하고, textarea의 수정을 금지하기 위해 disabled 속성을 추가한다. –>
  • #target-textarea의 CSS
    box-sizing: border-box; // 박스 사이징을 border-box로 설정한다. hegiht의 계산법은 box-sizing에 따라 달라지기 때문에, box-sizing 설정이 중요하다. 자세한 내용은 아래섹션 scrollHeight의 원리에서 설명한다.
    resize: none; // textarea의 크기를 사용자가 변동하지 못하게 한다.
    border: 1px solid rgb(42, 42, 42); // 테두리선의 모양과 색깔을 설정한다.
    width: 100%; // width를 부모 요소 div#wrapper 너비 대비 100%로 설정한다.
  • #wrapper의 CSS
    기본적인 래퍼 속성을 설정한다. 기본적으로 설정하는 프로퍼티들에 대한 내용은 참고1 포스트에 자세히 나와 있다.[참고1. 래퍼란?]
HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
<div id=“wrapper”>
    <textarea id=“target-textarea” disabled>내용물의 크기에 맞게 hegiht를 조절해보겠습니다.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus reiciendis et eaque fuga odit nisi repudiandae perferendis sit, voluptatibus, velit molestias! Deserunt fugiat non quae ducimus sapiente ab quibusdam sunt!
1
2
3
4
5
6
7
8
9
10</textarea>
cs
CSS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<style>
    #target-textarea {
        box-sizing: border-box;
        resize: none;
        border: 1px solid rgb(42, 42, 42);
        width: 100%;
    }
    /* 아래는 기본 래퍼 설정 */
    #wrapper {
        margin: 0 auto;
        padding: 10px 20%;
        max-width: 1170px;
    }
</style>
cs
RESULT

  • 구현 결과
    textarea는 width는 래퍼 너비 대비 100%로 설정되어 있기 때문에, 인터넷 브라우저의 크기에 따라 변하게 되어 있다. 그리고 textarea는 content에 있는 글자들을 다 보여줄 수가 없어서 스크롤을 생성시킨다. 여기까지가 HTML과 CSS의 기본 설정이다. 그렇다면 어떻게 내용물 높이에 맞춰서 textarea의 height를 설정할 수 있을까? 동적인 웹사이트를 위해서 자바스크립가 필요한 순간이다.

[2] 동적 동작 구현 (Javascript)

  • 예제 목표
    자바스크립트로 textarea의 높이를 내용물에 맞게 자동 조절한다.
  • 구현 원리
    scrollHeight는 내용물의 높이를 포함하는 개념이다. 따라서 textarea의 height를 scrollHeight로 설정함으로써 내용물의 높이에 맞게 자동 조절할 수 있다. 하지만 조심해야할 점들이 몇 가지 있다. 예를 들어 textarea의 height는 border-box이냐 content-box이냐에 따라 다르고, scrollHeight 또한 상황에 따라 비어있는 높이가 포함 될 수 있다. 아래의 scrollHeight의 원리를 정확히 먼저 이해하고, 자바스크립트를 작성해보자.

[2.1] scrollHeight의 원리

  • textarea의 박스 모델
    구현 핵심 원리는 scrollHeight를 이용하는 것이기 때문에, scrollHeight가 뭘 의미하는지 정확히 이해해야 한다. Figure 1 왼쪽을 보면, textarea는 margin (여기서는 표시 안함), border, padding, content 부분으로 나눠진다. 그리고 content 부분에 내용물을 표시하게 된다. textarea는 기본 박스 모델처럼 박스 사이징(box-sizing)에 따라 height가 다르게 된다.
    • box-sizing: border-box일 때
      height = content + padding + border
    • box-sizing: content-box일 때
      height = content
textarea scrollHeight
Figure 1. textarea 박스 모델. scrollHeight = 내용물의 높이 + paddingTop + paddingBottom

  • scrollHeight란?
    scrollHeight는 “content+padding” 외에 “보여지지 않는 내용물”의 높이를 더한 값이 된다. (Figure 1) 따라서 border-box의 경우에 textarea의 height를 scrollHeight + borderTop + borderBottom으로 설정해주면, textarea의 높이를 내용물 크기에 맞출 수 있다. 이것이 이번 구현의 핵심원리이다.
  • 주의할 점
    scrollHeight의 정의를 곱씹을 필요가 있다. (Figure 1 오른쪽) 만약 scrollHeight를 단순히 내용물의 높이 + padding으로 이해한다면 다음과 같은 문제가 발생할 수 있다. Figure 2처럼 내용물이 다 보여지는 경우를 생각해보자. textarea의 height가 내용물의 height보다 크게 설정되어 있어서, “비어있는 높이”가 존재한다. 이러한 비어있는 높이는 내용물의 높이도 아니고, 그렇다고 padding에 속하는 것도 아니다. 그냥 content에 속하는 것이다. 이런 경우 scrollHeight을 내용물 높이 + padding이 착각할 수 있는데, 실제로는 “내용물 높이” + “비어있는 높이” + padding이 된다. 다시 말해서 scrollHeight = content + padding이 된다. 비어있는 높이도 고려해야 한다는 것이다.
textarea scrollHeight
Figure 2. 내용물이 content에 다 표시된 경우: scrollHeight = content + padding. 비어있는 높이는 padding에 포함되는 개념도 내용물에 포함되는 개념도 아닌 점을 유의하자.

  • 문제 발생 시점
    Figure 2와 같은 상황이 발생할 수 있는 경우는, 브라우저 창을 작게 만들어서 textarea를 길게 만들었다가, 다시 창을 넓혀서 행을 줄이려고 할 때 textarea의 높이가 줄어들지 않는다. 말이 어려우니 아래 데모를 통해서 문제점을 확인해보자. 단순히 textarea의 height를 scrollHeight + borderTop + borderBottom로 할당할 때, Figure 2와 같은 상황에서는 scrollHeight가 “비어 있는 높이”를 포함하고 있어서 아래 공백도 함께 포함되는 것이다. 따라서 textarea가 내용물에 맞게 높이조절이 되지 않는다.
  • 해결 방법
    현재로선 “비어있는 높이”를 측정할 수 있는 방법이 따로 없기 때문에, 우리가 할 수 있는 방법은 textarea의 height를 0px로 만들어 주어서 비어있는 높이를 없애 주어 Figure 1처럼 만들어 준다. 그리고 height를 scrollHeight + borderTop + borderBottom으로 할당해줌으로써 textarea 높이를 내용물 높이에 맞출 수 있다.

[2.2] Javascript

위의 원리를 바탕으로 자바스크립트 코드를 짜보자.

function resize() { }

textarea의 크기를 조정하는 함수 resize()를 만들 것이다. 구현은 크게 3가지 순서로 나눌 수 있다. (1) textarea의 높이를 0px로 바꾼다. (2) textarea의 scrollHeight, borderTop, borderBottom을 구한다. (3) textarea의 height를 scrollHeight + borderTop + borderBottom으로 할당 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script>
    function resize() {
        let textarea = document.getElementById(“target-textarea”);
 
        textarea.style.height = “0px”;
 
        let scrollHeight = textarea.scrollHeight;
        let style = window.getComputedStyle(textarea);
        let borderTop = parseInt(style.borderTop);
        let borderBottom = parseInt(style.borderBottom);
 
        textarea.style.height = (scrollHeight + borderTop + borderBottom)+“px”;
    }
    
    window.addEventListener(“load”, resize);
    window.onresize = resize;
</script>
cs
  1. textarea의 높이를 0px로 바꾼다.
    • let textarea = document.getElementById(“target-textarea”); // textarea 요소를 불러온다.
    • textarea.style.hegiht = “0px”; // textarea의 높이를 0으로 설정한다. 단위 px를 붙여야 한다는 것에 유의하자.
  2. textarea의 크기 정보를 가져온다.
    • let scrollHeight = textarea.scrollHeight; // scrollHeight는 요소.scrollHeight 형태로 가져올 수 있다. scrollHeight는 요소.style와는 다르게 단위(px) 없이 정수로만 이뤄져 있다.
    • let style = window.getComputedStyle(textarea);  // textarea의 계산된 스타일을 가져오기 위해서 window.getComputedStyle(요소)를 사용하여 변수 style에 저장한다. 요소.style에 등록되어 있지 값들도 getComputedStyle함수로 가져올 수 있다.
    • let borderTop = parseInt(style.borderTop); // borderTop은 style.borderTop으로 가져올 수 있고, 값은 정수가 아니라 단위 px이 붙은 문자열의 형태이다. (예: 47px) 따라서 뒤에 있는 단위를 때어주기 위해 parseInt함수를 사용한다.
    • let borderBottom = parseInt(style.borderBottom); // borderBottom은 style.borderBottom으로 가져올 수 있고, 단위를 때어주기 위해 parseInt함수를 사용한다.
  3. textarea의 height를 할당해준다.
    • textarea.style.height = (scrollHeight + borderTop + borderBottom) + “px”; // border-box 형태이기 때문에 hegiht를 scrollHeight + borderTop + borderBottom으로 할당해준다. 그리고 style에는 단위 px를 붙인 형태로 입력해야함을 명심하자.

이벤트 리스너 (Event Listener)

  • window.addEventListener(“load”, resize); // 페이지가 다 로딩되고 나면, resize 함수를 실행시킨다. 이를 통해 첫 로딩시 textarea의 높이를 설정할 수 있다. window.onload = resize; 형태로도 입력할 수 있다.
  • window.onresize = resize; // 인터넷 브라우저 크기가 변동이 발생하면, resize 함수를 실행시킨다. window.addEventListener(“resize”, resize); 형태로도 입력할 수 있다.

최종 결과

참고
[1] 래퍼란?
[2] 텍스트 입력할 때, textarea 높이 자동 조절
[ Javascript 목차 보기 ]

Leave a Reply