コーディングで注意!IE9とモダンブラウザのフォームレイアウトの違いと解決策

ウェブサイトや何かのアプリケーションを開発しているときに「Internet Explorer(通称:IE)」の対応を求められるときがあります。Internet Explorerは年齢層が高めの方や、主婦の方などが使用しているために、そのような属性の方が利用するサービスを開発している場合はマストです。

自社メディアを運営している会社の方もですが、クライアントの案件をしている受託会社・制作会社の方はほぼ確実に苦しんだことがあるかと思います。

今回は、フロントエンドのエンジニアを苦しめているIEの中でも私のサービスで見つかったIE9とGoogle Chrome、safari、Firefoxなどのモダンブラウザでのレイアウトの違いと、formタグのブラウザごとの認識でこういう違いがあるんだというハマったポイントをご紹介します。

IE9のフォームのレイアウトはよろしくやってくれない

例えば下記のようなフォームを作成したい場合があります。

form

名前、かな、メールアドレスなどを入力した後に、登録ボタンと、戻るボタンがある場合です。修正するボタンでは、前のページに戻ったときに入力した値が消えてしまうのは面倒なので、入力した値を引き継いだままに前のページに戻りたいですよね。その場合にformタグでくくる必要があります。

しかし、登録、修正ボタンともにformタグでくくり、postします。その場合に、モダンブラウザでの認識の仕方と、IE9でのフォームのレイアウトの違いがあります。

IE9での補完の違いによってレイアウトが崩れてしまう、具体的にいうと登録ボタンが上で、修正ボタンが段落ちします。ここで、元のソースコード、モダンブラウザでのformタグの認識、IE9でのformタグの認識と分けて紹介します。

レイアウトの関係上特殊なマークアップをあえてしてみた場合

元のマークアップ。少々特殊ですが、上記のようなレイアウトで、formタグを二つ含む場合、formタグを使って、JavaScriptを使用しない場合、特殊なDOM構造にする必要がありますよね。レイアウトを実現するために必要なdivタグの中に</form>があるのは非常に違和感があります。

<form action="/regist" method="post">
  <input type="hidden" id="lastName" name="lastName" value="田中">
  <input type="hidden" id="firstName" name="firstName" value="たなか">
  <input type="hidden" id="email" name="email" value="a@gmail.com">

  <div class="u-clearfix c-button-column-2">
    <p>
      <button type="submit" name="resistButton">登録する</button>
    </p>
    </form>
    <form action="/back" method="post">
      <input type="hidden" id="lastName" name="lastName" value="田中">
      <input type="hidden" id="firstName" name="firstName" value="たなか">
      <input type="hidden" id="email" name="email" value="a@gmail.com">
      <p>
        <button type="submit" name="return">修正する</button>
      </p>
    </form>
  </div>

続いてモダンブラウザでのDOM構造はどのようになっているのかみてみましょう。

モダンブラウザは良きように閉じタグが認識される

こちらはモダンブラウザのformタグの構造になっています。モダンブラウザでは勝手にformタグでformタグがラッピングされるような構造として補完されています。formタグの入れ子構造になっていても登録、修正の挙動に問題がないのはモダンブラウザだからでしょうか。

<form action="/register" method="post">
	<div class="u-clearfix c-button-column-2">
		<input type="hidden" id="lastName" name="lastName" value="田中">
		<input type="hidden" id="firstName" name="firstName" value="たなか">
		<input type="hidden" id="email" name="email" value="a@gmail.com">
		<p>
			<button type="submit">登録する</button>
		</p>
		<form action="/back" method="post">
			<input type="hidden" name="_csrf" value="">
			<input type="hidden" id="lastName" name="lastName" value="田中">
			<input type="hidden" id="firstName name="firstName" value="たなか">
			<input type="hidden" id="email" name="email" value="a@gmail.com">
			<p>
			<button type="submit" name="return">修正する</button>
			</p>
		</form>
	</div>
</form>

これがモダンブラウザではformタグで全体を囲うように補完されているので、本来formタグの入れ子構造はあまりよくありませんが、挙動に問題はないようです。
しかし、これがIEでは違う補完のされ方になります。これが今回ボタンのレイアウトが崩れてしまう要因になっていました。

IE9ではformタグの閉じタグの認識が異なる

