LoginSignup
0
1

More than 1 year has passed since last update.

<React>テキストエリアの高さを自動でいい感じにする

Posted at

textareaは高さがrowsで指定した値になり自動でリサイズしてくれません。
今回は自動でリサイズする方法をまとめます。

こんなの

ezgif-3-846be6b9d0.gif

React

textarea.tsx
import { useEffect, useRef, useState } from 'react'

const heightToNumber = (str: string): number => {
  return +str.replace('px', '')
}

const calculateRows = (textarea: HTMLTextAreaElement | null): number => {
  if (!textarea) return 0

  const style = getComputedStyle(textarea)
  const lineHeight = heightToNumber(style.lineHeight)
  const paddingY = heightToNumber(style.paddingTop) + heightToNumber(style.paddingBottom)
  const textareaHeight = textarea.scrollHeight

  return Math.floor((textareaHeight - paddingY) / lineHeight)
}

function TextAreaWithDynamicRows() {
  const textareaRef = useRef<HTMLTextAreaElement | null>(null)
  const [rows, setRows] = useState(0)

  useEffect(() => {
    setRows(calculateRows(textareaRef.current))
  }, [])

  const handleInput = (): void => {
    setRows(calculateRows(textareaRef.current))
  }

  return (
    <textarea ref={textareaRef} rows={rows} onInput={handleInput}>
      あいうえお
    </textarea>
  )
}

解説

  1. textareaからパラメータを取得するのでrefで管理します
  2. textareaからgetComputedStyleでstyleを取得し
    scrollHeight(コンテンツのスクロールを加味した高さ)からpaddingの分を引いてコンテンツの高さを出し、lineheightで割ることでrowsを求めることができます。

\nを数えて行数を取得する例は多く見られますが、文字数により改行になっているものを数えることができないので今回は使っていません。

issue

なぜか1文字でも2行表示されるので解決法ある or もっと良いアルゴリズムあれば教えてください

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1