概要
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一方向でのデータ流れの恩恵を受けて、上記のように簡単に実現できました。