このセクションでは、要素の位置とサイズの制御について見ていきます。
ボックス要素の配置
前のセクションでは、ボックス内部の要素を水平方向と垂直方向に配置する方法について学びました。 実際には、ボックス内での要素の位置やサイズをさらに細かく制御する必要がある場面も多いはずです。 これらについて説明をはじめる前に、まずボックスがどのように動作するのかを確認しておきます。
要素の位置は、その要素が置かれるボックスのレイアウトスタイルによって決定されます。 例えば、水平ボックス内のボタンの位置は、前にボタンがある場合その右側になります。 また、要素のサイズは、「その要素にとって必要なサイズ」と「明示的に指定されたサイズ」の 2 つの要因によって決まります。 まず「その要素にとって必要なサイズ」は、要素の中に何があるのかによって決まります。 例えば、ボタンの幅ならば、中のテキストの長さで決まることになります。
一般的に、要素はその内容を収めるために最低限必要な大きさになります。 または、テキスト入力欄 (
) のように、要素によっては、使用される際のデフォルトサイズを持っているものもあります。 ボックスは、中に置かれた要素を収めるのに十分な大きさになります。 例えば、内部に 3 つのボタンがある水平ボックスの場合、3 つのボタンの大きさに若干のパディングを加えた幅になります。textbox
この画像で、最初の 2 つのボタンは、テキストを置くのに適切なサイズになっています。 3 番目のボタンは他より大きいですが、これはより多くの内容が含まれているためです。 ボタンが置かれているボックスの幅は、ボタンの幅の合計にボタン間のパディングを加えたものです。 ボタンの高さも、テキストを置くのに適切なサイズになっています。
width 属性と height 属性
ウィンドウ内の要素のサイズを詳細に制御したい場合もあると思います。 要素のサイズを制御するための機能は数多くありますが、 手っ取り早い方法は、HTML の img
タグで行なうように、 要素に
と width
属性を追加することです。 以下に例を示します。height
<button label="OK" width="100" height="40"/>
しかしながら、この方法は推奨しません。 移植や流用性が低くなりますし、XUL ファイル中で指定されたサイズが適さないテーマ (スキン) があるかもしれないからです。 もっとよい方法は、HTML のスタイルシートと同様の動作をする、スタイルプロパティを使うことです。 サイズの指定には、以下の CSS プロパティが使えます。
2 つのプロパティを両方指定した場合、設定された幅と高さの要素が作られます。 どちらか一方のサイズプロパティしか指定しなかった場合は、他方は必要に応じて計算されます。 これらのスタイルプロパティによるサイズ指定の場合、数値の後に単位をつけて指定する必要があります。(例: 80px)
伸縮可能な要素
伸縮しない要素の場合、実際のサイズを計算するのは非常に簡単です。 要素の大きさは、幅や高さが指定されている場合、単純に指定された値に従います。 サイズが指定されなかった場合、要素のデフォルトサイズとして、その内容が適切に収まる大きさになります。 伸縮可能な要素の場合、サイズの算出は少々トリッキーです。
伸縮可能な要素とは、0 より大きな値に設定された
属性をもつ要素のことです。 以前のセクションで説明したとおり、伸縮可能な要素は使用できるスペースに応じたサイズに伸縮します。 デフォルトサイズについては、伸縮しない要素の場合と同様に計算されます。 下の例は、このことを示しています。flex
<window orient="horizontal" xmlns="https://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <hbox> <button label="Yes" flex="1"/> <button label="No"/> <button label="I really don't know one way or the other"/> </hbox> </window>
ウィンドウは、最初は前出の画像の場合と同様に表示されます。 最初の 2 つのボタンは、適切なデフォルト幅で、3 番目のボタンはラベルが長いために、より大きなサイズになります。 最初のボタンは伸縮可能であるように指定されており、3 つの要素はすべて同じボックス内に置かれています。 ボックスの幅は、3 つのボタンすべての幅の合計 (画像では約 430 ピクセル) に初期設定されます。
ウィンドウの幅を広げると、増えたスペースを割り振るために各要素が伸縮可能かどうかチェックされます。 この場合、最初のボタンだけが伸縮可能な要素ではありますが、このボタンが広がることはありません。 これは、ボタンが置かれているボックスが伸縮可能ではないことに起因しています。 つまり、伸縮しない要素は、利用できるスペースが増えてもサイズが変化することはないため、 結果として、その中に置かれたボタンも大きくなることができず、ウィンドウが広がってもボタンは広がらないことになります。
これを解決するには、ボックスも伸縮可能にする必要があります。 そうすれば、ウィンドウを広げて新たなスペースが発生した場合、ボックスがそのスペースを利用して大きくなります。 ボックスが広がったことにより、ボックス内にも新たなスペースが作られることになり、中の伸縮可能なボタンも、増えたスペースに応じた大きさになります。 このプロセスは、入れ子になっているボックス分、必要に応じて繰り返されます。
最小サイズと最大サイズを設定する
要素を、「指定のサイズ以上に大きくならない」または「指定サイズ以下に小さくならない」といったように、一定の範囲内でのみ伸縮可能であるように制約したい場合があるかもしれません。このためには、以下の 4 つの属性が使用できます。
minwidth
- 要素が取ることのできる最小の幅を指定します。
minheight
- 要素が取ることのできる最小の高さを指定します。
maxwidth
- 要素が取ることのできる最大の幅を指定します。
maxheight
- 要素が取ることのできる最大の高さを指定します。
上記の属性値は、常にピクセルで指定する必要があります。 同じ目的で、CSS の min-width
、min-height
、max-width
、max-height
の各プロパティも使用可能です。CSS のプロパティを使用する場合は、複数の単位が使用できるので、数値に単位をつけて指定します。
これらのプロパティは、伸縮可能な要素に対して指定された場合のみ意味を持ちます。 例えば、最大の高さを設定すると、伸縮可能なボタンは、指定された最大の高さまでしか広がることはありません。 ボタンが最大の高さになる大きさを越えてウィンドウを大きくすることはできますが、ボタンは、それ以上は広がりません。 ボタンが置かれているボックスにも最大の高さを設定していなければ、ボックスの方は広がり続けます。
2 つのボタンに設定された伸縮の割合が同じ場合、通常、2 つは増えたスペースを半分づつ分け合います。 一方のボタンに最大幅が設定されている場合、最大幅に達した以降は、もう一方のボタンのみが広がり続け、残りのスペースすべてを占めることになります。
ボックスに最大幅か最大の高さが指定されている場合、子要素はその最大サイズを超えて広がることはできません。 ボックスに最小幅か最小の高さが指定されている場合、子要素はその最小サイズを下回って小さくすることはできません。
幅と高さを設定する例
以下に、幅と高さを設定する例をいくつか示します。
<button label="1" style="width: 100px;"/> <button label="2" style="width: 100em; height: 10px;"/> <button label="3" flex="1" style="min-width: 50px;"/> <button label="4" flex="1" style="min-height: 2ex; max-width: 100px"/> <textbox flex="1" style="max-width: 10em;"/> <description style="max-width: 50px">This is some boring but simple wrapping text.</description>
- 例 1
- 最初のボタンは、100 ピクセル (px はピクセルの意味) の幅で表示されます。単位を付ける必要があります。つけないと width の指定は無視されます。
- 例 2
- 2 番目のボタンは 10 ピクセルの高さ、100 em (em は現在のフォントで、文字「m」の幅) の幅で表示されます。
- 例 3
- 3 番目のボタンは伸縮可能なので、ボタンが置かれているボックスのサイズに従って広がります。しかし、ボタンが 50 ピクセル以下に縮小することはありません。スペーサーなどその他の伸縮可能なコンポーネントが flex の割合を超えて残りのスペースを吸収します。
- 例 4
- 4 番目のボタンは伸縮可能ですが 2 ex (ex は現在のフォントで文字「x」の高さ) 以下の高さになったり 100 ピクセル以上の高さになることはありません。
- 例 5
- テキスト入力欄は伸縮可能ですが、10 em 以上に広がることはありません。em は、内部にテキストをもつ要素のサイズを指定する場合には、しばしば使用されます。em でテキスト入力欄のサイズを指定しておくと、フォントが変更されたとき、自動的に新しいフォントで指定された文字数が表示可能な大きさに変更されるため便利です。これは特大のフォントに変更された場合でも動作します。
- 例 6
-
要素は、最大幅が 50 ピクセルに制約されています。内部のテキストは、50 ピクセルを超えると、次の行に折り返されます。description
ファイル検索ダイアログの例
それでは、こうしたスタイルをいくつか、ファイル検索ダイアログに追加してみましょう。 テキスト入力欄をウィンドウ全体に応じたサイズになるようにします。
<textbox id="find-text" flex="1" style="min-width: 15em;"/>
ここで、テキスト入力欄は伸縮可能に設定されています。 このため、利用者がダイアログのサイズを変更すると、あわせて伸縮します。 これは、利用者が長いテキスト文字列を入力したい場合に便利です。 また、テキスト入力欄に、少なくとも 15 文字は表示されるように、最小幅として 15 em が設定されています。 利用者がダイアログを非常に小さいサイズにしても、テキスト入力欄は、15 em 以下に縮小することはありません。 その場合、テキスト入力は、ウィンドウの端を超えて広がっているように描画されます。 以下の画像で、テキスト入力欄がウィンドウいっぱいに広がっている点に注意して下さい。
ボックス内の要素のまとめ方 (Packing)
子要素 2 つが置かれているボックスがあり、子要素はいずれも伸縮可能ではなく、ボックスは伸縮可能であるとします。 具体的には以下のようなものです。
<box flex="1"> <button label="Happy"/> <button label="Sad"/> </box>
ウィンドウのサイズを変更すると、ボックスはウィンドウのサイズに応じた大きさになります。 ボタンは伸縮可能ではないので、その幅は変わりません。 そのため、ボックス内部で増えたスペースが、ウィンドウの右の方に表示されます。 しかし、ここでは増えたスペースを左側に表示させて、ボタンをウィンドウ内で右寄せにしたかったとします。
これはボックス内にスペーサーを置くことで可能ですが、たくさん指定する必要がある場合は煩雑になります。 ボックスの追加属性
を使うことで、もっと簡単に指示することができます。 この属性は、ボックス内で子要素をまとめておく位置を指定します。 水平ボックスの場合、これは、子要素の水平方向の配置をコントロールします。 垂直ボックスの場合は、子要素の垂直方向の配置をコントロールします。 以下の値が指定可能です。pack
- start
- 子要素を、水平ボックスの場合左端に、垂直ボックスの場合上端に配置します。これがデフォルト値になります。
- center
- 子要素をボックスの中央に配置します。
- end
- 子要素を、水平ボックスの場合右端に、垂直ボックスの場合下端に配置します。
属性はまとめたい要素を含むボックスに設定するもので、まとめたい要素自身に設定するものではありません。pack
以前の例を変更して、次のように、要素を中央に置くことができます。
<box flex="1" pack="center"> <button label="Happy"/> <button label="Sad"/> </box>
今回の例は、ウィンドウのサイズが変更されると、ボタン自身で水平位置が中央になるように移動します。 この動きを前の例と比べてみてください。
ボックス内の要素のそろえ方 (Alignment)
上の Happy-Sad の例で、ウィンドウを水平方向にリサイズすると、ボックスの幅が変わります。 さらに、ウィンドウを垂直方向にリサイズした場合、ボタンの高さがそれに応じて変わることを確認できるはずです。 これは、デフォルトで、垂直方向に伸縮可能であることが設定されているためです。
この振る舞いは、
属性を使ってコントロールできます。 水平ボックスの場合、子要素の垂直方向の配置をコントロールします。 垂直ボックスの場合、子要素の水平方向の配置をコントロールします。 指定できる値は、align
に似ています。pack
- start
- 子要素を、水平ボックスの場合は上端に沿って、垂直ボックスの場合は左端に沿って配置します。
- center
- 子要素をボックスの中央に配置します。
- end
- 子要素を、水平ボックスの場合は下端に沿って、垂直ボックスの場合は右端に沿って配置します。
- baseline
- 子要素を、テキストの基準線にそって配置します。この値は水平ボックスのみ意味を持ちます。
- stretch
- 子要素をボックスのサイズに応じて伸張させます。この値がデフォルトです。これは伸縮可能な要素と似ていますが、伸縮する方向が異なります。
属性と同様に、pack
属性もそろえたい要素を含むボックスに設定するもので、そろえたい要素自身に設定するものではありません。align
例を示します。 下の最初のボックスは、デフォルトなので子要素を伸張させます。 2 番目のボックスは
属性が設定されているので、子要素は中央に置かれます。align
<?xml version="1.0"?> <?xml-stylesheet href="chrome://global/skin/" type="text/css"?> <window id="yesno" title="Question" orient="horizontal" xmlns="https://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <hbox> <button label="Yes"/> <button label="No"/> </hbox> <hbox align="center"> <button label="Maybe"/> <button label="Perhaps"/> </hbox> </window>
属性で指定する代わりに、スタイルプロパティ -moz-box-pack
と -moz-box-align
を使うこともできます。
テキストの切り取りとボタン
ボタンの最大幅以上の大きさのラベルをもつボタン要素を作ってしまう可能性があります。 通常は、その場合の動作としては、ボタンのサイズを大きくして解決します。 それ以外の方法として、ボタンなどのラベルを持った要素には、
と呼ばれる特別な属性があり、これを使うとテキストが大きくなりすぎた場合、その切り取り方を指定できます。crop
テキストが切り取られた場合、ボタンに、テキストが切り取られたことを示す省略符号 (...) が表示されます。 以下の 4 つの値が有効です。
- left
- テキストの左側が切り取られます。
- right
- テキストの右側が切り取られます。
- center
- テキストの両側が切り取られます。
- none
- テキストの切り取りは行われません。これがデフォルト値です。
この属性は、実際には、ダイアログが任意のサイズで使えるように設計されている場合にのみ役立ちます。
属性は crop
要素や、description
属性を伴う要素とともに使うことができます。 次の例は、この属性の使用例を示しています。label
<button label="Push Me Please!" crop="right" flex="1"/>
ウィンドウが小さくなった後、どのようにボタン上のテキストがその右側を切り取られたかを確認してください。 次は、ボックスモデルの要約といくつか付加的な詳細について説明します。