πŸ› οΈ textArea νƒœκ·Έ 쀄 수 μ œν•œ

λ°•λ―Όμš°Β·2023λ…„ 10μ›” 3일
1
post-thumbnail

πŸ“Œ 문제 상황

2023.09.01 ~ 2023.09.27 λ™μ•ˆ μ§„ν–‰ν–ˆλ˜ 앙골라 ν”„λ‘œμ νŠΈμ—μ„œ 포슀트 μž‘μ„±μ„ μœ„ν•΄ textArea νƒœκ·Έλ₯Ό μ‚¬μš©ν•΄μ•Ό ν•˜λŠ” 상황이 μžˆμ—ˆλ‹€. textArea νƒœκ·Έ λ‚΄μ—μ„œ μ‚¬μš©μžκ°€ ν…μŠ€νŠΈλ₯Ό μž…λ ₯ν•˜λ©΄ 이 λ‚΄μš©μ„ λ°”νƒ•μœΌλ‘œ ν¬μŠ€νŠΈκ°€ μž‘μ„±λœλ‹€.

이 ν…μŠ€νŠΈμ˜ λ‚΄μš©μ„ μ‹œκ°μ μœΌλ‘œ ν•œ λˆˆμ— νŒŒμ•…ν•  수 μžˆλ„λ‘ ν•˜κΈ° μœ„ν•΄, μ‚¬μš©μžκ°€ ν…μŠ€νŠΈλ₯Ό μž…λ ₯ν•˜λ”λΌλ„ textArea νƒœκ·Έ 내에 슀크둀이 생기지 μ•Šμ•˜μœΌλ©΄ ν–ˆλ‹€. κ·Έλž˜μ„œ textArea λ‚΄μ˜ ν…μŠ€νŠΈ λ‚΄μš©μ„ 5μ€„λ‘œ μ œν•œν•˜κ³  μ‹Άμ—ˆλ‹€.


πŸ“Œ ν•΄κ²° κ³Όμ •

이λ₯Ό μœ„ν•΄ λ‹€μ–‘ν•œ 방법을 μ‹œλ„ν–ˆλ‹€.

1. textArea의 rows 속성을 5둜 μ„€μ •

첫번째둜 μ‹œλ„ν–ˆλ˜ 방법은 textArea μš”μ†Œμ˜ rows 속성을 μ‚¬μš©ν•˜λŠ” λ°©λ²•μ΄μ—ˆλ‹€. 이 rows 속성은 textAreaλ‚΄μ˜ κ°€μ‹œμ μΈ height을 μ„€μ •ν•  수 μžˆλŠ” μ†μ„±μ΄μ§€λ§Œ, μš”μ†Œμ˜ height이 css둜 μ •ν•΄μ ΈμžˆλŠ” μƒνƒœμ—μ„œλŠ” 이 rows 속성이 μ μš©λ˜μ§€ μ•Šμ•˜λ‹€. κ·Έλž˜μ„œ λ‚˜μ˜ μ˜λ„λŒ€λ‘œ λ™μž‘ν•˜μ§€ μ•Šμ•˜κΈ°μ— λ‹€λ₯Έ 방법을 μƒκ°ν•΄λ³΄μ•˜λ‹€.


2. μž…λ ₯된 text μ•ˆμ— κ°œν–‰λ¬Έμž /nκ°€ 4개 λ“€μ–΄μžˆμœΌλ©΄ 5쀄 이상이라고 νŒλ‹¨

