$("div").append("section") できないらしいので色々調べてみた
追記: jQ的には解決していませんが、素の JavaScript を使った回避方法がわかりました。IE8以下では、オンザフライで作成した要素に対して innerHTML すると謎要素が作成されてしまうといった現象がでるため、一度要素片を、DOMツリー( body とかね ) にぶらさげてから innerHTML すると回避できました。
つまり、オンザフライな↓ではだめで… var div = document.createElement("div"); // 作る div.innerHTML = "<section>ほげー</section>"; // 突っ込む → ι(´Д`υ) ↓のようにすると謎の挙動を回避できます。 var div = document.createElement("div"); // 作る document.body.appendChild(div); // あてがう div.innerHTML = "<section>いけたー</section>"; // 突っ込む → ヽ(・ω・)ゝ createDocumentFragment() を使っても、オンザフライなノードに突っ込むと、同様に謎の挙動が発生します。 node.cloneNode() は、nodeがオンザフライかどうかに関わらず、謎の <:section> ノードを生成するため、 CSSを適用したい場合は、 section { ... } と記述するだけだとだめで、 section, \:section { ... } と併記する必要があります。 \:section を併記すると IE8 でスタイルが適用されます(IE6, IE7 では適用されません)。
文章で書くとよくわからないと思いますがコードにすると↓こんな感じです。
<!DOCTYPE html><html lang="ja"><head><meta charset="utf-8" /> <title></title></head><body> <style> section { color:blue;outline:2px solid blue } \:section { color:pink;outline:2px solid pink } /* IE8で<:section>に適用される, IE6, IE7には適用されない */ \\:section { color:red; outline:2px solid red } /* IE6, IE7, IE8 には適用されない */ </style> <script> document.createElement("section"); // HTML5 siv var div = document.createElement("div"); // 作る div.innerHTML = "<section>ほげー</section>"; document.body.appendChild(div); // あてがう → ι(´Д`υ) var div2 = document.createElement("div"); // 作る document.body.appendChild(div2); // あてがう div2.innerHTML = "<section>いけたー</section>"; // ヽ(・ω・)ゝ var div3 = div2.cloneNode(true); document.body.appendChild(div3); alert(div3.outerHTML); // ※ // ※ // IE9 では <div><section>いけたー</section></div> // IE8 では <DIV><:section>いけたー</:section></DIV> // IE7 では <DIV><:section>いけたー</:section></DIV> // IE6 では <DIV><:section>いけたー</:section></DIV> // IE9(IE7互換mode) では <DIV><section>いけたー</section></DIV> // IE9(IE8互換mode) では <DIV><section>いけたー</section></DIV> </script> </body></html>
IE9 の IE7,IE8 互換モードは実際の IE7,IE8 と細かな挙動が異なるのです、いっぱいあって説明する時間も気力もないのですが、ひとつ言えることは、「HTML5 に対応しました。(IE9 の互換モードで)確認もしました(ドヤ)」する人は、もれなく罠にはまるといいよ!
ここまで追記
ここから本文
@hokaccha さんのツイートを見て気になったので、
$('div').append('
hoge '); とかしたときIEでstyleが効かなくなる件jQuery1.5になったら対応してくれるかなと思ったけど、試してみたらダメだった。
IE6〜IE8 で HTML5 で追加された新要素(この場合は section) を jQuery で追加するとスタイルが適用されない問題があるらしい。
jQuery で試してみた
jQuery の最新版(1.5)で http://jsdo.it/uupaa/createHTML5ElementByjQuery 試してみた。
<script> var css = "div{border-top:1px solid blue}"; document.createElement("section"); // HTML5 shiv $(function() { $("head").append("<style>" + css + "</style>"); $("div").append("<section>section</section>"); }); </script> <style> section, \:section { display:block;border-top:1px solid red } </style> <div>div</div> <div>div</div>
uupaa.js で試してみた
uupaa.js の最新版で http://jsdo.it/uupaa/createHTML5ElementByuu 試してみた。
<script> var css = "div{border-top:1px solid blue}"; uu.ready(function() { uu.head(uu.style(css)); uu("div").add(uu.section("section")); }); </script> <style> section, \:section { display:block;border-top:1px solid red } </style> <div>div</div> <div>div</div>
IEのinnerHTMLとcloneNodeの不具合を調査している時に、
IE6〜IE8で(
… ).cloneNode(true)で生成せした要素にスタイルが当たらなくなるのは、 クローンで作成したノードがチラ見だとにみえて実は<:section>要素になっているため。 http://twitter.com/#!/uupaa/status/34544812854091776
- -
jsからは
のようにみえて、実はouterHTMLすると<:section>なので、CSSが当らないし、IEは仲間を呼んだ。爆弾岩が現れた。IEはぱるぷんてを唱えた。みたいなDOMツリーになる http://twitter.com/#!/uupaa/status/34545606823256064
- -
cloneNode()せずにNodeの属性を正確に素早くコピーする方法はない。cloneNodeすると
が<:section>になる。outerHTMLに" hoge "突っ込むとDOMツリーの親子関係ぶっこわれ3つのノードができる。手詰まりhttp://twitter.com/#!/uupaa/status/34555491514322944
- -
IEで
.cloneNode() した要素にCSSを当てるには \:section { display:block;border-top:1px solid red } のように \:section な感じで先頭にバクスラでエスケープいれればOK
と色々と無駄知識が手に入ったので、
このデモでは、CSSに section と一緒に \:section を併記し、ライブラリ内部でcloneNodeされている要素にもスタイルが適用されるようにしてあります(結局逃げてますが)。
実行結果
IE8 + jQuery
IE8 + uupaa.js
jQueryの場合、画像のように DOM ツリー構造がそもそも壊れちゃってて、
<div> 文字列 <section> 文字列 </section> </div>
のように、本来は2つあれば十分なはずの div 要素の子要素が4つもある。
この状態だとスタイルも適用されなかったんだけど…
どうせ、皆さんが使っているjQuery使えば対策済みですから大丈夫ですよ
HTML5の新要素をinnerHTMLで生成できないバグを回避する - latest log http://htn.to/9wkfZg
ってブクマが今朝のエントリに書かれてたのが気になる。
何か特別な方法があるのかもしれないんだけど、jQユーザではないのでよくわからず。
uupaa.js でも、コードを一部入れ替えると、jQueryのように壊れたDOMツリーが生成されてしまう。
// uu("div").add(uu.section("section")); // cloneNode でノードをノードとしてコピーする uu("div").add("<section>section</section>"); // innerHTML でノードを文字列としてコピーする
uu.section() でノードを作る場合は、内部で cloneNode が走るので被害を最小限にできるんだけど、
uu.node("
今のところ、innerHTML で親子関係が崩れる問題をどうにかする良い方法は見つかってない。IE6〜IE8のバグ由来の仕様という認識。
お願い
uupaa.jsで、HTML5で追加された要素を作成する時は、uu.add("
その際に、CSS には \:section や \:aside など cloneNode で生成される特殊な要素に対するスタイルも併記してください。
よろしくお願いします。
CSSの\:sectionの話については、こちらをどうぞ http://jsdo.it/uupaa/IEcloneNodeBug (HTML5の新要素をcloneNodeするとCSSが適用されないバグを対策する)