上記のフォームがIE9では下記のようにformタグと、<div class="u-clearfix c-button-column-2">が勝手に補強されているのです。その結果u-clearfixによって横長並びになっていたボタンが上下に崩れてしまうという問題が発生します。

formタグの入れ子構造のマークアップになってしまっているモダンブラウザの方も、本来意図しているマークアップではないですが、モダンブラウザ(スマートフォン端末を含む)では、formタグの入れ子構造になっていても登録、修正が行えています。なのでモダンブラウザだけでデバッグをしているとIEのレイアウト崩れに気づきません。

<form action="/register" method="post">
	<div class="u-clearfix c-button-column-2">
		<input type="hidden" id="lastName" name="lastName" value="田中">
		<input type="hidden" id="firstName" name="firstName" value="たなか">
		<input type="hidden" id="email" name="email" value="a@gmail.com">
		<p>
			<button type="submit">登録する</button>
		</p>
    </div>
</form>
<div class="u-clearfix c-button-column-2">
  <form action="/back" method="post">
    <input type="hidden" name="_csrf" value="">
    <input type="hidden" id="lastName" name="lastName" value="田中">
    <input type="hidden" id="firstName" name="firstName" value="たなか">
    <input type="hidden" id="email" name="email" value="a@gmail.com">
    <p>
    <button type="submit" name="return">修正する</button>
    </p>
  </form>
</div>

IEだとなんで逆にここまで高性能な補完のされ方になるのか気になるところですが、それが仇となってレイアウトが崩れてしまいます。ですからformタグの入れ子構造を変えてあげなければなりません。

この場合のformタグの構造の解決策1

少しハック的な方法になってしまいますが、formタグのマークアップの方法を変更して、JavaScriptを用いて、入力している値を登録ボタンを押した時に一緒に値を送るようにします。

このコーディングの組み方だとformタグの上に入力するためのinputタグがある場合、その値がうまくpostされません。なので、その値をJavaScriptでhiddenにしているinputタグのvalueに入れてあげてpostして解決しました。レイアウトを実現して、戻った時にも値を引き継いでユーザーに負荷をかけないためには裏側で細かい配慮が必要ですね。


<input type="text" placeholder="何かテキスト入れるフォームがある" />

<form action="/regist" method="post" id="js-submit-btn">

  <#-- IE9フォームのレイアウトの調整のためhiddenにしておいて入力値をvalueに挿入 -->
  <input "class='js-form-input' style='display:none;'"/>

  &lt;input type="hidden" name="_csrf" value=""&gt;
  &lt;input type="hidden" id="lastName" name="lastName" value="田中"&gt;
  &lt;input type="hidden" id="firstName" name="firstName" value="たなか"&gt;
  &lt;input type="hidden" id="email" name="email" value="a@gmail.com"&gt;

  <p class="c-btn c-btn--primary c-btn--ws u-fl-r">
    <button type="submit" class="c-btn--ws c-btn__link-item" name="resistButton">登録する</button>
  </p>
</form>
<form action="/back" method="post">
  &lt;input type="hidden" name="_csrf" value=""&gt;
  &lt;input type="hidden" id="lastName" name="lastName" value="田中"&gt;
  &lt;input type="hidden" id="firstName" name="firstName" value="たなか"&gt;
  &lt;input type="hidden" id="email" name="email" value="a@gmail.com"&gt;
  <p class="c-btn-prev c-btn--ws u-fl-l">
    <button type="submit" name="return">修正する</button>
  </p>
</form>

IE対応は大変だけど面白い

開発しているサービスでは、IEの利用比率が高く、全体の20%程度のユーザーが使っていることもあって対応することになりました。IEでデバックするのは大変なのでモダンブラウザで開発しているという方が多いかと思いますが、最終的にリリース前に確認のために見てみたら、愕然とした。。ということもあるかと思います。

あらかじめブラウザごとの違いを認識しながらコーディングをしておくと最終的に修正する項目が少なくて済みますので、自分の中でIE対策のTipsを貯めて置きたいですよね。

今回はformタグの例を元に、モダンブラウザとIEでのレイアウトや補完されるDOMの違いについてご紹介しました。

プログラミングやコーディングで悩んだときに相談できるサイトについてこちらにまとめてみました。
1日悩んでしまうのであれば、自分で調べつつ質問をしておいて回答がきたら参考にするというのも手です。
特にクライアントワークだと時間も限られているので、おすすめします。