textArea λ‚΄μ˜ ν…μŠ€νŠΈκ°€ 5μ€„μ΄λΌλŠ” 것은 μ‚¬μš©μžκ°€ μ—”ν„°λ₯Ό 4번 μž…λ ₯ν–ˆμ„ 것이라고 νŒλ‹¨ν•΄, μž…λ ₯된 text인 string κ°’μ—μ„œ κ°œν–‰ 문자 /n의 개수λ₯Ό νŒλ‹¨ν•΄, 이 κ°œμˆ˜κ°€ 4개 이상이라면 더 이상 μž…λ ₯ν•˜μ§€ λͺ»ν•˜λ„둝 ν•΄μ£Όλ©΄ λ˜κ² λ‹€κ³  μƒκ°ν–ˆλ‹€. ꡬ글에 κ²€μƒ‰ν•΄λ³΄μ•˜μ„ λ•Œλ„, μ΄λŸ¬ν•œ λ°©λ²•μœΌλ‘œ 문제λ₯Ό ν•΄κ²°ν•œ 사둀가 λ§Žμ•˜κ³  이와 κ΄€λ ¨λœ ν•¨μˆ˜ μ½”λ“œλ“€λ„ 많이 곡유되고 μžˆμ—ˆλ‹€.

ν•˜μ§€λ§Œ μ’€ 더 곰곰이 μƒκ°ν•΄λ³΄λ‹ˆ, ν˜„μž¬ ν”„λ‘œμ νŠΈ λ‚΄ textArea μš”μ†ŒλŠ” 고정적인 widthκ°€ μ •ν•΄μ ΈμžˆλŠ” μƒνƒœμ΄κ³ , μ—”ν„°λ₯Ό μž…λ ₯ν•˜μ§€ μ•Šμ•„λ„ μž…λ ₯된 text의 길이가 κΈΈλ©΄ textArea λ‚΄μ—μ„œ μžλ™μ€„λ°”κΏˆ(\n은 μ—†μ§€λ§Œ μ€„λ°”κΏˆμ΄ λ˜μ–΄μ„œ 2쀄이 됨)이 되기 λ•Œλ¬Έμ— μ΄λ ‡κ²Œ νŒλ‹¨ν•  μˆ˜λŠ” μ—†κ² λ‹€κ³  μƒκ°ν–ˆλ‹€.


3. Element.scrollHeight 속성 μ‚¬μš©

μ—¬λŸ¬κ°€μ§€ 방법을 찾아보닀 Element.scrollHeight μ΄λΌλŠ” 속성을 μ•Œκ²Œ λ˜μ—ˆλ‹€.

Element.scrollHeight

element_height

μœ„μ˜ κ·Έλ¦Όμ—μ„œ λ³Ό 수 μžˆλ“―μ΄, HTML element의 λ„ˆλΉ„μ™€ 높이λ₯Ό λ‚˜νƒ€λ‚΄λŠ” 속성은 μ—¬λŸ¬κ°€μ§€κ°€ 있고, 이 쀑 높이λ₯Ό λ‚˜νƒ€λ‚΄λŠ” 속성 쀑 clientHeightκ³Ό scrollHeight이 μžˆλ‹€.

  • clientHeight

    => border, scrollBarλ₯Ό μ œμ™Έν•œ μ‹€μ œ λ‚΄λΆ€ 컨텐츠가 μ°¨μ§€ν•˜λŠ” 크기λ₯Ό λ‚˜νƒ€λ‚Έλ‹€. 즉, μš”μ†Œ λ‚΄μ˜ 슀크둀이 λ˜λŠ” 컨텐츠가 μžˆλ”λΌλ„, μ‹€μ œλ‘œ λˆˆμ— λ³΄μ΄λŠ” μ˜μ—­μ˜ 높이λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.

  • Element.scrollHeight

    => ν™”λ©΄μ—μ„œ λ³΄μ΄λŠ” μ˜μ—­κ³Ό 상관없이, μ‹€μ œ μ—˜λ¦¬λ¨ΌνŠΈμ˜ 높이λ₯Ό λ‚˜νƒ€λ‚Έλ‹€. 즉, μš”μ†Œ λ‚΄μ˜ 슀크둀이 λ˜λŠ” 컨텐츠가 μžˆλ‹€λ©΄ κ·Έ μ»¨ν…μΈ μ˜ λ†’μ΄κΉŒμ§€ λ‹€ λ‚˜νƒ€λ‚΄μ£ΌλŠ” 속성이닀.

  • λ§Œμ•½ μš”μ†Œμ˜ μ½˜ν…μΈ κ°€ μŠ€ν¬λ‘€λ°” 없이 λͺ¨λ‘ λ³΄μ΄λŠ” 경우, μš”μ†Œμ˜ scrollHeight와 clientHeight은 λ™μΌν•˜λ‹€.

