ボックスモデル

XUL をマスターするには、そのボックスモデルをよく理解しておく必要があります。これは、XUL ドキュメント内におけるすべての要素の視覚的なレイアウトを決定するシステムです。異なるオペレーティングシステムや画面サイズと解像度で簡単にローカライズやスキンを施せるインタフェースを作成するために、どのように作用するかを知っておくことが重要です。

XUL のボックスモデルには、垂直指向の HTML レイアウトモデルと比べて数多くの改善点があります。XUL では、垂直指向だけでなく、水平指向のレイアウトも定義でき、インタフェースデザインに優れた柔軟性を提供しています。

XUL インタフェースは、次の基本的なコンポーネントに分けられます:

  • ボックス
  • テキスト
  • 画像
  • 整列と伸縮自在な配置
  • 幅と高さ
  • マージンとパディング

メニューやツールバー、ボタンなど、XUL におけるほとんどの複雑な要素は、これらの単純な構成要素からできています。複雑な要素は、後で取り上げる XBL を通して、単純なものから作成されます。この単純な考え方を理解しさえすれば、DOM インスペクタ と CSS を使用して XUL 要素を形作り、とても分かりやすく柔軟なレイアウトを作成できるようになるでしょう。

このセクションで紹介するほとんどの例は、XUL Box Alignment Example を使用して作られています。これらの例で、ボックスモデルの基本的なパーツがどのように振る舞うかを試すことをお勧めします。

ボックス

XUL のボックスは、HTML の <div> とよく似ています。これは、スタイル付けが無い、不可視の四角形のコンテナです (div にはデフォルトのスタイルがあります)。両者の振る舞いは似ていますが、XUL と HTML の根本的な違いの一つに、XUL のボックスは垂直指向と水平指向の両方のインタフェースがデザインできることがあります (div は垂直指向のみ)。

XUL には、hbox および vboxbox の 3 つの基本的なボックス要素があります。hbox 要素は、デフォルトで、その子ノードが左から右へ順に表示される水平指向のレイアウトになります。vbox 要素は、デフォルトで、その子ノードが上から下へ順に表示される垂直指向のレイアウトになります。box 要素は、どちらにでも指定できる一般的なバージョンですが、デフォルトで水平指向のレイアウトになります。 hbox とほとんど同じなので、あまり使用されません。

以下は、3 個のボタンを持つ hbox のとても単純な例です:

<hbox>
  <button label="Cat" />
  <button label="Parrot" />
  <button label="Porcupine" />
</hbox>

これは、Mac OS での外観です (黒の枠線を追加しています。デフォルトでは、ボックスにはありません):

代わりに vbox を使用すると次のようになります:

ボックス (および他の XUL 要素) の指向性は、orient 属性か -moz-box-orient CSS プロパティを使用して制御することができます。これらを使用すると hbox を垂直指向にしたり vbox を水平指向にしたりできますが、ほとんど役に立ちません。CSS プロパティは場合によって役に立つことがあるかもしれませんが、orient 属性は、コンテンツと体裁を同じところに記述することになるのでお勧めできません。

伸縮自在な配置

HTML の div は、CSS で寸法を指定しなければ、そのコンテンツと同じ大きさになります。これは XUL でも同様です。ただし、XUL の場合は 2 つの方向を考慮しなければなりません。hbox は、そのコンテンツの水平方向と同じ幅になりますが、利用可能な垂直方向のスペースをすべて占有します。hbox を水平方向に伸縮自在にするには、CSS プロパティの -moz-box-flex か、flex 属性を使用してください。これは、vbox における垂直方向にも同様に適用されます。

通常の style 属性と異なり、flex 属性は、XUL コード内で使用されることが想定されています。この属性は頻繁に使用されます。この属性を使用しなければ、多くの CSS コードを記述する必要があるでしょう。いずれにせよ、いつでも CSS で上書きできるため、あなたの拡張機能のスキンが失われることはありません。

伸縮自在な配置は数値で定義されます。ほとんどの要素のデフォルト値は 0 です。この値は、要素がその方向に引き伸ばされず、そのサイズは要素のコンテンツとパディングにより決定されることを意味します。要素を伸縮自在にしたいときは、この値を 1 に設定してください。この値に設定すると、要素が引き伸ばされる方向の利用可能なスペースを占有します。最初の例の hbox を伸縮自在にすると、次のようになります:

ボックスは、水平方向の空いたスペースを覆うように引き伸ばされます。ボタンは元のサイズを保っています。

ここで、"Cat" ボタンを伸縮自在にすると、次のようになります:

伸縮自在にしたボタンが利用可能な内部のスペースを占め、他の 2 個のボタンはボックスの末尾まで移動しました。

