レンダリングによって form タグが消えた話
- 最終更新日: 2026年1月21日(水)
- 公開日: 2026年1月21日(水)
はじめに
初めまして。
昨年10月より株式会社ファンデリーに入社しました、毎川です。
入社してから早いもので3ヶ月が経ちました。
本記事では、エンジニアとして業務に携わる中で遭遇した
HTML のレンダリング挙動が原因の不具合についてまとめます。
同じような現象で悩む方の参考になれば幸いです。
目次
- 経緯
- 不可解な現象
- 原因調査
- 原因の特定
- 解決方法
- まとめ
経緯
とある案件で発生していた不具合を解消するため、
「値を nil にするボタン」を一覧画面に追加する対応を行っていました。
詳細な業務ロジックは割愛しますが、td タグの中に以下のようなボタンを設置しました。
<tr>
<td class="action-cell">
<form action="/items/1/remove" method="post" class="remove-form">
<button type="submit" class="btn-remove">解除</button>
</form>
</td>
</tr>処理を実装し、動作確認を行ったところ——
2行目以降は正常に動作するのに、1行目だけ反応しない
という不可解な現象が発生しました。
不可解な現象
ボタンはクリックでき、見た目も他の行と同じです。
しかし、1行目のボタンだけは何度押してもリクエストが送信されません。
そこで Chrome の DevTools を確認しました。
すると、Elements タブ上では次のような DOM 構造になっていました。
<!-- 1行目 -->
<tr>
<td class="action-cell">
<!-- 本来ここにあるはずの form が存在しない -->
<button type="submit" class="btn-remove">解除</button>
</td>
</tr>
<!-- 2行目以降 -->
<tr>
<td class="action-cell">
<form action="/items/2/remove" method="post" class="remove-form">
<button type="submit" class="btn-remove">解除</button>
</form>
</td>
</tr>最初の1行目だけ、form タグが DOM から消えていたのです。
当然、form が存在しないためリクエストも送信されません。
原因調査
コード上はすべての行で同じ partial を使っており、
HTML の記述にも誤りはありません。
「なぜ 1 行目だけ?」という疑問が解消できず、
原因調査に時間を要しました。
原因の特定
調査を進める中で、そもそも DevTools で見ているものは何か
という点に立ち返りました。
DevTools の Elements タブに表示されているのは、
ブラウザが HTML を解析・修正した レンダリング後の DOM
です。
さらに調べると、HTML の仕様上、
<form>タグの中に<form>を入れ子にすることは 禁止- このような構造がある場合、ブラウザは HTML を自動的に修正する
というルールがあることが分かりました。
改めてコードを確認すると、
自分が編集していた partial は すでに form タグで囲まれた状態で render されていた ことが判明しました。
つまり、
- 外側ですでに
<form>が存在 - その内側でさらに
<form>を定義 - HTML の仕様違反が発生
- Chrome がレンダリング時に DOM を補正
- 結果として 最初の form だけが DOM から消えた
という流れでした。
解決方法
対応として、button_to(= form を生成)をやめ、link_to に変更しました。
<%= link_to "解除", item_path(@item),
data: {
turbo_method: :delete,
turbo_confirm: "本当に解除しますか?"
} %>これにより a タグとして出力され、
form の入れ子構造が解消され、不具合は無事解決しました。
まとめ
今回の経験から得た学びは以下の2点です。
- HTML では form タグの入れ子構造は許可されていない
- ブラウザはレンダリング時に壊れた HTML を自動修正する
Chrome の賢さに助けられる場面も多い一方で、
その挙動を知らないと原因特定が難しくなるケースもあると感じました。
今回の出来事を通して、
レンダリングの「便利さ」と「怖さ」の両方を実感しました。
今後は HTML の仕様とブラウザの挙動を意識しながら、
より安全な実装を心がけていきたいと思います。
参考文献
- MDN Web Docs –
<form>要素
https://developer.mozilla.org/ja/docs/Web/HTML/Element/form
(formタグの仕様および、入れ子構造が許可されていない点) - WHATWG HTML Living Standard – The
formelement
https://html.spec.whatwg.org/multipage/forms.html#the-form-element
(formの content model と HTML 仕様上の制約) - Chrome Developers – DOM と DevTools
https://developer.chrome.com/docs/devtools/dom/
(DevTools がレンダリング後の DOM を表示していることの公式説明)
現在デザイン・システム室では、新しいメンバーを募集しています。
少しでも興味を持たれた方は、ぜひご応募ください。
皆様からのご応募、心よりお待ちしております。