HTML μš”μ†Œμ˜ 크기 속성에 λŒ€ν•œ 더 μžμ„Έν•œ λ‚΄μš©μ€ μ—¬κΈ°λ₯Ό μ°Έκ³ ν–ˆλ‹€.

μ΄λŸ¬ν•œ λ‚΄μš©μ„ λ°”νƒ•μœΌλ‘œ, κ²°κ΅­ μ‚¬μš©μžμ˜ ν…μŠ€νŠΈ μž…λ ₯이 λ§Žμ•„μ Έ μš”μ†Œ μ•ˆμ— 슀크둀이 생길 경우 μš”μ†Œμ˜ scrollHeight 값이 λ³€ν•˜κ²Œ λœλ‹€λŠ” 사싀을 μ•Œκ²Œλ˜μ—ˆλ‹€.

κ·Έλž˜μ„œ textArea μš”μ†Œμ˜ height을 ν…μŠ€νŠΈκ°€ 5쀄 μž…λ ₯될 λ•ŒκΉŒμ§€λŠ” 슀크둀이 생기지 μ•Šκ³ , 6쀄을 μž…λ ₯ν–ˆμ„ λ•Œ 슀크둀이 생길 μ •λ„μ˜ νŠΉμ • κ°’(ex) 256px) 둜 지정해놓고, ν…μŠ€νŠΈ μž…λ ₯ μ‹œ textArea의 scrollHeight이 λ³€ν•œλ‹€λ©΄, κ·Έ μž…λ ₯은 6쀄 μ΄μƒμ˜ μž…λ ₯이기 λ•Œλ¬Έμ— μ μš©λ˜μ§€ μ•Šλ„λ‘ ν•˜λ©΄ λ˜κ² λ‹€κ³  μƒκ°ν–ˆλ‹€.

κ·Έλž˜μ„œ μ²˜μŒμ—” λ‹€μŒκ³Ό 같이 μš”μ†Œμ˜ scrollHeight 값이 λ³€ν•˜μ§€ μ•Šμ„ λ•Œλ§Œ μž…λ ₯이 κ°€λŠ₯해도둝 ν•΄μ£Όμ—ˆλ‹€.

const MAX_OPTION_SCROLL_HEIGHT = 252;

const handleChangeOptionValues = (e: ChangeEvent<HTMLTextAreaElement>) => {
    const { id, value } = e.target;
    if (e.target.scrollHeight === MAX_OPTION_SCROLL_HEIGHT) { 
        // scrollHeight이 λ³€ν•˜μ§€ μ•Šμ„ λ•Œλ§Œ μž…λ ₯ κ°€λŠ₯
        setInputValues({
        ...inputValues,
        [id]: value.substring(0, MAX_TITLE_OPTION_LENGTH),
      	});
    } 
  };

ν•˜μ§€λ§Œ μ’€ 더 μƒκ°ν•΄λ³΄λ‹ˆ, 슀크둀이 생기기 μ „μ—λŠ” μš”μ†Œμ˜ clientHeight κ°’κ³Ό scrollHeight 값이 같을 것이고 슀크둀이 생길 λ•Œ 이 값이 μ„œλ‘œ λ‹¬λΌμ§ˆ 것이기 λ•Œλ¬Έμ—, ꡳ이 μƒμˆ˜κ°’μΈ const MAX_OPTION_SCROLL_HEIGHT = 252;을 μ„ μ–Έν•΄ λΉ„κ΅ν•˜μ§€ μ•Šκ³  clientHeight κ°’κ³Ό scrollHeight을 λΉ„κ΅ν•˜λ„λ‘ λ‘œμ§μ„ λ³€κ²½ν–ˆλ‹€. 그리고 ν•˜μœ„ ν•¨μˆ˜λ₯Ό textArea의 onChange 이벀트 ν•Έλ“€λŸ¬λ‘œ μ—°κ²°ν•΄μ£Όμ—ˆλ‹€.

