【Polymer 1.0】フレキシブルレイアウト
目次
- 概要
- iron-flex-layout コンポーネントを使用する
- HorizontalレイアウトとVerticalレイアウト
- 子エレメントのサイズをフレキシブルに制御する
- Cross-axisにエレメントを配置
- Main-axisにエレメントを配置
- 自身のエレメントの配置設定
- 折り返しレイアウト
- リバースレイアウト
- <body>をアプリケーション領域で満たす
- 汎用的なルール
概要
iron-flex-layoutコンポーネントはCSS flexible boxをシンプルに利用するための方法を提供します。このコンポーネントではFlexboxを利用するために2つの方法を提供します:
- CSSクラス: Flexboxを使用するためのCSSクラスを提供します。このCSSクラスはマークアップで直接指定します。
- カスタムCSS Mixin: Flexboxを使用するためのカスタムCSS Mixinを提供します。CSSルールの定義の中で、
@apply()
関数の引数にこのカスタムCSS Mixinを指定して利用します。
この2つの方法のどちらを利用するかは好みの問題です:
classe: ⇒ ソースコード
mixin: ⇒ ソースコード
iron-flex-layout コンポーネントを使用する
CSSクラスを使用する場合は、次のファイルをインポートします:
<link rel="import" href="bower_components/iron-flex-layout/classes/iron-flex-layout.html">
次はCSSクラスのシンプルな使用例です:
<div class="layout horizontal wrap">
このようにclass
には複数のCSSクラスを指定できます。指定するCSSクラスの順番は意識しないため、wrap horizontal layout
も同じ意味になります。
カスタムCSS Mixin を使用する場合は、次のファイルをインポートします:
<link rel="import" href="bower_components/iron-flex-layout/iron-flex-layout.html">
次はカスタムCSS Mixin のシンプルな使用例です (カスタムCSS Mixin の詳細はここを参照ください):
<dom-module id="mixin-simple-demo"> <style> .container { @apply(--layout-horizontal); @apply(--layout-wrap); } </style> <template> <div class="container"> ...
HorizontalレイアウトとVerticalレイアウト
次は最もシンプルな横方向と縦方向のレイアウトのサンプルです。
classes:
<div class="layout horizontal"> <div>One</div> <div>Two</div> <div>Three</div> </div> <div class="layout vertical"> <div>One</div> <div>Two</div> <div>Three</div> </div>
mixin:
<dom-module id="horizontal-and-vertical-demo"> <style> ... .container-horizontal { @apply(--layout-horizontal); } .container-vertical { @apply(--layout-vertical); } </style> <template> <div class="container-horizontal"> <div>One</div> <div>Two</div> <div>Three</div> </div> <div class="container-vertical"> <div>One</div> <div>Two</div> <div>Three</div> </div> ...
デフォルトで適用される幅と高さ
ここではまずHorizontalまたはVerticalレイアウトで、デフォルトで適用される幅と高さについて見ていきましょう。次のサンプルでは、<body>
に3つの<div>
がコンテナとして配置されています。
- 1つ目の
div
は子エレメントを1つ持ちます。 - 2つ目の
<div>
は子エレメントを持ちません。 - 3つ目の
<div>
は子エレメントを1つ持ち、また高さが指定されています。
<!doctype html> <html> <head> ... <style> html, body { height: 100%; } body { margin: 0; } .container { margin: 10px; padding: 5px; background-color: lightgray; } .item { background-color: white; margin: 5px; padding: 10px; } </style> </head> <body class="fullbleed layout vertical"> <!-- このコンテナは子エレメントを持つ --> <div class="layout vertical container"> <div class="item">One</div> </div> <!-- このコンテナは子エレメントを持たない --> <div class="layout vertical container"></div> <!-- このコンテナは子エレメント持ち、高さが指定されている --> <div class="layout vertical container" style="height: 150px;"> <div class="item">One</div> </div> </body> </html>
まず<div>
の幅ですが、3つとも親エレメント(ここでは<body>
)の幅の中で可能な範囲でストレッチされています。またブラウザをリサイズしても<div>
の幅は適切に追従します。
次に<div>
の高さですが、1つ目の<div>
は子エレメントの高さから計算して親である<div>
の高さが決定されています。2つ目の<div>
は子エレメントを持たないため、親である<div>
がペタンコになっています。3つ目の<div>
は指定された高さが適用されています。
レイアウトを行う際は次のことを頭に置いておくと良いでしょう:
- 幅が指定されないコンテナでは、親コンテナの中で可能な範囲で幅がストレッチされる。
- 高さが指定されないコンテナでは、子エレメントの高さを基準にしてコンテナの高さが決定される。
- 高さが指定されたコンテナでは、子エレメントの高さよりコンテナに指定された高さが優先される。
Main-axis と Cross-axis
コンテナは2つの軸を持っています。layout horizontal
やlayout vertical
がこれにあたります。これに対して
デフォルトでは、子エレメントのサイズはCross-axis方向へストレッチされます:
<div class="layout horizontal" style="height: 150px;"> <div>Stretch Fill</div> <div>Stretch Fill</div> </div> <div class="layout vertical" style="height: 150px;"> <div>Stretch Fill</div> <div>Stretch Fill</div> </div>
レイアウトを行う際は次のことを頭に置いておくと良いでしょう:
- Main-axisがHorizontalの場合、子エレメントは縦方向へストレッチします:
- Main-axisがVerticalの場合、子エレメントは横方向へストレッチします:
子エレメントのサイズをフレキシブルに制御する
コンテナの子エレメントは、
classes:
<div class="layout horizontal"> <div>One</div> <div class="flex">Two (flex)</div> <div>Three</div> </div>
mixin:
<dom-module id="horizontal-flex-demo"> <style> ... .container { @apply(--layout-horizontal); } .flexchild { @apply(--layout-flex); } </style> <template> <div class="container"> <div>One</div> <div class="flexchild">Two (flex)</div> <div>Three</div> </div> ...
Horizontalと同様にVerticalでもエレメントのサイズが柔軟に変化します。ただしVerticalレイアウトではコンテナのheight
に値を指定する必要あります。指定しない場合はレイアウトが崩れる場合があります:
classes:
<div class="layout vertical" style="height: 250px;"> <div>Alpha</div> <div class="flex">Beta (flex)</div> <div>Gamma</div> </div>
mixin:
<dom-module id="vertical-flex-demo"> <style> ... .container { @apply(--layout-vertical); } .flexchild { @apply(--layout-flex); } </style> <template> <div class="container" style="height: 250px;"> <div>One</div> <div class="flexchild">Two (flex)</div> <div>Three</div> </div> ...
次はheight
に値をしなかった場合にレイアウトが崩れた例です:
Note: ChromeでカスタムCSS Mixinを使用した場合にこのようなレイアウト崩れが起きました。CSSクラスを使用した場合はまた違う結果になります。またブラウザやそのバージョンによっても挙動が異なるようです。
子エレメントのサイズは割合を指定することができます。割合はflex-2
のように、数字の部分を2〜12の範囲で指定します (flex
は1) :
classes:
<div class="layout horizontal"> <div class="flex-2">Alpha</div> <div class="flex">Beta</div> <div class="flex-3">Gamma</div> </div>
mixin:
<dom-module id="horizontal-flex-ratio-demo"> <style> ... .container { @apply(--layout-horizontal); } .flexchild { @apply(--layout-flex); } .flex2child { @apply(--layout-flex-2); } .flex3child { @apply(--layout-flex-3); } </style> <template> <div class="container"> <div class="flex3child">One</div> <div class="flexchild">Two</div> <div class="flex2child">Three</div> </div> ...
ここではコンテナに子エレメントをフィットさせています。フィットさせるためには以下の性質を利用します:
- 幅のフィットは、
flex を指定することによって行う。 - 高さのフィットは、Main-axisがHorizontalの場合に子エレメントが縦方向へストレッチする性質を利用する (詳細は「Main-axis と Cross-axis」を参照ください) 。
classes:
<div class="layout horizontal" style="height: 150px;"> <div class="flex">Fit</div> </div>
mixin:
<dom-module id="horizontal-fit-demo"> <style> ... .container { @apply(--layout-horizontal); } .flexchild { @apply(--layout-flex); } </style> <template> <div class="container" style="height: 150px;"> <div class="flexchild">Fit</div> </div> ...
Cross-axisにエレメントを配置
ここではCross-axisにエレメントを配置する方法についてみていきます。
次のサンプルでは、Cross-axis (Vertical) のstart位置にエレメントを配置しています:
classes:
<div class="layout horizontal start" style="height: 150px;"> <div>start</div> <div>start</div> </div>
mixin:
<dom-module id="horizontal-start-demo"> <style> ... .container { @apply(--layout-horizontal); @apply(--layout-start); } </style> <template> <div class="container" style="height: 150px;"> <div>start</div> <div>start</div> </div> ...
次のサンプルでは、Cross-axis (Vertical) のcenter位置にエレメントを配置しています:
classes:
<div class="layout horizontal center" style="height: 150px;"> <div>center</div> <div>center</div> </div>
mixin:
<dom-module id="horizontal-center-demo"> <style> ... .container { @apply(--layout-horizontal); @apply(--layout-center); } </style> <template> <div class="container" style="height: 150px;"> <div>center</div> <div>center</div> </div> ...
次のサンプルでは、Cross-axis (Vertical) のend位置にエレメントを配置しています:
classes:
<div class="layout horizontal end" style="height: 150px;"> <div>end</div> <div>end</div> </div>
mixin:
<dom-module id="horizontal-end-demo"> <style> ... .container { @apply(--layout-horizontal); @apply(--layout-end); } </style> <template> <div class="container" style="height: 150px;"> <div>end</div> <div>end</div> </div> </template> ...
次のサンプルでは、上下左右中央にエレメントを配置しています:
classes:
<div class="layout horizontal center-center" style="height: 150px;"> <div>center-center</div> <div>center-center</div> </div>
mixin:
<dom-module id="horizontal-center-center-demo"> <style> ... .container { @apply(--layout-horizontal); @apply(--layout-center-center); } </style> <template> <div class="container" style="height: 150px;"> <div>center-center</div> <div>center-center</div> </div> </template> ...
Main-axisにエレメントを配置
ここではMain-axisにエレメントを配置する方法についてみていきます。
Note: ここでのサンプルでは、Main-axis (Horizontal) に子エレメントを配置する際、子エレメントが縦方向へストレッチしています。この理由については「Main-axis と Cross-axis」を参照ください) 。
次のサンプルでは、Main-axis (Horizontal) のstart位置に子エレメントを配置しています:
classes:
<div class="layout horizontal start-justified" style="height: 100px;"> <div>start-justified</div> </div>
mixin:
<dom-module id="horizontal-start-justified-demo"> <style> ... .container { @apply(--layout-horizontal); @apply(--layout-start-justified); } </style> <template> <div class="container" style="height: 100px;"> <div>start-justified</div> </div> </template> ...
次のサンプルでは、Main-axis (Horizontal) のcenter位置に子エレメントを配置しています:
classes:
<div class="layout horizontal center-justified" style="height: 100px;"> <div>center-justified</div> </div>
mixin:
<dom-module id="horizontal-center-justified-demo"> <style> ... .container { @apply(--layout-horizontal); @apply(--layout-center-justified); } </style> <template> <div class="container" style="height: 100px;"> <div>center-justified</div> </div> </template> ...
次のサンプルでは、Main-axis (Horizontal) のend位置に子エレメントを配置しています:
classes:
<div class="layout horizontal end-justified" style="height: 100px;"> <div>end-justified</div> </div>
mixin:
<dom-module id="horizontal-end-justified-demo"> <style> ... .container { @apply(--layout-horizontal); @apply(--layout-end-justified); } </style> <template> <div class="container" style="height: 100px;"> <div>end-justified</div> </div> </template> ...
次のサンプルでは、Main-axis (Horizontal) のエレメントとエレメント間のスペースが均等になります:
classes:
<div class="layout horizontal justified" style="height: 100px;"> <div>justified</div> <div>justified</div> <div>justified</div> </div>
mixin:
<dom-module id="horizontal-justified-demo"> <style> ... .container { @apply(--layout-horizontal); @apply(--layout-justified); } </style> <template> <div class="container" style="height: 100px;"> <div>justified</div> <div>justified</div> <div>justified</div> </div> </template> ...
次のサンプルでは、Main-axis (Horizontal) のエレメントの周りのスペースが均等になります:
classes:
<div class="layout horizontal around-justified" style="height: 100px;"> <div>around-justified</div> <div>around-justified</div> </div>
mixin:
<dom-module id="horizontal-around-justified-demo"> <style> ... .container { @apply(--layout-horizontal); @apply(--layout-around-justified); } </style> <template> <div class="container" style="height: 100px;"> <div>around-justified</div> <div>around-justified</div> </div> </template> ...
自身のエレメントの配置設定
「Cross-axisにエレメントを配置」ではコンテナにstart
やcenter
などを適用し、子エレメントの配置をしていました。ここでは子エレメントに直接self-start
やself-center
などを適用して子エレメントの配置を行います:
classes:
<div class="layout horizontal justified" style="height: 150px;"> <div class="flex self-start">Alpha</div> <div class="flex self-center">Beta</div> <div class="flex self-end">Gamma</div> <div class="flex self-stretch">Delta</div> </div>
mixin:
<dom-module id="horizontal-self-demo"> <style> ... .container { @apply(--layout-horizontal); @apply(--layout-justified); } .child1 { @apply(--layout-self-start); @apply(--layout-flex); } .child2 { @apply(--layout-self-center); @apply(--layout-flex); } .child3 { @apply(--layout-self-end); @apply(--layout-flex); } .child4 { @apply(--layout-self-stretch); @apply(--layout-flex); } </style> <template> <div class="container" style="height: 150px;"> <div class="child1">Alpha</div> <div class="child2">Beta</div> <div class="child3">Gamma</div> <div class="child4">Delta</div> </div> ...
折り返しレイアウト
ここでは収まりきらないエレメントを折り返します。
classes:
<div class="layout horizontal wrap" style="width: 250px;"> <div>Alpha</div> <div>Beta</div> <div>Gamma</div> <div>Delta</div> </div>
mixin:
<dom-module id="horizontal-wrap-demo"> <style> ... .container { @apply(--layout-horizontal); @apply(--layout-wrap); } </style> <template> <div class="container" style="width: 250px;"> <div>Alpha</div> <div>Beta</div> <div>Gamma</div> <div>Delta</div> </div> ...
リバースレイアウト
ここでは通常とは逆方向にエレメントを配置します。以下はそのクラスとMixinの一覧です:
クラス | Mixin |
---|---|
layout horizontal‑reverse | ‑‑layout-horizontal-reverse |
layout verical‑reverse | ‑‑layout-verical-reverse |
layout wrap‑reverse | ‑‑layout-wrap-reverse |
classes:
<div class="layout horizontal-reverse"> <div>Alpha</div> <div>Beta</div> <div>Gamma</div> <div>Delta</div> </div>
mixin:
<dom-module id="horizontal-reverse-demo"> <style> ... .container { @apply(--layout); @apply(--layout-horizontal-reverse); } </style> <template> <div class="container"> <div>Alpha</div> <div>Beta</div> <div>Gamma</div> <div>Delta</div> </div> ...
<body>をアプリケーション領域で満たす
多くのケースでは<body>
領域の全てをアプリケーションで利用したいといったことがほとんどでしょう。このような場合は次の項目を決まりごととして記述してください:
<body>
タグにfullbleed
、layout
、vertical
クラスを適用する。<body>
直下のアプリケーション領域となるエレメント (カスタムエレメント) にflex
クラスを適用する。
まず<body>
直下のアプリケーション領域を<div>
とした場合のサンプルです:
<!doctype html> <html> <head> <script src="bower_components/webcomponentsjs/webcomponents-lite.js"></script> <link rel="import" href="bower_components/iron-flex-layout/classes/iron-flex-layout.html"> ... <style> .my-app { background-color: greenyellow; } </style> </head> <body class="fullbleed layout vertical"> <div class="flex my-app">Fitting a fullbleed body.</div> </body> </html>
次は<body>
直下のアプリケーション領域をカスタムエレメント (my-app
) とした場合のサンプルです:
<dom-module id="my-app"> <style> :host { background-color: greenyellow; } </style> <template> Fitting a fullbleed body. </template> <script> Polymer({ is: 'my-app' }); </script> </dom-module>
<!doctype html> <html> <head> <script src="bower_components/webcomponentsjs/webcomponents-lite.js"></script> <link rel="import" href="bower_components/iron-flex-layout/classes/iron-flex-layout.html"> ... </head> <body class="fullbleed layout vertical"> <my-app class="flex"></my-app> </dom-module> </body>
どちらのサンプルもこの図のような結果になります:
汎用的なルール
次のような汎用的なルールも提供されます:
クラス | Mixin | 内容 |
---|---|---|
block | --layout-block | display: block |
invisible | --layout-invisible | visibility: hidden |
relative | --layout-relative | position: relative |
fit | --layout-fit | コンテナに子エレメントをフィットさせる |
Note:
fit
(--layout-fit
) を使用する場合は、祖先でエレメントのサイズが決められてかつposition: relative
の必要があります。
<div class="layout vertical"> <div>Before <span>[A Span]</span> After</div> <div>Before <span class="block">[A Block Span]</span> After</div> <div>Before <span class="invisible">[A Invisible Span]</span> After</div> <div class="relative" style="height: 100px;"> <div class="fit" style="background-color: black; color: white">Fit</div> </div> </div>