[Angular8]サイトを簡単スタイリング!Angular Flex-Layoutの使い方をまとめてみた
どうも!大阪オフィスの西村祐二です。
フッター、ヘッターのレイアウトなど、画面のスタイリングをする際に、CSSのFlexboxなどで記載していく人は多いのではないでしょうか。
AngularではCSSのFlexboxをCSSファイルに書かず、HTMLタグ(ディレクティブ)を設定するだけで、簡単にFlexboxを設定できるライブラリAngular Flex-Layoutが公式から提供されています。
<div fxLayout="row" fxLayoutAlign="space-between"> </div>
今回はそのAngular Flex-Layoutの使い方をまとめてみます。
目次
環境
Angular CLI: 8.3.14 Node: 10.15.1 OS: darwin x64 Angular: 8.2.12 ... animations, common, compiler, compiler-cli, core, forms ... language-service, platform-browser, platform-browser-dynamic ... router Package Version ----------------------------------------------------------- @angular-devkit/architect 0.803.14 @angular-devkit/build-angular 0.803.14 @angular-devkit/build-optimizer 0.803.14 @angular-devkit/build-webpack 0.803.14 @angular-devkit/core 8.3.14 @angular-devkit/schematics 8.3.14 @angular/cdk 8.2.3 @angular/cli 8.3.14 @angular/flex-layout 8.0.0-beta.27 @ngtools/webpack 8.3.14 @schematics/angular 8.3.14 @schematics/update 0.803.14 rxjs 6.4.0 typescript 3.5.3 webpack 4.39.2
試していく環境を準備
はじめに、CLIを使ってプロジェクトを作成します。
$ npm install -g @angular/cli $ ng new test-flex-layout --style scss --routing $ cd test-flex-layout
Angular Flex-Layoutをインストールして、プロジェクトに設定します。公式サイトを参考に設定します。
$ npm i -s @angular/flex-layout @angular/cdk
app.module.ts
にimportします。
import { FlexLayoutModule } from '@angular/flex-layout'; ... @NgModule({ ... imports: [ FlexLayoutModule ], ... });
Flexboxの設定があたっているかわかりやすいようにHTMLとCSSを設定していきます。
<div class="container"> <div class="item item1">1</div> <div class="item item2">2</div> <div class="item item3">3</div> <div class="item item4">4</div> <div class="item item5">5</div> </div>
$itemColors:( item1: red, item2: blue, item3: green, item4: pink, item5: slategray ); @each $item, $color in $itemColors { .#{$item} { background: $color; } } .item { width: 80px; height: 80px; } .container { width: 300px; height: 300px; color: #fff; background: #eee; }
設定ができたらローカル実行して画面を確認してみましょう。
$ ng serve -o
下記のような画面がでれば環境の設定は終了です。
早速試していく!
fxLayout 子要素の並ぶ向き
現状、子要素が縦に並んでいる状態です。子要素を横並びにします。
fxLayout
を指定するだけで、containerクラスがflex container
になります。
そうすることで、containerクラスの中の子要素が自動的にflex item
になってくれます。
fxLayout="row"
containerクラスのdivタグ内で子要素が横並びになります。
<div class="container" fxLayout="row"> <div class="item item1">1</div> <div class="item item2">2</div> <div class="item item3">3</div> <div class="item item4">4</div> <div class="item item5">5</div> </div>
画面はこんなかんじに子要素が横並びになります。
ちなみにflex item
になるのは、flex container
の直近の子要素だけであって、それ以下に階層がある場合は、flex item
にならないので注意ください。
設定をいじってどう画面が変化するか確認していきましょう。
fxLayout="column"
containerクラスのdivタグ内で子要素が縦並びになります。
fxLayout="column-reverse"
containerクラスのdivタグ内で逆順で子要素が縦並びになります。
fxLayout="row-reverse"
containerクラスのdivタグ内で逆順で子要素が横並びになります。
CSSとの対応表
Value | 対応するCSS |
---|---|
'' (default) | flex-direction: row |
row |
flex-direction: row |
row-reverse |
flex-direction: row-reverse |
column |
flex-direction: column |
column-reverse |
flex-direction: column-reverse |
要素の折返し
wrap
を追加するとcontainerクラスのdivからはみ出した要素を折返してくれます。
fxLayout="row wrap"
左から右に向かってスタートし折り返されます。
fxLayout="row-reverse wrap"
右から左に向かってスタートして折り返されます。
fxLayout="column wrap"
上から下に向かってスタートし、折り返されます。
fxLayout="column-reverse wrap"
下から上に向かってスタートし折り返されます。
CSSとの対応表
Value | 対応するCSS |
---|---|
wrap cloumn |
flex-flow: wrap cloumn |
row-reverse wrap |
flex-flow: row-reverse wrap |
column wrap |
flex-flow: column wrap |
column-reverse wrap |
flex-flow: column-reverse wrap |
inline-flex
inline-flex
を設定することも可能です。
fxLayout="row inline"
のように書くことでinline-flex
とすることができます。
fxLayoutAlign 要素の整列順
設定したflex-direction
の軸に対して子要素を左、右、中央揃えなど設定できます。
fxLayoutAlign
の第1引数にメインの軸(rowであればx軸、columnであればy軸)の設定、第2引数に別軸をプラスして設定(rowであればy軸、columnであればx軸)できます。
デフォルトではfxLayoutAlign="start"
が設定されています。
下記にいろんな設定を試した際の画面を載せていきます。
前提としてfxLayout="row wrap"
を設定しておきます。
fxLayoutAlign="center"
要素が中央揃えになります。
<div class="container" fxLayout="row wrap" fxLayoutAlign="center"> <div class="item item1">1</div> <div class="item item2">2</div> <div class="item item3">3</div> <div class="item item4">4</div> <div class="item item5">5</div> </div>
fxLayoutAlign="end"
要素が右揃えになります。
fxLayoutAlign="space-around"
要素を均等に配置し各要素の両側に半分の大きさの間隔を置いて配置されます。
fxLayoutAlign="space-between"
要素の余白が均等になるように配置されます。最初のアイテムは先頭に寄り、最後のアイテムは末尾に寄る形で配置されます。
fxLayoutAlign="space-evenly"
space-aroundと微妙な違いしかありませんが、 各要素を均等に配置し、各要素の周りに同じ大きさの間隔を置いて配置されます。
fxLayoutAlign="center center"
第2引数に値を指定するとCross Axis方向(rowの場合だとy軸方向)に対して配置します。
要素が中央に配置されます。
直近の子要素にのみ指定されるので、「1」を中央にしたいときは「1」を囲うタグに指定すると要素の中で中央に配置されます。
<div class="container" fxLayout="row wrap" fxLayoutAlign="center center"> <div class="item item1" fxLayoutAlign="center center">1</div> <div class="item item2">2</div> <div class="item item3">3</div> <div class="item item4">4</div> <div class="item item5">5</div> </div>
fxLayoutAlign="center start"
fxLayoutAlign="center end"
fxLayoutAlign="center space-around"
fxLayoutAlign="center space-between"
CSSの高さの指定をはずして、stretchの設定を味わう
下記のようにCSSのheight: 80px;
をコメントアウトします。
$itemColors:( item1: red, item2: blue, item3: green, item4: pink, item5: slategray ); @each $item, $color in $itemColors { .#{$item} { background: $color; } } .item { width: 80px; // height: 80px; } .container { width: 300px; height: 300px; color: #fff; background: #eee; }
- fxLayoutAlign="start"
<div class="container" fxLayout="row wrap" fxLayoutAlign="start"> <div class="item item1">1</div> <div class="item item2">2</div> <div class="item item3">3</div> <div class="item item4">4</div> <div class="item item5">5</div> </div>
デフォルトで、align-items: stretch; align-content: stretch
が設定されているので余白がなくなり引き伸ばされます。
- fxLayoutAlign="start start">
第2引数を設定するとstretch
から設定が変更されるので下記のような画面になります。
CSSとの対応表
- Main Axis
Value 対応するCSS (default)
justify-content: flex-start
start
orflex-start
justify-content: flex-start
center
justify-content: center
end
orflex-end
justify-content: flex-end
space-around
justify-content: space-around
space-between
justify-content: space-between
space-evenly
justify-content: space-evenly
- Cross Axis (optional)
Value 対応するCSS (default)
align-items: stretch; align-content: stretch
start
orflex-start
align-items: flex-start; align-content: flex-start
center
align-items: center; align-content: center
end
orflex-end
align-items: flex-end; align-content: flex-end
space-around
align-items: space-around; align-content: space-around
space-between
align-items: space-between; align-content: space-between
stretch
max-width: 100% if flex-direction: column; else max-height: 100%
baseline
align-items: baseline; align-content: stretch
fxLayoutGap 要素間のマージン設定
要素と要素の間にマージンを入れたいときはfxLayoutGap
を指定することで余白をいれることができます。
ただ、挙動としては下記のようになっていますので、使うときはココを頭にいれて設定するのが良いかと思います。
- flex-direction="row"のときはmargin-rightが設定される
-
flex-direction="column"のときはmargin-bottomが設定される
-
最後の要素にはマージンが設定されない
Grid Mode
CSS Grid Layoutの際はgrid
と指定することでマージンを設定できます。
<div fxLayoutGap="16px grid"> <div>Section 1</div> <div>Section 2</div> <div>Section 3</div> </div>
fxFlex 子要素(Flexアイテム)に指定するプロパティ
fxFlex="<grow> <shrink> <basis>"
という形で設定していきます。
- grow:余白ができたとき、どの要素をどれだけ広げるかの設定
- shrink:要素が溢れたとき、どの要素をどれだけ縮めるかの設定
- basis:計算するときの基準となる幅、高さの値。autoのときは要素の大きさになる
CSS対応表
alias | 対応するCSS |
---|---|
grow |
flex: 1 1 100% |
initial |
flex: 0 1 auto |
auto |
flex: <grow> <shrink> 100% |
none |
flex: 0 0 auto |
nogrow |
flex: 0 1 auto |
noshrink |
flex: 1 0 auto |
fxFlexOrder 要素の順番を入れ替える
要素の順番を入れ替えることができます。
デフォルトではorder: 0
が設定されいます。
ここでは「1」にfxFlexOrder="1"
とすることで、order: 1
が設定されて後ろに移動されます。
<div class="container" fxLayout="row wrap"> <div class="item item1" fxFlexOrder="1">1</div> <div class="item item2">2</div> <div class="item item3">3</div> <div class="item item4">4</div> <div class="item item5">5</div> </div>
CSS対応表
Value | 対応するCSS |
---|---|
(default) |
order: 0 |
<int> |
order: <int> |
fxFlexOffset 要素間のマージンを設定
fxFlexOffset
はfxLayoutGap
と逆の余白を設定できる機能をもっています。だだ、これはFlexアイテムにのみ指定することができます。
- flex-direction="row"のときはmargin-leftが設定される
-
flex-direction="column"のときはmargin-topが設定される
▼rowで「2」「5」にfxFlexOffset
を設定
<div class="container" fxLayout="row wrap"> <div class="item item1">1</div> <div class="item item2" fxFlexOffset="10px">2</div> <div class="item item3">3</div> <div class="item item4">4</div> <div class="item item5" fxFlexOffset="10px">5</div> </div>
▼columnで「2」「5」にfxFlexOffset
を設定
<div class="container" fxLayout="column wrap"> <div class="item item1">1</div> <div class="item item2" fxFlexOffset="10px">2</div> <div class="item item3">3</div> <div class="item item4">4</div> <div class="item item5" fxFlexOffset="10px">5</div> </div>
Value | 対応するCSS |
---|---|
(default) |
margin-left: 0% |
<int><suffix> |
margin-left: <int><suffix> |
fxFlexAlign 要素個別にCross Axis設定にする
この要素だけ、rowからcolumnに切り替えたいなど、Cross Axisに切り替えることができます。
下記設定では「5」だけがCross Axisのflex-endの設定になっています。
<div class="container" fxLayout="row wrap"> <div class="item item1">1</div> <div class="item item2">2</div> <div class="item item3">3</div> <div class="item item4">4</div> <div class="item item5" fxFlexAlign="end">5</div> </div>
Value | 対応するCSS |
---|---|
start |
align-self: flex-start |
center |
align-self: center |
end |
align-self: flex-end |
baseline |
align-self: baseline |
stretch |
align-self: stretch |
fxFlexFill, fxFill
cssファイルにwidthや、heightを設定していますが、fxFlexFill, fxFill
を設定することで、cssの設定が上書きされ下記のプロパティが設定されます。
Key | Value |
---|---|
margin |
0 |
width |
100% |
height |
100% |
min-width |
100% |
min-height |
100% |
下記よりはcontainerクラスの設定が上書きされていることがわかります。
<div class="container" fxLayout="row wrap" fxFlexFill> <div class="item item1">1</div> <div class="item item2">2</div> <div class="item item3">3</div> <div class="item item4">4</div> <div class="item item5">5</div> </div>
レスポンシブデザイン
下記表より、幅によってレイアウトを変更することができます。
[]
で囲うことで、条件式によって制御することもできます。
<api>.<breakpoint alias>="<value>" [<api>.<breakpoint alias>]="<expression>"
下のサンプルのように「1」がウインドウサイズが600px-959pxの間非表示、それ以外は表示ということも可能です。
fxHide
で要素を隠したり、fxShow
で表示したりすることができます。
<div class="container" fxLayout="row wrap"> <div class="item item1" fxShow fxHide.sm="true">1</div> <div class="item item2">2</div> <div class="item item3">3</div> <div class="item item4">4</div> <div class="item item5">5</div> </div>
breakpoint | mediaQuery |
---|---|
xs | 'screen and (max-width: 599px)' |
sm | 'screen and (min-width: 600px) and (max-width: 959px)' |
md | 'screen and (min-width: 960px) and (max-width: 1279px)' |
lg | 'screen and (min-width: 1280px) and (max-width: 1919px)' |
xl | 'screen and (min-width: 1920px) and (max-width: 5000px)' |
lt-sm | 'screen and (max-width: 599px)' |
lt-md | 'screen and (max-width: 959px)' |
lt-lg | 'screen and (max-width: 1279px)' |
lt-xl | 'screen and (max-width: 1919px)' |
gt-xs | 'screen and (min-width: 600px)' |
gt-sm | 'screen and (min-width: 960px)' |
gt-md | 'screen and (min-width: 1280px)' |
gt-lg | 'screen and (min-width: 1920px)' |
応用
ある程度使い方がわかってきたら、次は実際によく使いそうな場面を想定してみましょう。
3カラムのレイアウト
はじめは下記のようにスタイリングしておきます。CSSでは色だけつけています。
<div class="container" fxLayout> <div class="left">left</div> <div class="center">center</div> <div class="right">right</div> </div> <footer>footer</footer>
$itemColors:( center: red, left: skyblue, right: green ); @each $item, $color in $itemColors { .#{$item} { background: $color; } } header, footer { background: #eee; }
ここから、FlexLayoutを使って両端を100pxで固定しておいて、余った領域をcenterが専有する3カラムのレイアウトを作っていきます。
これはhtmlタグで完結できます。
両端固定なのでfxFlex="0 0 100px"
を設定し、centerは余った領域を使うので、fxFlex="grow"
とすることで3カラムを実現できます。
<header>header</header> <div class="container" fxLayout.="column"> <div class="left" fxFlex="0 0 100px">left</div> <div class="center" fxFlex="grow">center</div> <div class="right" fxFlex="0 0 100px">right</div> </div> <footer>footer</footer>
ヘッダーメニュー(ロゴだけ左端、メニューは右寄せ)
よくあるヘッダーメニューもhtmlタグで完結できます。
fxFlexOffset
でmargin-left
を指定できるので、右側に寄せたい要素で設定しauto
としてやることで右側によせることができます。
<header>header</header> <header> <div>Logo</div> <div fxFlexOffset="auto">Menu 1</div> <div>Menu 2</div> </header> <div class="container" fxLayout> <div class="left" fxFlex="0 0 100px">left</div> <div class="center" fxFlex="grow">center</div> <div class="right" fxFlex="0 0 100px">right</div> </div> <footer>footer</footer>
フッターを最下部に固定表示
コンテンツの高さが足りないときに、フッターの下にスペースができてしまうのを防ぎます。
全体をmainクラスのdivで囲いcolumnにします。containerクラスのdivが上下に伸縮してほしいので、fxFlex="grow"
を設定します。
<div class="main" fxLayout="column"> <header> <div>Logo</div> <div fxFlexOffset="auto">Menu 1</div> <div>Menu 2</div> </header> <div class="container" fxLayout="row" fxFlex="grow"> <div class="left" fxFlex="0 0 100px">left</div> <div class="center" fxFlex="grow">center</div> <div class="right" fxFlex="0 0 100px">right</div> </div> <footer>footer</footer> </div>
cssでmainクラスの高さを画面100%にしたいのでmin-height: 100vh;
を追加します。
// 下記を追加 .main { min-height: 100vh; }
bodyにデフォルトでついてるマージンとパディングを無効化しておきます。
body { margin: 0; padding: 0; }
これで下記のようにコンテンツの高さが足りなくてもフッターが最下部に固定で表示されます。
画像とテキストを互い違いに表示
LPサイトなどでよくある形のテキストと画像が入れ替わっているレイアウトも簡単に作れます。
下記の12,18,25行目fxLayoutAlign="start start"
は、デフォルト設定のstretch
で画像が引き伸ばされるのを防ぎます。
fxLayout="row-reverse"
で簡単に入れ替えることができます。
<div class="main" fxLayout="column"> <header> <div>Logo</div> <div fxFlexOffset="auto">Menu 1</div> <div>Menu 2</div> </header> <div class="container" fxLayout="row" fxFlex="grow"> <!-- left --> <div class="left" fxFlex="0 0 100px">left</div> <!-- center --> <div class="center" fxFlex="grow" fxLayout="column" fxLayoutGap="20px"> <div fxLayout="row" fxLayoutAlign="start start" fxLayoutGap="10px"> <img src="assets/mesoko_01.png" width="100px" /> <span> こんにちは、めそ子です。いつもは広報兼人事担当として、クラスメソッドをアピールするための活動をしていますが、今回は僭越ながら、少しだけ、私のことについてお話しさせてください。 </span> </div> <div fxLayout="row-reverse" fxLayoutAlign="start start" fxLayoutGap="10px"> <img src="assets/mesoko2nd.png" width="100px" /> <span> こんにちは、めそ子です。2017年6月より2代目めそ子として、広報兼人事担当のお仕事をしています。先輩から引き継いだ「めそ子通信」は今後私が執筆してゆきますので、どうぞよろしくお願いします。 </span> </div> <div fxLayout="row" fxLayoutAlign="start start" fxLayoutGap="10px"> <img src="assets/mesoko1709.png" width="100px" /> <span> こんにちは、めそ子です。昼間の雲は高い位置に浮かび、夜はずいぶん涼しくなって、すっかり秋めいてきましたね。まだサンダルを履いていたいところですが、そろそろ衣替えもしなくちゃです。 </span> </div> </div> <!-- right --> <div class="right" fxFlex="0 0 100px">right</div> </div> <footer>footer</footer> </div>
下記のような画面になります。
コードはすこし見通しが悪くなっていますが、実際はコンポーネントを分割してメンテナンスしやすくしておきましょう。
レスポンシブデザインに対応させてスマホ用とWeb用で表示を切り替える
600px以下になるとスマホ用のレイアウトになるように設定します。
スマホで使いやすいように、下部に固定でメニューを表示し、ヘッダーはメニュー部分を非表示にして、ロゴを中央に配置します。
また、コンテンツもrowからcolumnになるように設定し、コンテンツ=>left=>right=>footerの順番になるようにします。
スマホ用のメニューはfxHide.gt-xs="true"
とすることで、600px以上のときは非表示となるので、web用の大きさでは表示されません。
ngClass
にはxsなどのウインドウの大きさでクラスをつけたりはずしたりすることができます。今回は、600px以下になったら、mo-headerというクラスをつけるようにしています。ngClass.xs="mo-header"
<div class="main" fxLayout="column"> <header> <div ngClass.xs="mo-header" fxLayoutAlign.xs="center center">Logo</div> <div fxFlexOffset="auto" fxHide.xs="true">Menu 1</div> <div fxHide.xs="true">Menu 2</div> </header> <div class="mo-menu" fxLayout="row" fxLayoutAlign="space-around center" fxHide.gt-xs="true" fxFlexOrder="4"> <div>Menu 1</div> <div>Menu 2</div> </div> <div class="container" fxLayout fxLayout.xs="column" fxFlex="grow"> <!-- left --> <div class="left" fxFlex="0 0 100px" fxFlexOrder.xs="1">left</div> <!-- center --> <div class="center" fxFlex="grow" fxLayout="column" fxLayoutGap="20px"> <div fxLayout="row" fxLayoutAlign="start start" fxLayoutGap="10px"> <img src="assets/mesoko_01.png" width="100px" /> <span> こんにちは、めそ子です。いつもは広報兼人事担当として、クラスメソッドをアピールするための活動をしていますが、今回は僭越ながら、少しだけ、私のことについてお話しさせてください。 </span> </div> <div fxLayout="row-reverse" fxLayoutAlign="start start" fxLayoutGap="10px"> <img src="assets/mesoko2nd.png" width="100px" /> <span> こんにちは、めそ子です。2017年6月より2代目めそ子として、広報兼人事担当のお仕事をしています。先輩から引き継いだ「めそ子通信」は今後私が執筆してゆきますので、どうぞよろしくお願いします。 </span> </div> <div fxLayout="row" fxLayoutAlign="start start" fxLayoutGap="10px"> <img src="assets/mesoko1709.png" width="100px" /> <span> こんにちは、めそ子です。昼間の雲は高い位置に浮かび、夜はずいぶん涼しくなって、すっかり秋めいてきましたね。まだサンダルを履いていたいところですが、そろそろ衣替えもしなくちゃです。 </span> </div> </div> <!-- right --> <div class="right" fxFlex="0 0 100px" fxFlexOrder.xs="2">right</div> </div> <footer fxFlexOrder.xs="3">footer</footer> </div>
$itemColors:( center: pink, left: skyblue, right: green ); @each $item, $color in $itemColors { .#{$item} { background: $color; } } header, footer { background: #eee; } .main { min-height: 100vh; } .mo-menu { width: 100%; height: 50px; background: #eee; position: sticky; bottom: 0; } .mo-header { height: 50px; width: 100%; }
CSS Grid Layout
CSS FlexboxだけじゃなくCSS Grid Layoutにも対応しています。
Grid Directive | CSS Property(s) | Extra Inputs |
---|---|---|
gdAlignColumns |
align-content and align-items |
gdInline for inline-grid |
gdAlignRows |
justify-content and justify-items |
gdInline for inline-grid |
gdArea |
grid-area |
none |
gdAreas |
grid-areas |
gdInline for inline-grid |
gdAuto |
grid-auto-flow |
gdInline for inline-grid |
gdColumn |
grid-column |
none |
gdColumns |
grid-template-columns |
gdInline for inline-grid! at the end means grid-auto-columns |
gdGap |
grid-gap |
gdInline for inline-grid |
gdGridAlign |
justify-self and align-self |
none |
gdRow |
grid-row |
none |
gdRows |
grid-template-rows |
gdInline for inline-grid! at the end means grid-auto-rows |
下記のように親要素にディレクティブを指定すると利用することができるようです。
<div gdAuto> <div fxLayout="row"> <div fxFlex></div> </div> </div>
https://github.com/angular/flex-layout/blob/28bc2ae7476367f111edfce39a05b3f9041501f7/guides/Grid.md
さいごに
Angular Flex-Layoutの使い方をまとめてみました。
CSSファイルを行ったり来たりする必要がなく、簡単かつ、手軽にレイアウトの設定ができるので、かなり重宝しそうなライブラリです。
また、レイアウトに関する処理をHTML側によせることができるので、CSSのコード量を減らすことができるのも嬉しいポイントかなと思います。
誰かの参考になれば幸いです。