const handleChangeOptionValues = (e: ChangeEvent<HTMLTextAreaElement>) => {
  const { id, value } = e.target;
  if (e.target.scrollHeight === e.target.clientHeight) {
    setInputValues({
      ...inputValues,
      [id]: value.substring(0, MAX_INPUT_LENGTH),
    });
  }
};

lineHeight 속성 μ„€μ •

그리고 textArea 내에 5쀄이 같은 κ°„κ²©μœΌλ‘œ λ°°μΉ˜λ˜λ„λ‘ ν•˜κΈ° μœ„ν•΄ μš”μ†Œμ˜ height인 212λ₯Ό 5둜 λ‚˜λˆˆ 42 값을 line-height κ°’μœΌλ‘œ μ„€μ •ν•΄μ£Όμ—ˆλ‹€.

const OptionInput = styled.textarea`
	line-height: 42px;
`;

word-break, overflow 속성 μ„€μ •

clientHeight κ°’κ³Ό scrollHeight을 비ꡐ해 5μ€„λ‘œ μ œν•œμ„ ν•΄μ£Όμ—ˆμ§€λ§Œ, μ΄λ ‡κ²Œ 숫자λ₯Ό 계속 μž…λ ₯ν•˜λ©΄ ν•œκΈ€μž ν˜Ήμ€ 두 κΈ€μž μ •λ„λŠ” λ‹€μŒ μ€„λ‘œ λ‚΄λ €μ˜€λŠ” 버그가 λ°œμƒν–ˆλ‹€. κ·Έλž˜μ„œ, μΆ”κ°€λ‘œ css 속성인 word-breakκ³Ό overflow 값을 μ„€μ •ν•΄μ£Όμ–΄ μ΄λŸ¬ν•œ 뢀뢄을 보이지 μ•Šλ„λ‘ μ„€μ •ν•΄μ£Όμ—ˆλ‹€.

const OptionInput = styled.textarea`
  word-break: break-all;
  overflow: hidden;
`;

πŸ“Œ κ²°κ³Ό 및 정리

λ”°λΌμ„œ textArea μš”μ†Œ λ‚΄ 쀄 수λ₯Ό μ œν•œν•˜κΈ° μœ„ν•΄μ„œ λ‹€μŒκ³Ό 같은 방법을 μ μš©ν–ˆλ‹€.

  1. λͺ‡ 쀄 μ œν•œν•  건지 λ¨Όμ € κ²°μ • => n쀄

  2. μ›ν•˜λŠ” μš”μ†Œμ˜ 높이λ₯Ό μ„€μ •ν•˜κ³ , lineHeight을 μš”μ†Œμ˜ 높이 / n κ°’μœΌλ‘œ μ„€μ •

    β‡’ n개 쀄 이상 μž…λ ₯ μ‹œ 슀크둀이 생길 κ²ƒμž„

  3. μš”μ†Œμ˜ clientHeight κ°’κ³Ό scrollHeight 값이 같을 λ•Œλ§Œ μš”μ†Œμ˜ λ‚΄μš©μ΄ λ³€κ²½λ˜λ„λ‘ ν•΄μ£ΌκΈ°

    const handleChangeOptionValues = (e: ChangeEvent<HTMLTextAreaElement>) => {
      const { id, value } = e.target;
      if (e.target.scrollHeight === e.target.clientHeight) {
          // μš”μ†Œμ˜ λ‚΄μš© λ³€κ²½
      }
    };
  4. κ·Έλž˜λ„ 가끔 ν•œ 두 κΈ€μžλŠ” λ°‘μœΌλ‘œ λ‚΄λ €κ°€λ―€λ‘œ ν•΄λ‹Ή μš”μ†Œμ˜ css에 두 속성 써주기

    word-break: break-all;
    overflow: hidden;
profile
κΎΈμ€€νžˆ, 깊게

0개의 λŒ“κΈ€