"Parrot" ボタンも伸縮自在にするとどうなるでしょうか?

両方のボタンの値が 1 に設定されているため、利用可能なスペースが 2 個のボタンに均等に与えられました。ただし、常にこうなるとは限らないので注意してください。ボタンの一つが、その最小サイズよりも長いラベルを持っていた場合、そのボタンのサイズはラベルの長さに合わせられます。他のボタンは、残りのスペースを与えられます。

伸縮自在な要素を異なるサイズにしたいときは、1 よりも大きな値を設定してください。

上図では、"Cat" ボタンの flex 属性の値は 3、"Parrot" ボタンの flex 属性の値は 1 に設定しています。値が 3 に設定された "Cat" ボタンが 1 よりも長くなりました。ここでも、要素のコンテンツによって長さが変わることに注意してください。この例では、ボタン内のラベルとパディングのサイズに依存します。"Parrot" ボタンのラベルがもっと長かった場合、サイズの比率は維持されません。

伸縮自在な要素のサイズをさらに制御することができます。minwidthmaxwidth, minheight, maxheight 属性を使用するか、これらに相当する CSS の min-widthmax-width, min-height, max-height を使用してください。chrome の skin セクションの style コードを維持するため、後者の使用が推奨されます。これらの名前からも分かる通り、要素が大きすぎたり小さすぎたりしないように、引き延ばす範囲を制御できます。

すべての CSS プロパティによる長さは、注意して扱わなければなりません。可能な限り、絶対単位 (px) ではなく、相対単位 (em, %) を使用することをお勧めします。相対単位を使用すれば、アクセシビリティに制限のあるユーザによりフォントサイズが変更されていても、その設定に比例して UI のサイズが変更されます。この規則の一般的な例外は、CSS が画像と直接関連しており、ピクセル単位 (px) で扱う必要がある場合です。

また、HTML のように、固定サイズの要素も、widthheight CSS プロパティまたは属性を使用して制御できます。これらの属性は、伸縮自在な要素には適用されません。

マージンとパディング、スペース

マージン (外側の余白) とパディング (内側の余白) は、要素間のスペースや要素の内側のスペースを定義するために、HTML と XUL の両方で頻繁に使用されます。margin は、要素とその周りの要素の間のスペースを決定し、padding は、コンテナ要素の境界とその子ノードの間のスペースを決定します。

時には、要素の間に伸縮自在のスペースを定義する必要があるでしょう。この場合は、spacer 要素に flex 値を指定して使用してください。spacer 要素は完全に不可視で、スペースを空けることしかしません。これは、伸縮自在のスペースが必要な時にだけ使用してください。固定サイズのスペースが必要な場合は、マージンやパディングを使用し、XUL ドキュメントに不要なノードを追加することは避けてください。

整列

XUL は、HTML と異なり、要素を水平方向や垂直方向に整列させる簡単な方法を提供しています。align 属性と pack 属性、または CSS プロパティの -moz-box-align-moz-box-pack のどちらかを使用できます。pack は、コンテナの指向する方向における子要素の配置を決定します。aline は、もう一方の方向における配置を決定します。伸縮自在な hbox の align を center に、pack を end に設定すると、次のようになります:

要素の整列と伸縮自在な配置は合わせて使用できない場合があるので、特に注意してください。ボタンの一つを伸縮自在にした場合、pack を使用しても役に立ちませんが、align は役立ちます。また、垂直方向に利用可能なスペースが無かったとしても、flex や pack を hbox に使用しても意味がありません。コンテナ要素自身が伸縮自在であるか、そのコンテンツよりも固定幅が大きな必要があるからです。

テキスト

テキストを表示するために使用される XUL 要素は、labeldescription の 2 つがあります。これらはほとんど同じ振る舞いをしますが、異なる状況で使用されます。

label 要素は、主に、Firefox の設定ウィンドウで見られるような XUL フォーム内のテキストに使用します。次のコードは、label 要素の一般的な使用例です:

<label control="xulschoolhello-gretting-textbox"
  value="&xulschoolhello.typeGreeting.label;" />
<textbox id="xulschoolhello-gretting-textbox" />

label は、"Type a greeting message" のテキスト、次の textbox は、ユーザがメッセージを入力するフォームです。control 属性は、label を textbox へリンクします。ユーザが label 部分のテキストをクリックすると、textbox にフォーカスが移動します。また、ユーザがスクリーンリーダを使用している場合は、textbox にフォーカスが置かれると label のテキストが読み上げられます。

description 要素は、テキストが説明のための情報のみであることを意味し、フォームなどの入力要素と関連付けられていない場合に使用されます。

