JavaScript で doctype を変える
- カテゴリ:
- HTML
- JavaScript
- コメント数:
- Comments: 0
◆ 「document.implementation.createDocumentType」 で作れる
◆ 「document.doctype」 と replace する
◆ 変えても互換(Quirks)モードか標準モードかは変わらない
◆ document.compatMode で確認できる
◆ document.write で新しく一から DOM を doctype 付きで作れば変えられる
◆ 「document.doctype」 と replace する
◆ 変えても互換(Quirks)モードか標準モードかは変わらない
◆ document.compatMode で確認できる
◆ document.write で新しく一から DOM を doctype 付きで作れば変えられる
doctype へアクセス
JavaScript で doctype を変えたくなったので調べてみましたdoctype は
document.doctype
でアクセスできます
プロパティを見ればそれぞれの情報が取得できます
document.doctype.name
// "html"
document.doctype.publicId
// "-//W3C//DTD XHTML 1.0 Transitional//EN"
document.doctype.systemId
// "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
// "html"
document.doctype.publicId
// "-//W3C//DTD XHTML 1.0 Transitional//EN"
document.doctype.systemId
// "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
でも変えることはできません
document.doctype.publicId
// "-//W3C//DTD HTML 4.01 Transitional//EN"
document.doctype.publicId = "-//W3C//DTD HTML 4.01//EN"
document.doctype.publicId
// "-//W3C//DTD HTML 4.01 Transitional//EN"
// "-//W3C//DTD HTML 4.01 Transitional//EN"
document.doctype.publicId = "-//W3C//DTD HTML 4.01//EN"
document.doctype.publicId
// "-//W3C//DTD HTML 4.01 Transitional//EN"
transitional なものを strict にしてみようとしましたがダメでした
doctype を変える
プロパティを変えれないなら doctype オブジェクトごと置き換えようと思ったのですが doctype って作れるものだっけ?作った記憶ないですし document のメソッドを調べてもそれらしいのはありません
ググってみるとこうやってできるみたいでした
var doctype = document.implementation.createDocumentType("html", "", "")
document.doctype.replaceWith(doctype)
document.doctype.replaceWith(doctype)
これはすでにある場合に置き換える方法で doctype 宣言がない場合には append (prepend) します
※ Chrome は append で body の後ろに doctype 置くこともできますが Firefox はエラーでした
var doctype = document.implementation.createDocumentType("html", "", "")
document.append(doctype)
document.append(doctype)
本当にやりたかったこと
上の方法で doctype は変わりましたdoctype は
ただやりたかったのは 「本当に doctype を変えるだけ」 じゃないんです
実際に変えても何も変化がないですし
transitional と strict のモードで HTML や CSS の挙動が変わるので strict モードに切り替えたいというのが目的です
特に about:blank で画面作ってると 互換モードになってるので HTML5 の doctype 付きのページに移植すると動かなかったりもします
html と body にも height の 100% が必要とか単位 px が必要とか
Quirks モード
HTML/CSS の解釈の違いなどのモードの違いは doctype が strict か transitional かの違いで決まってると思ってたのですが 調べてみると正確には違うようでしたtransitional かつ URL がない場合に互換モードになるようです
もちろん doctype 自体がない場合もです
またこの互換モードには Quirks モードという名前がついてるようです
互換モードを調べていると 標準と互換モードの違いに 上で書いた「height の 100%」と「単位 (px など) が必要」以外にこんなものがありました
- フォントサイズが small がデフォルトサイズになる
- margin を auto にしてもセンタリングしない
- デフォルトの box-sizing が border-box
これらは doctype 調べてるときにも見かけますし 昔 doctype を調べてた頃に サイズに padding が含んだり含まれなかったりで困った覚えがありますし フォントサイズの small や medium の指定がページによってサイズが違ってた覚えがあります
ですが URL なしの HTML4.01 のページや doctype なしの about:blank で試してもこれらの特徴は起きませんでした
フォントサイズを small にするとデフォルトより縮みますし margin:auto をつければセンタリングしますし width に padding は含みません
Chrome だけでなく Firefox も一緒でした
MDN には違いをまとめたページがあり ここではフォントサイズが違ったり margin が auto になるとは書かれていません
box-sizing は input と textarea でのみ適用されるようです
Quirks モードを変えたい
doctype を変えても 実際の挙動 (height: 100% など) は変わりませんでしたモードを確認する方法を調べてみると Firefox だと右クリックの 「ページの情報を表示」 からページ情報を開いて 描画モードを見ればわかります
後方互換モードと標準準拠モード | MDN
Quirks モードだと 「Quirks (後方互換) モード」
標準モードだと「Standards Compliant (標準準拠) モード」
と表示されます
Chrome だとこういう確認はできないみたいですが JavaScript でモードが取得できました
document.compatMode | MDN
document.doctype
// <!DOCTYPE html>
document.compatMode
// "CSS1Compat"
// <!DOCTYPE html>
document.compatMode
// "CSS1Compat"
document.doctype
// null
document.compatMode
// "BackCompat"
// null
document.compatMode
// "BackCompat"
もしかすると ここを変えるとモードが変わったり?
やってみると読み取り専用らしく 代入しても変化ありませんでした
なんとなくそんな気はしてましたけどね
document 全体を新しく作るしかないみたい
doctype を置き換えたあとに html 要素から全部を置き換えてみたり display: none にして戻してみたり試したのですが 全然ダメでしたStackOverlow を見てみると document を再び open して作り直す方法が紹介されていました
他に方法なさそうですし この方法しかなさそうです
document.write("<!doctype html>\n" + document.documentElement.outerHTML)
やってみると element タブで確認して doctype が表示されていて compatMode も CSS1Compat になっていました
特徴も標準モードのものになっています
ただ この方法は document を開いて HTML を再度パースして DOM を構築しています
html 要素の outerElement を使うので DOM の構造や各要素の属性は一緒になりますが script タグは再び実行されますし 構造は一緒でも各要素は別物になるので 変数に保存していた要素や 要素のプロパティに保存していた値は使えなくなります
about:blank を使う時最初に実行する使い方なら問題ないですが 既存ページに使うのは問題がでるかもしれません
ところで transitional がよく traditional になってしまいます
似てる上に 言葉としても 古いものだから traditional で自然なのであまり違和感ないんですよね