HTML要素の中には、iframes、アプレット、埋め込みオブジェクト、フォームといった、フロントエンド開発者を悩ませる要素があります。ブラウザーやOSによって表示結果が異なるので、完全な調整が難しいのです。
jQureryUIからBootstrapまで、さまざまなライブラリーやフレームワークを使えば、要素を置き換えることができます。
ところで、開発者を悩ませるこれらのHTML要素は、なぜブラウザーやOSによって表示が異なるのでしょうか? W3Cのあいまいな定義が原因との指摘もありますが、正しいのでしょうか?
今回の記事で探索するテーマが「置換要素」です。
置換要素とはなにか?
探検には、調査が重要です。まずは、仕様書で置換要素の定義を調べます。
置換要素は、イメージ、埋め込みドキュメント、アプレットなどのコンテンツをCSSフォーマットモデルのスコープ外で「ある要素」と定義します。たとえば、HTML IMG要素のコンテンツは「src」属性が指定する画像に置き換えます。置換要素には、固有の幅、固有の高さ、固有の比の内在的寸法を指定します。たとえば、ビットマップ画像は、絶対単位で指定された固有の幅と高さ(これらのデータから固有の比が計算できます)を指定します。一方、ブランクのHTMLドキュメントをはじめ内在的寸法の指定がないドキュメントもあります。
置換要素の一般的な説明が分かりました。仕様部分を詳しく調べる前に、「内在的寸法」を解説します。
内在的寸法とはなにか?
内在的寸法の定義は、「CSSイメージ値と置換コンテンツモジュール レベル3」を参照します。
内在的寸法は、固有の高さ、固有の幅、固有のアスペクト比(幅と高さの比)を意味します。オブジェクトにより、内在的寸法を持っていたり、いなかったりします。内在的寸法には、オブジェクトに推奨するサイズや元の大きさを指定します。オブジェクトが使われるコンテクストの関数ではありません。また、一般的にはCSSは内在的寸法を見出す方法について定義しません。
例を挙げます。
- 画像は3つの寸法=幅、高さ、アスペクト比のすべてを持ちます
- SVG画像はアスペクト比のみ持つことがあります。スケーリングが可能なので、幅や高さは1つの値に固定されません
- iframe要素で挿入される空のHTMLページは寸法を持ちません
これらの特性はお互いに関係しているので、2つのサイズ情報しか持たないオブジェクトはありません。2つあれば、自動的に3番目が決まります。
オブジェクトをページ内に配置すると、ドキュメントに内在的寸法を伝えて、適切に表示します。この情報はあとで有用ですが、ここまでにして、本題に戻ります。
実際の置換要素
置換要素の説明をするには、WHATWGのHTML Living Standard「レンダリング」セクションが必要です。仕様書を詳しく読むと、HTML要素には常に置換要素として働くものや、ある特定の状況下でしか置換要素にならないものもあり、複雑だと分かります。
Subsection 14.4を読めば、すべてのケースが理解できます。
埋め込みコンテンツ
はじめに紹介する置換要素は「埋め込みコンテンツ」です。ドキュメントに別のリソースをインポートする要素はすべて埋め込みコンテンツに含まれます。別のボキャブラリーからドキュメントに挿入されるコンテンツも埋め込みコンテンツです。外部からのリソースは、定義の要求にマッチする内在的寸法を持っています。
主要な要素は、embed、iframe、videoです。常に外部コンテンツをドキュメント中にインポートするため、常に置換要素として扱います。
以下の特殊な要素の場合は少々複雑です。
- applet:プラグインでは置換要素で、それ以外は通常の要素として扱います
- audio:「ユーザーインターフェイス要素を表に出す」ときだけ、置換要素として扱います。高さは約1行分で、幅はユーザーエージェントのインターフェイス機能を表示するのに必要なサイズとなります
- object:画像、プラグイン、ネストされたブラウジングコンテクストを表現する場合、置換要素として扱います(iframeに似ています)
- canvas:埋め込みコンテンツを示す場合(要素のビットマップを含む、あるいは要素と同じ内在的寸法を持つ透明な黒のビットマップを含む場合)に置換要素として扱います
これらの要素が使われるケースの詳細は、埋め込みコンテンツのためのWHATWGのレンダリングルールを参照してください。
画像
画像が適切に表示されるなら、img要素は画像の内在的寸法で置換要素として扱われています。画像には、type="image"が指定されたinput要素を含みます。
画像がページ上に表示されない場合は少し複雑です。ブラウザーが最終的に表示しようとした画像が存在しない場合は、要素が表現するテキスト(オプションでアイコンも追加できます)を置換要素として扱います。<input type="image">の場合は通常のボタンが代わりに表示されます。完全なルールと条件は、仕様書に記述されています。
置換要素のデフォルトサイズ
置換要素のwidth/heightプロパティは、ページに持ち込んだコンテンツの内在的寸法で決まります。iframeがブランクのHTMLページを読み込む場合など寸法が計算できないときは、視覚フォーマッティングモデルの詳細にあるように、ブラウザーはデフォルトルールに従います。ルールセットそのものは膨大で複雑です。「どうしてもうまくいかない」場合を扱います。
幅(width)が自動(auto)の計算値を持っているのに、1つも条件に合わない場合、幅(width)の値は300pxになります。300pxでは大きすぎるデバイスは、ユーザーエージェントの2:1のアスペクト比でデバイスにフィットする長方形の最大幅を使います。
高さ(height)が自動(auto)の計算値を持っているのに、1つも条件に合わない場合、高さ(height)は、2:1のアスペクト比を有し150pxを超えない範囲、かつ幅がデバイスの幅に収まる最大の長方形の高さを設定します。
これらは、次の3つの基本規則にまとめられます。
- オブジェクトにwidth、height、ratioの値があれば、使用します。
- オブジェクトにratioの値しかなければ、ratioの値を保ちつつ、幅と高さはautoを用います
- 寸法情報がなにも得られない場合は以下のどちらかを用います
- ビューポートが300pxより大きい場合は、width: 300px; height: 150px;を用います
- ビューポートが300pxより小さい場合は、幅と高さにはautoを用い、アスペクト比2:1を用います
ビットマップ画像は通常のサイズで表示され、SVGはアスペクト比を保持しつつ、スペース一杯に表示され、iframeはデフォルトの最大サイズ300×150になっているのが分かります。ビューポートを狭くすると、iframeは常に2:1のアスペクト比を保ちます。
まとめ
置換要素のリストです。
- 埋め込みコンテンツ:embed、iframe、videoは常に置換要素として扱います
- 埋め込みコンテンツ:applet、audio、 object、canvasは、ある特定の場合、置換要素として扱います
- 画像:適切にロードされ、ブラウザーに表示されるimgおよびinput type="image"は、置換要素として扱います
ほかのフォーム要素は…?
最初に紹介したとおり、ほかのタイプのフォーム要素も置換要素との誤解があるようです。確かに、スタイルや属性がなければ、フォーム要素はデフォルトの幅と高さで表示されます。ではフォーム要素は置換要素の要件を満たすのでしょうか。
答えは誤りです。HTML Living Standardの「レンダリング」セクション、「14.3 非置換要素」のサブセクションに「14.3.11 フォームコントロール」があります。多くの人が内在的寸法だと錯覚しているのは、次の行のせいでしょう。
フォームコントロールはそれぞれ、ウィジェットセクションに記述があります。コントロールがどんなものか分かります。
フォームパーツの表示がブラウザーやOSごとに大きく異なる理由です。
このセクションで定義した要素は、ガイドラインのさまざまな方法で表示します。ユーザーエージェントは、ウィジェットのプラットホーム・ネイティブな外観を実現できるように、CSSのappearanceプロパティを適切に設定するように推奨されます。アニメーションなどプラットホームに適したものを実装してください。
出典:14.5 Widgets > 14.5.1 Introduction
「プラットホーム・ネイティブのアピアランス(外観)」に、フォーム要素がブラウザーごと、OSごとに違う方法で実現される理由の説明があります。これらのウィジェットがどう表示されるかは、各ブラウザー固有の定義による、というわけです。
最後に
置換要素とフォームコントロールが混同される理由が理解できましたか。HTMLとCSSの仕様を詳しく見ると、HTML要素の異なったカテゴリーでは<input type="image">だけが置換要素です。
思い描いていた結末とは異なるかもしれませんが、HTMLのあまり知られていない部分の説明ができたと思います。
(原文:Replaced Elements in HTML: Myths and Realities)
[翻訳:関 宏也/編集:Livit]