IE8以下におけるiframeの境界線(frameborder)問題
Updated / Published
IE8以下でiframe
要素が生成するインラインフレームの境界線を非表示にするにはCSSのborder
関連プロパティで代替できないため、HTML上で直接frameborder="0"
の指定が必須なのは既知のことでしょうが、いざJavaScriptから動的に境界線の非表示を操作しようとすると思わぬどはまりをしたので、同じようなことをしようとした人が今後いたときのために備忘録を残しておきます。
先に結論から書くと、IE8以下ではiframe
要素が生成するインラインフレームの境界線を動的に操作することはできません。この点を踏まえた上で様々なアプローチを試みた結果を記します。
問題点
まず、IE8以下では、ボーダー領域とは別の領域でインラインフレームの境界線をレンダリングしているためCSSのborder
関連プロパティでは代替できないようになっており、この境界線を非表示にできるのが唯一frameborder
属性を用いてframeborder="0"
を指定した場合だけです。
しかしHTML5では、frameborder
属性が廃止となったため、HTML5のドキュメント上でframeborder
属性を用いることは、Valid(正当)ではありません。もちろんブラウザをはじめとしたソフトウェアの多くは寛容に作られているので、Invalidであっても、処理できなくなったり、表示されなくなるなどのクリティカルな問題が発生するわけではありませんが、このframeborder
属性を指定していることのみがInvalidの要因となるのであれば、制作者としては残念な気持ちになります。
IE8以下にのみframeborder
属性の付与を試みる
先の問題点を踏まえて、問題となるIE8以下にのみframeborder
属性を付与してみます。
<iframe src="sample.html" id="sample"></iframe>
<script>
if( !window.addEventListener ) {
var iframe = document.getElementById("sample");
iframe.frameBorder = 0; //または iframe.setAttribute("frameBorder","0"); でも可
}
</script>
最初にwindow.addEventListene
をサポートしているかを条件にIE8以下を対象にします。
JavaScriptではHTMLオブジェクトがframe
要素またはiframe
要素の場合、frameBorder
プロパティの指定が可能です。これはsetAttribute
プロパティで設定しても同様です。ただし、setAttribute
プロパティを用いる場合は、IE8以下独自の問題でframeBorder
とBだけ大文字で記述する必要があるようです。IE8ではsetAttribute('frameborder','0')
と記述しても自動的にBだけ大文字に変換する不思議な仕組みになっています。
上記の結果は、開発ツール上ではframeBorder="0"
が付与されていることが確認できますが、残念ながら境界線は非表示にはなりませんでした。
インラインフレーム自体の生成をJavaScriptで試みる
IE8以下にのみframeborder
属性の付与を試みる方法では、境界線を非表示にすることができなかったのですが、次の2通りのコードを書き分けることで、先ほどの結果がなぜ非表示にならなかったのかの原因が判明しました。
<div id="here"></div>
<script>
if( !window.addEventListener ) {
var iframe = document.createElement("iframe");
iframe.src = "sample.html";
iframe.id = "sample";
iframe.frameBorder = 0;
document.getElementById("here").appendChild(iframe);
}
</script>
この結果は、期待通り境界線が非表示になりました。次に試しにドキュメント上にインラインフレームを追加した後からframeborder
属性の付与を試みると、生成されたインラインフレームがframeBorder="0"
をもっていても境界線は表示されたままになります。
<div id="here"></div>
<script>
if( !window.addEventListener ) {
var iframe = document.createElement("iframe");
iframe.src = "sample.html";
iframe.id = "sample";
document.getElementById("here").appendChild(iframe);
iframe.frameBorder = 0; //ドキュメント追加後に指定
}
</script>
これらの結果から言えることは、IE8以下ではどうやら既にドキュメント上に存在しているインラインフレームにframeborder
属性を付与しても境界線を動的に操作することはできないようです。
一度削除してから再度インラインフレームを生成する
IE8のためだけにインラインフレーム自体の生成をJavaScriptに依存させてしまうのは他のブラウザにまで余計な処理をさせることになり不本意なので、IE8以下にだけ既にHTML上に存在しているインラインフレームを削除してから、再度境界線が非表示にできるようにインラインフレームの生成を試みてみます。
<iframe src="sample.html" id="sample"></iframe>
<script>
if( !window.addEventListener ) {
var iframe = document.getElementById("sample");
var parent = iframe.parentNode;
parent.removeChild(iframe);
iframe = document.createElement("iframe");
iframe.src = "sample.html";
iframe.id = "sample";
iframe.frameBorder = 0;
parent.appendChild(iframe);
}
</script>
この結果は、期待通り境界線が非表示になりましたが、今度はインラインフレーム内のドキュメントにスタイルシートが正常に適用されないという別の問題が発生してしまいました。一体どうなっているのやら、本当に変なブラウザです。
コンディショナルコメントに頼る
最後にIE9以下が独自にサポートしているIEコンディショナルコメントに頼ってみました。IE8以下以外のブラウザでは直接iframe
要素を記述してインラインフレームを生成し、IE8以下ではインラインフレーム自体の生成をJavaScriptに依存させることにしました。
<div id="here"><!--[if (gt IE 8)|!(IE)]><!--><iframe src="sample.html" id="sample"></iframe><!--<![endif]--></div>
<script>
if( !window.addEventListener ) {
var iframe = document.createElement("iframe");
iframe.src = "sample.html";
iframe.id = "sample";
iframe.frameBorder = 0;
document.getElementById("here").appendChild(iframe);
}
</script>
これであれば他のブラウザに影響を与えることなく、IE8でも期待通りインラインフレームの境界線を非表示にすることができました。でも、ただ文法上でValidにするために、独自のIEコンディショナルコメントを含めたりするのは本末転倒でここまでする意味が感じられないですよね。
結論
IE8以下でiframe
要素が生成するインラインフレームの境界線を非表示にする良い代替方法はありません。また、どこまでValid、Invalidに拘ったところで、よくあるソーシャルボタンなどもインラインフレームで埋め込まれるので、それら外部のWebアプリケーションもIE8以下で境界線を消すためにframeborder="0"
が指定されており、HTML5のドキュメントであれば自ずとInvalidということになります。iframe
要素のframeborder
属性以外にも外部のWebアプリケーションを埋め込むと強制的にInvalidになる要因は後をたちませんから、Validを追求することにも無理があると結論付けざるをえないでしょう。