概要

safariで複数行入力フィールドtextareaのプレースホルダに改行がうまく表示されない問題に対しての調査結果と対策をメモします。

<textarea placeholder='a\nb\nc'/>

textareaのplaceholder改行コードについての仕様

textareaのプレースホルダの文言に改行コードが含まれる場合、表示する際に改行として扱わなければなりません。

  • Mozillaドキュメント
    textarea 要素

    placeholder
    コントロールに何を入力できるかに関する、ユーザーへの助言です。プレースホルダーのテキスト内にあるキャリッジリターンやラインフィードは、表示する際に改行として扱わなければなりません。

  • W3C標準
    ブラウザの標準仕様上でも、レンダリングする時に改行をしなければなりません。
    html5 textarea-placeholder仕様

    All U+000D CARRIAGE RETURN U+000A LINE FEED character pairs (CRLF) in the hint, as well as all other "CR" (U+000D) and "LF" (U+000A) characters in the hint, must be treated as line breaks when rendering the hint.

  • Safariの動き
    ChromeとFirefoxがOKですが、safariの場合、改行コードがうまく表示されません。
    そもそも、プレースホルダが簡潔なヒントなので、html5仕様にも複数行を許可するものでもありません。
    DOMにplaceholderの改行コードが半角スペースに置換されてしまいます。

対応方法

下記理由で、プログラミングで必要によってvalue属性にplaceholderの内容を設定したら、解決になります。

  • placeholderが入力値がないかつフォーカスになっている状態の場合しか表示されないものです。
  • value属性に含まれる改行コードが改行としてうまくレンダリングしてくれます。

次はreact+reduxの場合を具体的な例として説明します。

  • componentのstateにフラグを立てます。
constructor(props) {
  super(props);
  this.state = { focused: false }; // textareaにフォーカスになっているかどうかを定義
}
  • 未入力かつフォーカスになってない場合、placeholderの内容をvalue属性に設定します。onblurとonfocusによってフラグの値を変更します。
<textarea
  value={
    (!this.state.focused && this.props.myState.form.content.length ===0)
      ? 'a\nb\nc'
      : this.props.myState.form.content
  }
  onfocus={() => this.setState({focused: true})}
  onblur={() => this.setState({focused: false})}
/>

react+redux一方向でのデータ流れの恩恵を受けて、上記のように簡単に実現できました。

参考記事

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.