XUL でテキストを扱うことは簡単に思われますが、実際はかなり扱いにくい対象です。他の言語にローカライズされた文字列が元の文字列よりも長くなることを、常に心に留めておかなければなりません。特に、英語の文字列よりも長くなります。また、長いテキストブロックの使用や、テキストの長さに合わせた UI の設計は避けてください。テキストがとても長くなること、UI が適応しなければならないことを常に心に留めてください。

label は短くし、一行で表示されるようにすべきです。また、description は長くなることがあるので、複数行になってもすべて表示されるようにすべきです。description のテキストが折り返されるようにするには、テキストを、value 属性を使用せずに、要素の子ノードとして記述してください:

<description>&xulschoolhello.description.label;</description>

このように記述しても、テキストは一行に入る分まで幅が広くなります。XUL ダイアログやウィンドウの内部で折り返す幅を指定するには、CSS を追加する必要があります。description の幅を制限するには、CSS プロパティの width を使用してください。指定した幅でテキストが折り返されます。

折り返す位置を合わせるためにテキストを複数の locale 文字列に分けてはいけません。一つのテキストを分けると、ローカライズを難しくしたり不可能にする場合があります。

テキストの折り返しが description では不十分な、さらに複雑な状況もあります。例えば、templates には description 要素のようにテキストを置けないため、テキストが正しく折り返されません。この問題の回避策は、代わりに textbox 要素を使用することです。 XUL Solutions のブログ記事で、このテキストの折り返しについてのガイドがあります。高等なテキストの扱い方をする場合は、これらのことを心に留めておいてください。

長すぎるテキストを扱うもう一つの方法は、crop 属性を使用することです。テキストが、そのコンテナが許容するより長い場合は、超過した分が切り取られ、省略記号 "..." に置き換えられます。テキストを切り取る部分を選べますが、通常はテキストの末尾を切り取るため end を指定します。テキストの折り返しと似ていますが、crop は、テキストを表示するスペースが無い場合にのみ効果があります。そのため、CSS で幅を制限する必要があるでしょう。

XUL では、とても簡単に label にリンクを作成することができます。必要なことは、label 要素に text-link クラスを設定し、onclick ハンドラを追加するだけです (oncommand では動作しません)。label がリンクと同じスタイルで表示されるため、ユーザは、それがリンクであることが分かるでしょう。

HTML のように一部分だけをクリック可能にする場合はコツが要ります。label はリッチテキストを扱うことができないため、対応策では JavaScript を使用しなければなりません。可能性の一つは、locale の properties ファイルで、リンクであることが分かるように特別なマークアップを使用することです:

xulschoolhello.linkedText.label = Go to <a>our site</a> for more information

この構文は HTML と似ているため読みやすいでしょう。しかし、この書き方では string budle は何もしません。正規表現を使用して文字列を分割し、3 つの異なる label を生成する必要があります。リンクとなる label には、text-link クラスを設定します。また、CSS を使用して分割したテキスト間のスペースを調整する必要があるでしょう。

もう一つの方法は、リンク部分を本物の HTML を使用してマークアップすることです。

xulschoolhello.linkedText.label = Go to <html:a onclick="%S">our site</html:a> for more information

XUL ドキュメントに HTML を含めるには、ドキュメントのルートに名前空間を追加する必要があります:

<overlay id="xulschoolhello-browser-overlay"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
  xmlns:html="http://www.w3.org/1999/xhtml">

こうすることで、properties ファイルの文字列をパースした結果が html:p (段落) 要素になります。また、DOMParser オブジェクトを使用して、XML を簡単にパースできます。

XUL ドキュメントは厳格な XML であるため、XUL 内では厳格 (strict) な XHTML しか使用できません。書式のいいかげんな HTML は使用できません。

練習問題

DOM インスペクタを使用して Firefox の chrome を調べてください。ツールバーボタンやメニュー項目、テキストボックスなどを選択し、ボックスモデル、CSS スタイル規則、計算されたスタイルビューを調べてください。計算された widthheight の値を調べ、パディングやマージンが XUL ノードの寸法にどのように影響しているか調べてください。

Hello World 拡張を変更し、CSS だけを使用して Firefox の外観を大胆に変更してください。ボタンのサイズや外観を変更したりツールバーやステータスバーの背景色を変更したり、フォントのスタイル、サイズなどを変更して遊んでみてください。これは、本来は拡張機能にさせる事ではなく、テーマで行うことなので注意してください。しかしながら、Firefox の外観を簡単に変更する方法が分かると、とても楽しいでしょう。

CSS に詳しくない場合は、このチュートリアルを進める前に、CSS の入門チュートリアルや他のオンライン上の解説をよく読んでください。

This tutorial was kindly donated to Mozilla by Appcoast.

ドキュメントのタグと貢献者

タグ: 
 このページの貢献者: ethertank, Marsf
 最終更新者: ethertank,