## 問題の内容 フォームヘルパーで作成したフォームの標準の挙動として、 [railsは、バリデーション・エラーが起きたフォーム要素を、`field_with_errors`クラスを指定したdiv要素で囲みます](https://railsguides.jp/active_record_validations.html#%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A8%E3%83%A9%E3%83%BC%E3%82%92%E3%83%93%E3%83%A5%E3%83%BC%E3%81%A7%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B)。 つまり、バリデーション・エラーの有無によって、HTMLの階層構造が変わってしまいます。 その一方で、BootstrapのInput groupは、`input-group`クラスを指定した要素の直接の子要素としてフォーム要素があることを前提としています。 そのためバリデーション・エラー時に、`input-group`を指定した要素とフォーム要素の間に`field_with_errors`クラスのdiv要素が割り込むことで、Input groupの表示を乱してしまいます。 この問題に対し、インターネット上の情報では、 `display: contents;`を利用する方法や [`config.action_view.field_error_proc`](https://railsguides.jp/configuring.html#config-action-view-field-error-proc)の設定を変更する方法が紹介されていましたが、 私が試した限りでは問題の解決に至りませんでした。 そこで以下では、Input groupの利用を諦めて、Input groupに似た表示を他のBootstrapの機能で実現する方法をご紹介します。 なお、この問題に関して別の何か良い方法をご存じの方がいらっしゃいましたら、コメントをいただけると嬉しいです。 ## Bootstrapにおいて、Input groupに似た表示をgridで作成する方法 例として、Input groupを利用した以下のフォームの一部分を考えます。 ```erb
@ <%= f.text_field :username, class: 'form-control' %>
``` このフォームの一部分に近い表示を実現する例が以下のコードです。Input groupを利用した表示と比べると、「@」を囲む枠線は無くなりますが、文字やフォームの位置関係は近いものを実現できます。なお、ブラウザの画面幅をいろいろと変えた場合でも、位置関係の近さは大丈夫なはずです。 ```erb
@
<%= f.text_field :username, class: 'form-control' %>
``` このコードで利用しているBootstrapのクラスについて少し解説します。 まず横幅のバランスに関しては、以下のクラスを利用しています。 - `col-auto`:内容の幅、つまり、上述のコードではフォームの左にある文字列である「@」の幅に基づいたカラムの幅になります。 - `col`:残っている幅を均等に割り付けた幅になります。例えば`col`クラスのカラムが2つあれば残りの幅が2分割されて均等に割り付けられます。上述のコードでは`col`クラスのカラムは1つですので、左にある「@」のカラムの幅を除いた残りの幅が全てこの`text_field`のカラムに割り付けられます。 次に文字の位置(この例では「@」の位置)は、以下のクラスで調整しています - `col-form-label`:指定することでフォームと上下位置をそろえられます。 - `gx-*`:ガターを調整することで「@」とフォームの間の距離を調整し左右位置を調整しています。なお、左右位置を細かく調整したい場合にはmarginで直接細かく指定しても良いかもしれません。 ### (参考)Input groupに似せることよりもgridのカラム幅の指定を優先する場合 グリッドにおいて要素間の左右位置をそろえたいとき等では、`col-auto`を使わずに、以下のコードのようにカラム幅を指定する方法もあります。 このような場合では、文字列の左右位置の調整に`text-end`クラスや`text-center`クラスが役立つかもしれません。 ```erb
@
<%= f.text_field :username, class: 'form-control' %>
``` ## コードの動作確認をしたgemのバージョン - rails (7.1.3.4) - bootstrap (5.3.3)